[PATCH v3 7/9] selinux: Implement Infiniband PKey "Access" access vector

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

Add a type and access vector for PKeys. Implement the ib_pkey_access
hook 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 

---
v2:
- Use void* blobs for security structs. Paul Moore
- Add pkey specific data to the audit log. Paul Moore
- Don't introduce a new initial sid, use unlabeled. Stephen Smalley

v3:
- Reorder parameters to pkey_access hook. Paul Moore

 include/linux/lsm_audit.h   |  7 +++
 security/lsm_audit.c| 13 
 security/selinux/hooks.c| 23 +
 security/selinux/include/classmap.h |  2 ++
 security/selinux/include/security.h |  2 ++
 security/selinux/ss/services.c  | 41 +
 6 files changed, 88 insertions(+)

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_OP11
+#define LSM_AUDIT_DATA_PKEY12
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/lsm_audit.c b/security/lsm_audit.c
index cccbf30..2546d82 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -397,6 +397,19 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_format(ab, " kmod=");
audit_log_untrustedstring(ab, a->u.kmod_name);
break;
+   case LSM_AUDIT_DATA_PKEY: {
+   struct in6_addr sbn_pfx;
+
+   memset(_pfx.s6_addr, 0,
+  sizeof(sbn_pfx.s6_addr));
+
+   memcpy(_pfx.s6_addr, >u.pkey->subnet_prefix,
+  sizeof(a->u.pkey->subnet_prefix));
+
+   audit_log_format(ab, " pkey=0x%x subnet_prefix=%pI6c",
+a->u.pkey->pkey, _pfx);
+   break;
+   }
} /* switch (a->type) */
 }
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ef1088c..101ea82 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5995,6 +5995,28 @@ static int selinux_key_getsecurity(struct key *key, char 
**_buffer)
 #endif
 
 #ifdef CONFIG_SECURITY_INFINIBAND
+static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 
pkey_val)
+{
+   struct common_audit_data ad;
+   int err;
+   u32 sid = 0;
+   struct ib_security_struct *sec = ib_sec;
+   struct lsm_pkey_audit pkey;
+
+   err = security_pkey_sid(subnet_prefix, pkey_val, );
+
+   if (err)
+   return err;
+
+   ad.type = LSM_AUDIT_DATA_PKEY;
+   pkey.subnet_prefix = subnet_prefix;
+   pkey.pkey = pkey_val;
+   ad.u.pkey = 
+   return avc_has_perm(sec->sid, sid,
+   SECCLASS_INFINIBAND_PKEY,
+   INFINIBAND_PKEY__ACCESS, );
+}
+
 static int selinux_ib_alloc_security(void **ib_sec)
 {
struct ib_security_struct *sec;
@@ -6196,6 +6218,7 @@ static struct security_hook_list selinux_hooks[] = {
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(ib_pkey_access, selinux_ib_pkey_access),
LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
 #endif
diff --git a/security/selinux/include/classmap.h 
b/security/selinux/include/classmap.h
index 1f1f4b2..d42dd4d 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -165,5 +165,7 @@ struct security_class_mapping secclass_map[] = {
  { COMMON_CAP_PERMS, NULL } },
{ "cap2_userns",
  { COMMON_CAP2_PERMS, NULL } },
+   { "infiniband_pkey",
+ { "access", NULL } },
{ NULL }
   };
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 

[PATCH v3 6/9] selinux: Allocate and free infiniband security hooks

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

Implement and attach hooks to allocate and free Infiniband object
security structures.

Signed-off-by: Daniel Jurgens 

---
v2:
- Use void * blobs for security structs.  Paul Moore
- Shorten ib_end_port to ib_port.  Paul Moore
- Allocate memory for security struct with GFP_KERNEL. Yuval Shaia

 security/selinux/hooks.c  | 25 -
 security/selinux/include/objsec.h |  5 +
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7c22703..ef1088c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -17,6 +17,7 @@
  * Paul Moore 
  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
  *Yuichi Nakamura 
+ *  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,
@@ -5991,7 +5992,26 @@ static int selinux_key_getsecurity(struct key *key, char 
**_buffer)
*_buffer = context;
return rc;
 }
+#endif
+
+#ifdef CONFIG_SECURITY_INFINIBAND
+static int selinux_ib_alloc_security(void **ib_sec)
+{
+   struct ib_security_struct *sec;
+
+   sec = kzalloc(sizeof(*sec), GFP_KERNEL);
+   if (!sec)
+   return -ENOMEM;
+   sec->sid = current_sid();
+
+   *ib_sec = sec;
+   return 0;
+}
 
+static void selinux_ib_free_security(void *ib_sec)
+{
+   kfree(ib_sec);
+}
 #endif
 
 static struct security_hook_list selinux_hooks[] = {
@@ -6175,7 +6195,10 @@ 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(ib_alloc_security, selinux_ib_alloc_security),
+   LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
+#endif
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
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 
+ *  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.8.3.1

___
Selinux mailing list
Selinux@tycho.nsa.gov
To unsubscribe, send email to selinux-le...@tycho.nsa.gov.
To get help, send an email containing "help" to selinux-requ...@tycho.nsa.gov.


[PATCH v3 9/9] selinux: Add a cache for quicker retreival of PKey SIDs

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

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  and Paul Moore
 (see security/selinux/netif.c and
security/selinux/netport.c for more information)

Signed-off-by: Daniel Jurgens 

---
v2:
- Renamed the files to ibpkey. Paul Moore
- Fixed a braket indentation mismatch in sel_pkey_find. Yuval Shaia
- Change spin_lock_bh to spin_lock_irqsave to resolve HARDIRQ lockdep
  warning.  Dan Jurgens

 security/selinux/Makefile |   2 +-
 security/selinux/hooks.c  |   4 +-
 security/selinux/ibpkey.c | 245 ++
 security/selinux/include/ibpkey.h |  31 +
 security/selinux/include/objsec.h |   6 +
 5 files changed, 286 insertions(+), 2 deletions(-)
 create mode 100644 security/selinux/ibpkey.c
 create mode 100644 security/selinux/include/ibpkey.h

diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 3411c33..ff5895e 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 ibpkey.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 5aa345f..a6088a1 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -90,6 +90,7 @@
 #include "netif.h"
 #include "netnode.h"
 #include "netport.h"
+#include "ibpkey.h"
 #include "xfrm.h"
 #include "netlabel.h"
 #include "audit.h"
@@ -167,6 +168,7 @@ static int selinux_cache_avc_callback(u32 event)
sel_netnode_flush();
sel_netport_flush();
synchronize_net();
+   sel_pkey_flush();
call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
}
return 0;
@@ -6003,7 +6005,7 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 
subnet_prefix, u16 pkey_val)
struct ib_security_struct *sec = ib_sec;
struct lsm_pkey_audit pkey;
 
-   err = security_pkey_sid(subnet_prefix, pkey_val, );
+   err = sel_pkey_sid(subnet_prefix, pkey_val, );
 
if (err)
return err;
diff --git a/security/selinux/ibpkey.c b/security/selinux/ibpkey.c
new file mode 100644
index 000..6e52c54
--- /dev/null
+++ b/security/selinux/ibpkey.c
@@ -0,0 +1,245 @@
+/*
+ * 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  and
+ * Paul Moore 
+ *   (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 
+#include 
+#include 
+#include 
+
+#include "ibpkey.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_find - Search for a pkey record
+ * @subnet_prefix: subnet_prefix
+ * @pkey_num: pkey_num
+ *
+ * Description:
+ * Search the pkey table and return the matching record.  If an entry
+ * can not be found in the table return NULL.
+ *
+ */
+static struct sel_pkey *sel_pkey_find(u64 subnet_prefix, u16 pkey_num)
+{
+

[PATCH v3 4/9] IB/core: Enforce security on management datagrams

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

During MAD and snoop agent registration for SMI QPs check that the
calling process has permission to access the manage the subnet  and
register a callback with the LSM to be notified of policy changes. When
notificaiton of a policy change occurs recheck permission and set a flag
indicating sending and receiving SMPs is allowed.

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 

---
v2:
- Squashed LSM hook additions. Paul Moore
- Changed security blobs to void*. Paul Moore
- Shorten end_port to port. Paul Moore
- Change "smp" to "manage_subnet". Paul Moore
- Use the LSM policy change notification and a flag to track permission
  instead of calling the LSM hook for every SMP. Dan Jurgens
- Squashed PKey and SMP enforcement into the same patch and moved the
  logic into security.c. Dan Jurgens

v3:
- ib_port -> ib_endport. Paul Moore
- Use notifier chains for LSM notification. Paul Moore
- Reorder LSM hook parameters to put sec first. Paul Moore

 drivers/infiniband/core/core_priv.h | 35 ++
 drivers/infiniband/core/mad.c   | 52 +
 drivers/infiniband/core/security.c  | 92 +
 include/linux/lsm_hooks.h   |  8 
 include/linux/security.h|  6 +++
 include/rdma/ib_mad.h   |  4 ++
 security/security.c |  8 
 7 files changed, 197 insertions(+), 8 deletions(-)

diff --git a/drivers/infiniband/core/core_priv.h 
b/drivers/infiniband/core/core_priv.h
index 68e3de0..2c35162 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -37,6 +37,8 @@
 #include 
 
 #include 
+#include 
+#include "mad_priv.h"
 
 struct pkey_index_qp_list {
struct list_headpkey_index_list;
@@ -166,6 +168,11 @@ int ib_get_cached_subnet_prefix(struct ib_device *device,
u64  *sn_pfx);
 
 #ifdef CONFIG_SECURITY_INFINIBAND
+int ib_security_pkey_access(struct ib_device *dev,
+   u8 port_num,
+   u16 pkey_index,
+   void *sec);
+
 void ib_security_destroy_port_pkey_list(struct ib_device *device);
 
 void ib_security_cache_change(struct ib_device *device,
@@ -183,7 +190,19 @@ void ib_destroy_qp_security_abort(struct ib_qp_security 
*sec);
 void ib_destroy_qp_security_end(struct ib_qp_security *sec);
 int ib_open_shared_qp_security(struct ib_qp *qp, struct ib_device *dev);
 void ib_close_shared_qp_security(struct ib_qp_security *sec);
+int ib_mad_agent_security_setup(struct ib_mad_agent *agent,
+   enum ib_qp_type qp_type);
+void ib_mad_agent_security_cleanup(struct ib_mad_agent *agent);
+int ib_mad_enforce_security(struct ib_mad_agent_private *map, u16 pkey_index);
 #else
+static inline int ib_security_pkey_access(struct ib_device *dev,
+ u8 port_num,
+ u16 pkey_index,
+ void *sec)
+{
+   return 0;
+}
+
 static inline void ib_security_destroy_port_pkey_list(struct ib_device *device)
 {
 }
@@ -232,5 +251,21 @@ static inline int ib_open_shared_qp_security(struct ib_qp 
*qp,
 static inline void ib_close_shared_qp_security(struct ib_qp_security *sec)
 {
 }
+
+static inline int ib_mad_agent_security_setup(struct ib_mad_agent *agent,
+ enum ib_qp_type qp_type)
+{
+   return 0;
+}
+
+static inline void ib_mad_agent_security_cleanup(struct ib_mad_agent *agent)
+{
+}
+
+static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
+ u16 pkey_index)
+{
+   return 0;
+}
 #endif
 #endif /* _CORE_PRIV_H */
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 2d49228..94ebc3e 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -40,9 +40,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "mad_priv.h"
+#include "core_priv.h"
 #include "mad_rmpp.h"
 #include "smi.h"
 #include "opa_smi.h"
@@ -367,6 +369,12 @@ struct ib_mad_agent *ib_register_mad_agent(struct 
ib_device *device,
atomic_set(_agent_priv->refcount, 1);
init_completion(_agent_priv->comp);
 
+   ret2 = ib_mad_agent_security_setup(_agent_priv->agent, qp_type);
+   if (ret2) {
+   ret = ERR_PTR(ret2);
+   

[PATCH v3 5/9] selinux: Create policydb version for Infiniband support

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 
Reviewed-by: Eli Cohen 

---
v2:
- Shorten ib_end_port to ib_port. Paul Moore
- Added bounds checking to port number. Paul Moore
- Eliminated {} in OCON_PKEY case statement.  Yuval Shaia

v3:
- ib_port -> ib_endport. Paul Moore

 security/selinux/include/security.h |   3 +-
 security/selinux/ss/policydb.c  | 130 +++-
 security/selinux/ss/policydb.h  |  27 +---
 3 files changed, 136 insertions(+), 24 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_INFINIBAND31
 
 /* 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..6056c2c 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,

[PATCH v3 2/9] IB/core: Enforce PKey security on QPs

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

Add new LSM hooks to allocate and free security contexts and check for
permission to access a PKey.

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,
or alternate path, check that the QP has permission for the PKey in the
PKey table 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 index a QP is using. After the reset to init
transition the user can modify the port, PKey index and alternate path
independently. So port and PKey settings changes can be a merge of the
previous settings and the new ones.

In order to maintain access control if there are PKey table or subnet
prefix change keep a list of all QPs are using each PKey index on
each port. If a change occurs all QPs using that device and port must
have access enforced for the new cache settings.

These changes add 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 established prior to the modify and removed if the
modify fails.

1. When a QP is modified to a particular Port, PKey index or alternate
   path insert that QP into the appropriate lists.

2. Check permission to access the new settings.

3. If step 2 grants access attempt to modify the QP.

4a. If steps 2 and 3 succeed remove any prior associations.

4b. If ether fails remove the new setting associations.

If a 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 make sure all the
QPs that share the real_qp have permission as well. If the QP that
owns a security structure is denied access the security structure is
marked as such and the QP is added to an error_list. Once the moving
the QP to error is complete the security structure mark is cleared.

Maintaining the lists correctly turns QP destroy into a transaction.
The hardware driver for the device frees the ib_qp structure, so while
the destroy is in progress the ib_qp pointer in the ib_qp_security
struct is undefined. When the destroy process begins the ib_qp_security
structure is marked as destroying. This prevents any action from being
taken on the QP pointer. After the QP is destroyed successfully it
could still listed on an error_list wait for it to be processed by that
flow before cleaning up the structure.

If the destroy fails the QPs port and PKey settings are reinserted into
the appropriate lists, the destroying flag is cleared, and access control
is enforced, in case there were any cache changes during the destroy
flow.

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

Signed-off-by: Daniel Jurgens 

---
v2:
- Squashed LSM hook additions. Paul Moore
- Changed security blobs to void*. Paul Moore

v3:
- Change parameter order of pkey_access hook. Paul Moore

 drivers/infiniband/core/Makefile |   3 +-
 drivers/infiniband/core/cache.c  |  21 +-
 drivers/infiniband/core/core_priv.h  |  77 +
 drivers/infiniband/core/device.c |  33 ++
 drivers/infiniband/core/security.c   | 617 +++
 drivers/infiniband/core/uverbs_cmd.c |  20 +-
 drivers/infiniband/core/verbs.c  |  27 +-
 include/linux/lsm_hooks.h|  27 ++
 include/linux/security.h |  21 ++
 include/rdma/ib_verbs.h  |  48 +++
 security/Kconfig |   9 +
 security/security.c  |  31 ++
 12 files changed, 925 insertions(+), 9 deletions(-)
 create mode 100644 drivers/infiniband/core/security.c

diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index edaae9f..da4e2c1 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -10,7 +10,8 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=   ib_uverbs.o 
ib_ucm.o \
 ib_core-y :=   packer.o ud_header.o verbs.o cq.o rw.o sysfs.o \
device.o fmr_pool.o cache.o netlink.o \
roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
-   multicast.o mad.o smi.o agent.o mad_rmpp.o
+   multicast.o mad.o smi.o agent.o mad_rmpp.o \
+   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/cache.c b/drivers/infiniband/core/cache.c
index 8a44894..ebe0337 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -53,6 +53,7 @@ struct ib_update_work {

[PATCH v3 3/9] selinux lsm IB/core: Implement LSM notification system

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

Add a generic notificaiton mechanism in the LSM. Interested consumers
can register a callback with the LSM and security modules can produce
events.

Because access to Infiniband QPs are enforced in the setup phase of a
connection security should be enforced again if the policy changes.
Register infiniband devices for policy change notification and check all
QPs on that device when the notification is received.

Add a call to the notification mechanism from SELinux when the AVC
cache changes or setenforce is cleared.

Signed-off-by: Daniel Jurgens 

---
v2:
- new patch that has the generic notification, replaces selinux and
  IB/core patches related to the ib_flush callback. Yuval Shaia and Paul
  Moore

v3:
- use notifier chains. Paul Moore

 drivers/infiniband/core/device.c | 53 
 include/linux/security.h |  8 ++
 security/security.c  | 20 +++
 security/selinux/hooks.c |  5 ++--
 security/selinux/selinuxfs.c |  2 ++
 5 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 5b42e83..7b6fd06 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -39,6 +39,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -82,6 +84,14 @@ static LIST_HEAD(client_list);
 static DEFINE_MUTEX(device_mutex);
 static DECLARE_RWSEM(lists_rwsem);
 
+static int ib_security_change(struct notifier_block *nb, unsigned long event,
+ void *lsm_data);
+static void ib_policy_change_task(struct work_struct *work);
+static DECLARE_WORK(ib_policy_change_work, ib_policy_change_task);
+
+static struct notifier_block ibdev_lsm_nb = {
+   .notifier_call = ib_security_change,
+};
 
 static int ib_device_check_mandatory(struct ib_device *device)
 {
@@ -344,6 +354,40 @@ static int setup_port_pkey_list(struct ib_device *device)
return 0;
 }
 
+static void ib_policy_change_task(struct work_struct *work)
+{
+   struct ib_device *dev;
+
+   down_read(_rwsem);
+   list_for_each_entry(dev, _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,
+ );
+
+   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(_rwsem);
+}
+
+static int ib_security_change(struct notifier_block *nb, unsigned long event,
+ void *lsm_data)
+{
+   if (event != LSM_POLICY_CHANGE)
+   return NOTIFY_DONE;
+
+   schedule_work(_policy_change_work);
+
+   return NOTIFY_OK;
+}
+
 /**
  * ib_register_device - Register an IB device with IB core
  * @device:Device to register
@@ -1075,10 +1119,18 @@ static int __init ib_core_init(void)
goto err_sa;
}
 
+   ret = register_lsm_notifier(_lsm_nb);
+   if (ret) {
+   pr_warn("Couldn't register LSM notifier. ret %d\n", ret);
+   goto err_ibnl_clients;
+   }
+
ib_cache_setup();
 
return 0;
 
+err_ibnl_clients:
+   ib_remove_ibnl_clients();
 err_sa:
ib_sa_cleanup();
 err_mad:
@@ -1098,6 +1150,7 @@ err:
 
 static void __exit ib_core_cleanup(void)
 {
+   unregister_lsm_notifier(_lsm_nb);
ib_cache_cleanup();
ib_remove_ibnl_clients();
ib_sa_cleanup();
diff --git a/include/linux/security.h b/include/linux/security.h
index 0bd8319..84abc05 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -69,6 +69,14 @@ struct audit_krule;
 struct user_namespace;
 struct timezone;
 
+enum lsm_event {
+   LSM_POLICY_CHANGE,
+};
+
+int call_lsm_notifier(enum lsm_event event, void *data);
+int register_lsm_notifier(struct notifier_block *nb);
+int unregister_lsm_notifier(struct notifier_block *nb);
+
 /* These functions are in security/commoncap.c */
 extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
   int cap, int audit);
diff --git a/security/security.c b/security/security.c
index 45b6dc0..8b8ddb2 100644
--- a/security/security.c
+++ b/security/security.c
@@ -33,6 +33,8 @@
 /* Maximum number of letters for an LSM name string */
 #define SECURITY_NAME_MAX  10
 
+static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
+
 /* Boot-time LSM user choice */
 static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY;
@@ -98,6 +100,24 @@ 

[PATCH v3 1/9] IB/core: IB cache enhancements to support Infiniband security

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

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.

Also removed an unneded pr_warn about memory allocation failure.

Signed-off-by: Daniel Jurgens 
Reviewed-by: Eli Cohen 
Reviewed-by: Leon Romanovsky 

---
v2:
- In ib_get_cached_subnet_prefix wait to initialize p until after
  validation.  Yuval Shaia

 drivers/infiniband/core/cache.c | 36 ++--
 drivers/infiniband/core/core_priv.h |  3 +++
 include/rdma/ib_verbs.h |  1 +
 3 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 0409667..8a44894 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -932,6 +932,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,
+   u8port_num,
+   u64  *sn_pfx)
+{
+   unsigned long flags;
+   int p;
+
+   if (port_num < rdma_start_port(device) ||
+   port_num > rdma_end_port(device))
+   return -EINVAL;
+
+   p = port_num - rdma_start_port(device);
+   read_lock_irqsave(>cache.lock, flags);
+   *sn_pfx = device->cache.subnet_prefix_cache[p];
+   read_unlock_irqrestore(>cache.lock, flags);
+
+   return 0;
+}
+EXPORT_SYMBOL(ib_get_cached_subnet_prefix);
+
 int ib_find_cached_pkey(struct ib_device *device,
u8port_num,
u16   pkey,
@@ -1108,6 +1128,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(>cache.lock);
 
kfree(gid_cache);
@@ -1166,9 +1188,18 @@ 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) {
-   pr_warn("Couldn't allocate cache for %s\n", device->name);
+   !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);
return -ENOMEM;
}
 
@@ -1211,6 +1242,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 19d499d..ce826e4 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -153,4 +153,7 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb,
 int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
 struct netlink_callback *cb);
 
+int ib_get_cached_subnet_prefix(struct ib_device *device,
+   u8port_num,
+   u64  *sn_pfx);
 #endif /* _CORE_PRIV_H */
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 156673a..205ea09 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1709,6 +1709,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.8.3.1

___
Selinux mailing list
Selinux@tycho.nsa.gov
To unsubscribe, send email to selinux-le...@tycho.nsa.gov.
To get help, send an email containing "help" to selinux-requ...@tycho.nsa.gov.


[PATCH v3 0/9] SELinux support for Infiniband RDMA

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens 

The selinux next tree is missing some patches for IB/core.  This series
applies cleanly to ib-next, and should apply cleanly to selinux-next once
the IB patches are merged.

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.

Every Infiniband fabric must have a subnet manager. The subnet manager
provisions the partitions and configures the end nodes. Each end port has
a PKey table containing 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 IB ports.

A PKey label consists of a subnet prefix and a range of PKey values and is
similar to the labeling mechanism for netports. Each Infiniband port can
reside on a different subnet, 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 port is labeled by name and port number. There is a single
access vector for IB ports called "manage_subnet".

Because RDMA allows kernel bypass, enforcement must be done during
connection setup. Communication 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 a generic notification callback mechanism
is added to the LSM. One callback is registered for checking the QP PKey
associations when the policy changes. Mad agents also register a callback,
they cache the permission to send and receive SMPs to avoid another per
packet call to the LSM.

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 which port, pkey index, and alternate path for every IB device.
This makes operations that used to be atomic transactional.

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
modification. 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 decive specific
driver (i.e. mlx4_ib) 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 is 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.

---
v2:
- Use void* blobs in the LSM hooks. Paul Moore
- Make the policy change callback generic. Yuval Shaia, Paul Moore
- Squash LSM changes into the patches where the calls are added. Paul Moore
- Don't add new initial SIDs. Stephen Smalley
- Squash MAD agent PKey and SMI patches. Dan Jurgens
- Changed ib_end_port to ib_port. Paul Moore
- Changed ib_port access vector from smp to manage_subnet. Paul Moore
- Added pkey and ib_port details to the audit log. Paul Moore
- See individual patches for more detail.

v3:
- ib_port -> ib_endport. Paul Moore
- use notifier chains for LSM notifications. Paul Moore
- reorder parameters 

Re: [PATCH] selinux-testsuite: Add test for execstack on thread stacks.

2016-07-29 Thread Paul Moore
On Fri, Jul 29, 2016 at 9:45 AM, Stephen Smalley  wrote:
> On 07/29/2016 09:39 AM, Paul Moore wrote:
>> On Thu, Jul 28, 2016 at 10:43 AM, Stephen Smalley  wrote:
>>> Test execstack permission checking for thread stacks.
>>> The test is conditional on Linux >= 4.7.
>>>
>>> Signed-off-by: Stephen Smalley 
>>> ---
>>> Revised to make it conditional on the kernel version in which
>>> the corresponding change was merged, so it passes on old and new kernels.
>>>
>>>  tests/mmap/Makefile|  2 ++
>>>  tests/mmap/mprotect_stack_thread.c | 58 
>>> ++
>>>  tests/mmap/test|  8 +-
>>>  3 files changed, 67 insertions(+), 1 deletion(-)
>>>  create mode 100644 tests/mmap/mprotect_stack_thread.c
>>
>> With v4.7 released, and the newly added conditionals, I see no reason
>> not to merge this patch (as well as the userns cap test) into the
>> master branch.  Can you think of any reason why not?
>
> No, that's why I re-spun these patches.  Should be good to go.  I
> force-pushed the updated patches to the branches, so they should be
> available to merge or cherry-pick there.

Okay, great.  Just a reminder, you've got write access to that repo,
and since you seem like a trustworthy guy I would say just go ahead a
do the merge yourself ;)

-- 
paul moore
security @ redhat
___
Selinux mailing list
Selinux@tycho.nsa.gov
To unsubscribe, send email to selinux-le...@tycho.nsa.gov.
To get help, send an email containing "help" to selinux-requ...@tycho.nsa.gov.


Re: [PATCH] selinux-testsuite: Add test for execstack on thread stacks.

2016-07-29 Thread Stephen Smalley
On 07/29/2016 09:39 AM, Paul Moore wrote:
> On Thu, Jul 28, 2016 at 10:43 AM, Stephen Smalley  wrote:
>> Test execstack permission checking for thread stacks.
>> The test is conditional on Linux >= 4.7.
>>
>> Signed-off-by: Stephen Smalley 
>> ---
>> Revised to make it conditional on the kernel version in which
>> the corresponding change was merged, so it passes on old and new kernels.
>>
>>  tests/mmap/Makefile|  2 ++
>>  tests/mmap/mprotect_stack_thread.c | 58 
>> ++
>>  tests/mmap/test|  8 +-
>>  3 files changed, 67 insertions(+), 1 deletion(-)
>>  create mode 100644 tests/mmap/mprotect_stack_thread.c
> 
> With v4.7 released, and the newly added conditionals, I see no reason
> not to merge this patch (as well as the userns cap test) into the
> master branch.  Can you think of any reason why not?

No, that's why I re-spun these patches.  Should be good to go.  I
force-pushed the updated patches to the branches, so they should be
available to merge or cherry-pick there.

> 
>> diff --git a/tests/mmap/Makefile b/tests/mmap/Makefile
>> index f2f486c..e330f3e 100644
>> --- a/tests/mmap/Makefile
>> +++ b/tests/mmap/Makefile
>> @@ -1,5 +1,7 @@
>>  TARGETS=$(patsubst %.c,%,$(wildcard *.c))
>>
>> +LDLIBS += -lpthread
>> +
>>  all: $(TARGETS)
>>
>>  clean:
>> diff --git a/tests/mmap/mprotect_stack_thread.c 
>> b/tests/mmap/mprotect_stack_thread.c
>> new file mode 100644
>> index 000..fed9969
>> --- /dev/null
>> +++ b/tests/mmap/mprotect_stack_thread.c
>> @@ -0,0 +1,58 @@
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +static void *test_thread(void *p)
>> +{
>> +   char buf[4096];
>> +   int rc;
>> +   void *ptr;
>> +   long pagesize = sysconf(_SC_PAGESIZE);
>> +
>> +   ptr = (void *) (((unsigned long) buf) & ~(pagesize - 1));
>> +
>> +   rc = mprotect(ptr, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC);
>> +   if (rc < 0) {
>> +   perror("mprotect");
>> +   exit(1);
>> +   }
>> +   return NULL;
>> +}
>> +
>> +int main(int argc, char **argv)
>> +{
>> +   struct utsname uts;
>> +   pthread_t thread;
>> +
>> +   if (argc != 2) {
>> +   fprintf(stderr, "usage: %s [pass|fail]\n", argv[0]);
>> +   exit(1);
>> +   }
>> +
>> +   if (strcmp(argv[1], "pass") && strcmp(argv[1], "fail")) {
>> +   fprintf(stderr, "usage: %s [pass|fail]\n", argv[0]);
>> +   exit(1);
>> +   }
>> +
>> +   if (uname() < 0) {
>> +   perror("uname");
>> +   exit(1);
>> +   }
>> +
>> +   if (!strcmp(argv[1], "fail") && strverscmp(uts.release, "4.7") < 0) {
>> +   printf("%s: Kernels < 4.7 do not check execstack on thread 
>> stacks, skipping.\n", argv[0]);
>> +   /* pass the test by failing as if it was denied */
>> +   exit(1);
>> +   }
>> +
>> +   pthread_create(, NULL, test_thread, NULL);
>> +   pthread_join(thread, NULL);
>> +   exit(0);
>> +}
>> +
>> diff --git a/tests/mmap/test b/tests/mmap/test
>> index 6b1de55..e1c2942 100755
>> --- a/tests/mmap/test
>> +++ b/tests/mmap/test
>> @@ -1,7 +1,7 @@
>>  #!/usr/bin/perl
>>
>>  use Test;
>> -BEGIN { plan tests => 30}
>> +BEGIN { plan tests => 32}
>>
>>  $basedir = $0;  $basedir =~ s|(.*)/[^/]*|$1|;
>>
>> @@ -68,6 +68,12 @@ ok($result, 0);
>>  $result = system "runcon -t test_execmem_t $basedir/mprotect_stack 2>&1";
>>  ok($result);
>>
>> +# Test success and failure for thread execstack, independent of execmem.
>> +$result = system "runcon -t test_execstack_t $basedir/mprotect_stack_thread 
>> pass";
>> +ok($result, 0);
>> +$result = system "runcon -t test_execmem_t $basedir/mprotect_stack_thread 
>> fail 2>&1";
>> +ok($result);
>> +
>>  # Test success and failure for file execute on mmap w/ file shared mapping.
>>  $result = system "runcon -t test_file_rwx_t $basedir/mmap_file_shared 
>> $basedir/temp_file";
>>  ok($result, 0);
>> --
>> 2.5.5
>>
> 
> 
> 

___
Selinux mailing list
Selinux@tycho.nsa.gov
To unsubscribe, send email to selinux-le...@tycho.nsa.gov.
To get help, send an email containing "help" to selinux-requ...@tycho.nsa.gov.


Re: [PATCH] selinux-testsuite: Add test for execstack on thread stacks.

2016-07-29 Thread Paul Moore
On Thu, Jul 28, 2016 at 10:43 AM, Stephen Smalley  wrote:
> Test execstack permission checking for thread stacks.
> The test is conditional on Linux >= 4.7.
>
> Signed-off-by: Stephen Smalley 
> ---
> Revised to make it conditional on the kernel version in which
> the corresponding change was merged, so it passes on old and new kernels.
>
>  tests/mmap/Makefile|  2 ++
>  tests/mmap/mprotect_stack_thread.c | 58 
> ++
>  tests/mmap/test|  8 +-
>  3 files changed, 67 insertions(+), 1 deletion(-)
>  create mode 100644 tests/mmap/mprotect_stack_thread.c

With v4.7 released, and the newly added conditionals, I see no reason
not to merge this patch (as well as the userns cap test) into the
master branch.  Can you think of any reason why not?

> diff --git a/tests/mmap/Makefile b/tests/mmap/Makefile
> index f2f486c..e330f3e 100644
> --- a/tests/mmap/Makefile
> +++ b/tests/mmap/Makefile
> @@ -1,5 +1,7 @@
>  TARGETS=$(patsubst %.c,%,$(wildcard *.c))
>
> +LDLIBS += -lpthread
> +
>  all: $(TARGETS)
>
>  clean:
> diff --git a/tests/mmap/mprotect_stack_thread.c 
> b/tests/mmap/mprotect_stack_thread.c
> new file mode 100644
> index 000..fed9969
> --- /dev/null
> +++ b/tests/mmap/mprotect_stack_thread.c
> @@ -0,0 +1,58 @@
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +static void *test_thread(void *p)
> +{
> +   char buf[4096];
> +   int rc;
> +   void *ptr;
> +   long pagesize = sysconf(_SC_PAGESIZE);
> +
> +   ptr = (void *) (((unsigned long) buf) & ~(pagesize - 1));
> +
> +   rc = mprotect(ptr, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC);
> +   if (rc < 0) {
> +   perror("mprotect");
> +   exit(1);
> +   }
> +   return NULL;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +   struct utsname uts;
> +   pthread_t thread;
> +
> +   if (argc != 2) {
> +   fprintf(stderr, "usage: %s [pass|fail]\n", argv[0]);
> +   exit(1);
> +   }
> +
> +   if (strcmp(argv[1], "pass") && strcmp(argv[1], "fail")) {
> +   fprintf(stderr, "usage: %s [pass|fail]\n", argv[0]);
> +   exit(1);
> +   }
> +
> +   if (uname() < 0) {
> +   perror("uname");
> +   exit(1);
> +   }
> +
> +   if (!strcmp(argv[1], "fail") && strverscmp(uts.release, "4.7") < 0) {
> +   printf("%s: Kernels < 4.7 do not check execstack on thread 
> stacks, skipping.\n", argv[0]);
> +   /* pass the test by failing as if it was denied */
> +   exit(1);
> +   }
> +
> +   pthread_create(, NULL, test_thread, NULL);
> +   pthread_join(thread, NULL);
> +   exit(0);
> +}
> +
> diff --git a/tests/mmap/test b/tests/mmap/test
> index 6b1de55..e1c2942 100755
> --- a/tests/mmap/test
> +++ b/tests/mmap/test
> @@ -1,7 +1,7 @@
>  #!/usr/bin/perl
>
>  use Test;
> -BEGIN { plan tests => 30}
> +BEGIN { plan tests => 32}
>
>  $basedir = $0;  $basedir =~ s|(.*)/[^/]*|$1|;
>
> @@ -68,6 +68,12 @@ ok($result, 0);
>  $result = system "runcon -t test_execmem_t $basedir/mprotect_stack 2>&1";
>  ok($result);
>
> +# Test success and failure for thread execstack, independent of execmem.
> +$result = system "runcon -t test_execstack_t $basedir/mprotect_stack_thread 
> pass";
> +ok($result, 0);
> +$result = system "runcon -t test_execmem_t $basedir/mprotect_stack_thread 
> fail 2>&1";
> +ok($result);
> +
>  # Test success and failure for file execute on mmap w/ file shared mapping.
>  $result = system "runcon -t test_file_rwx_t $basedir/mmap_file_shared 
> $basedir/temp_file";
>  ok($result, 0);
> --
> 2.5.5
>



-- 
paul moore
www.paul-moore.com
___
Selinux mailing list
Selinux@tycho.nsa.gov
To unsubscribe, send email to selinux-le...@tycho.nsa.gov.
To get help, send an email containing "help" to selinux-requ...@tycho.nsa.gov.