[PATCH v1 1/1] IB/core: Fix static analysis warning in ib_policy_change_task

2017-07-05 Thread Dan Jurgens
From: Daniel Jurgens 

ib_get_cached_subnet_prefix can technically fail, but the only way it
could is not possible based on the loop conditions. Check the return
value before using the variable sp to resolve a static analysis warning.

Fixes: 8f408ab64be6 ("selinux lsm IB/core: Implement LSM notification
system")
Signed-off-by: Daniel Jurgens 
Reported-by: Dan Carpenter 

-v1:
- Fix check to !ret. Paul Moore
---
 drivers/infiniband/core/device.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 631eaa9..a5dfab6 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -376,7 +376,8 @@ static void ib_policy_change_task(struct work_struct *work)
WARN_ONCE(ret,
  "ib_get_cached_subnet_prefix err: %d, this 
should never happen here\n",
  ret);
-   ib_security_cache_change(dev, i, sp);
+   if (!ret)
+   ib_security_cache_change(dev, i, sp);
}
}
up_read(_rwsem);
-- 
1.8.3.1



[PATCH] IB/core: Fix static analysis warning in ib_policy_change_task

2017-06-30 Thread Dan Jurgens
From: Daniel Jurgens 

ib_get_cached_subnet_prefix can technically fail, but the only way it
could is not possible based on the loop conditions. Check the return
value before using the variable sp to resolve a static analysis warning.

Fixes: 8f408ab64be6 ("selinux lsm IB/core: Implement LSM notification
system")
Signed-off-by: Daniel Jurgens 
Reported-by: Dan Carpenter 
---
 drivers/infiniband/core/device.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 631eaa9..dabd9f9 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -376,7 +376,8 @@ static void ib_policy_change_task(struct work_struct *work)
WARN_ONCE(ret,
  "ib_get_cached_subnet_prefix err: %d, this 
should never happen here\n",
  ret);
-   ib_security_cache_change(dev, i, sp);
+   if (ret)
+   ib_security_cache_change(dev, i, sp);
}
}
up_read(_rwsem);
-- 
1.8.3.1



[PATCH] IB/core: Fix uninitialized variable use in check_qp_port_pkey_settings

2017-06-30 Thread Dan Jurgens
From: Daniel Jurgens 

Check the return value from get_pkey_and_subnet_prefix to prevent using
uninitialized variables.

Fixes: d291f1a65232 ("IB/core: Enforce PKey security on QPs")
Signed-off-by: Daniel Jurgens 
Reported-by: Dan Carpenter 
---
 drivers/infiniband/core/security.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/infiniband/core/security.c 
b/drivers/infiniband/core/security.c
index 3e8c389..70ad19c 100644
--- a/drivers/infiniband/core/security.c
+++ b/drivers/infiniband/core/security.c
@@ -120,21 +120,25 @@ static int check_qp_port_pkey_settings(struct 
ib_ports_pkeys *pps,
return 0;
 
if (pps->main.state != IB_PORT_PKEY_NOT_VALID) {
-   get_pkey_and_subnet_prefix(>main,
-  ,
-  _prefix);
+   ret = get_pkey_and_subnet_prefix(>main,
+,
+_prefix);
+   if (ret)
+   return ret;
 
ret = enforce_qp_pkey_security(pkey,
   subnet_prefix,
   sec);
+   if (ret)
+   return ret;
}
-   if (ret)
-   return ret;
 
if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) {
-   get_pkey_and_subnet_prefix(>alt,
-  ,
-  _prefix);
+   ret = get_pkey_and_subnet_prefix(>alt,
+,
+_prefix);
+   if (ret)
+   return ret;
 
ret = enforce_qp_pkey_security(pkey,
   subnet_prefix,
-- 
1.8.3.1



[PATCH v2 1/2] selinux-testsuite: Infiniband pkey tests

2017-05-30 Thread Dan Jurgens
From: Daniel Jurgens 

New tests for infiniband pkeys. Most users don't have Infiniband
hardware, and if they do the pkey configuration is not standardized.
There is a configuration file for enabling the test and setting
environment specific test configurations. If the tests are disabled they
will always show as passed.

Signed-off-by: Daniel Jurgens 

---
v1:
- Synchronized interface names with refpolicy changes.
- Changed pkey test to not assume the default pkey is labeled, instead
it take a list of indexes with labeled and unlabeled pkeys.  It checks
that the labeled aren't allowed, unlabeled are allowed, and it labels
the unlabeled ones to make sure they aren't allowed when labeled.

v2:
Stephen Smalley:
- Ifdef around new corenet_ib* interfaces.
- Updated README with libibverbs-devel dependency.
- Ran new test program through astyle with recommended settings.
---
 README   |  12 ++-
 policy/Makefile  |   3 +-
 policy/test_ibpkey.te|  30 +++
 tests/Makefile   |   4 +-
 tests/infiniband_pkey/Makefile   |   7 ++
 tests/infiniband_pkey/create_modify_qp.c | 136 +++
 tests/infiniband_pkey/ibpkey_test.conf   |  18 
 tests/infiniband_pkey/test   |  84 +++
 8 files changed, 290 insertions(+), 4 deletions(-)
 create mode 100644 policy/test_ibpkey.te
 create mode 100644 tests/infiniband_pkey/Makefile
 create mode 100644 tests/infiniband_pkey/create_modify_qp.c
 create mode 100644 tests/infiniband_pkey/ibpkey_test.conf
 create mode 100644 tests/infiniband_pkey/test

diff --git a/README b/README
index deedae5..a4c8ebb 100644
--- a/README
+++ b/README
@@ -68,8 +68,9 @@ libselinux-devel # to build some of the test programs
 net-tools # for ifconfig, used by capable_net/test
 netlabel_tools # to load NetLabel configuration during inet_socket tests
 iptables # to load iptables SECMARK rules during inet_socket tests
+libibverbs-devel # to build ibpkey test program.
 
-yum install perl-Test perl-Test-Harness perl-Test-Simple selinux-policy-devel 
gcc libselinux-devel net-tools netlabel_tools iptables
+yum install perl-Test perl-Test-Harness perl-Test-Simple selinux-policy-devel 
gcc libselinux-devel net-tools netlabel_tools iptables libibverbs-devel
 
 The testsuite requires a pre-existing base policy configuration of
 SELinux, using either the old example policy or the reference policy
@@ -195,3 +196,12 @@ establish a base directory (based on the path of the script
 executable).  This won't always be accurate, but will work for this
 test harness/configuration.
$basedir = $0;  $basedir =~ s|(.*)/[^/]*|$1|;
+
+INFINIBAND TESTS
+
+Because running Infiniband tests requires specialized hardware you must
+set up a configuration file for these tests. The tests are disabled by
+default.  See comments in the configuration file for info.
+
+Infiniband PKey test conf file:
+tests/infiniband_pkey/ibpkey_test.conf
diff --git a/policy/Makefile b/policy/Makefile
index 7bc7f95..46c9fb5 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -22,7 +22,8 @@ TARGETS = \
test_task_create.te test_task_getpgid.te test_task_getsched.te \
test_task_getsid.te test_task_setpgid.te test_task_setsched.te \
test_transition.te test_inet_socket.te test_unix_socket.te \
-   test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te
+   test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te \
+   test_ibpkey.te
 
 ifeq ($(shell [ $(POL_VERS) -ge 24 ] && echo true),true)
 TARGETS += test_bounds.te
diff --git a/policy/test_ibpkey.te b/policy/test_ibpkey.te
new file mode 100644
index 000..373404c
--- /dev/null
+++ b/policy/test_ibpkey.te
@@ -0,0 +1,30 @@
+#
+#
+# Policy for testing Infiniband Pkey access.
+#
+
+attribute ibpkeydomain;
+
+# Domain for process.
+type test_ibpkey_access_t;
+domain_type(test_ibpkey_access_t)
+unconfined_runs_test(test_ibpkey_access_t)
+typeattribute test_ibpkey_access_t testdomain;
+typeattribute test_ibpkey_access_t ibpkeydomain;
+
+dev_rw_infiniband_dev(test_ibpkey_access_t)
+dev_rw_sysfs(test_ibpkey_access_t)
+
+# Define a pkey type for labeling pkeys during the test.
+type test_ibpkey_t;
+ifdef(`corenet_ib_pkey',`
+corenet_ib_pkey(test_ibpkey_t)
+')
+
+ifdef(`corenet_ib_access_unlabeled_pkeys',`
+corenet_ib_access_unlabeled_pkeys(test_ibpkey_access_t)
+')
+
+# Allow all of these domains to be entered from the sysadm domain.
+miscfiles_domain_entry_test_files(ibpkeydomain)
+userdom_sysadm_entry_spec_domtrans_to(ibpkeydomain)
diff --git a/tests/Makefile b/tests/Makefile
index fb8a0aa..7dfe2a8 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -4,13 +4,13 @@ export CFLAGS+=-g -O0 -Wall -D_GNU_SOURCE
 
 DISTRO=$(shell ./os_detect)
 
-SUBDIRS:=domain_trans entrypoint execshare exectrace execute_no_trans \

[PATCH v2 2/2] selinux-testsuite: Infiniband endport tests

2017-05-30 Thread Dan Jurgens
From: Daniel Jurgens 

New tests for Infiniband endports. Most users do not have infiniband
hardware, and if they do the device names can vary.  There is a
configuration file for enabling the tests and setting environment
specific configurations.  If the tests are disabled they always show as
passed.

A special test application was unnecessary, a standard diagnostic
application is used instead.  This required a change to the make file
to avoid trying to build an application in the new subdir.

Signed-off-by: Daniel Jurgens 

---
v1:
- Synchronize interface names with refpolicy changes.
- Allowed access to unlabeled pkeys vs default pkey, default pkey is no
longer labeled in the refpolicy.

v2:
Stephen Smalley:
- Use a stub makefile instead of a SUBDIRS_NO_MAKE directive.
- Use ifdefs around corenet_ib* interfaces.
- Only build the test_ibpendport.te file if the infiniband_endport class
is available.
- use corecmd_bin_entry_type intefrace instead of allow ... bin_t:
---
 README   |  7 +++-
 policy/Makefile  |  4 +++
 policy/test_ibendport.te | 40 +++
 tests/Makefile   |  2 +-
 tests/infiniband_endport/Makefile|  2 ++
 tests/infiniband_endport/ibendport_test.conf | 14 
 tests/infiniband_endport/test| 49 
 tests/infiniband_pkey/test   |  0
 8 files changed, 116 insertions(+), 2 deletions(-)
 create mode 100644 policy/test_ibendport.te
 create mode 100644 tests/infiniband_endport/Makefile
 create mode 100644 tests/infiniband_endport/ibendport_test.conf
 create mode 100755 tests/infiniband_endport/test
 mode change 100644 => 100755 tests/infiniband_pkey/test

diff --git a/README b/README
index a4c8ebb..de50eb4 100644
--- a/README
+++ b/README
@@ -201,7 +201,12 @@ INFINIBAND TESTS
 
 Because running Infiniband tests requires specialized hardware you must
 set up a configuration file for these tests. The tests are disabled by
-default.  See comments in the configuration file for info.
+default.  See comments in the configuration file for info. The endport
+tests use smpquery, for Fedora it's provided by the infiniband-diags
+package.
 
 Infiniband PKey test conf file:
 tests/infiniband_pkey/ibpkey_test.conf
+
+Infiniband Endport test conf file:
+tests/infiniband_endport/ibendport_test.conf
diff --git a/policy/Makefile b/policy/Makefile
index 46c9fb5..c062009 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -49,6 +49,10 @@ ifeq ($(shell grep -q getrlimit 
$(POLDEV)/include/support/all_perms.spt && echo
 TARGETS += test_prlimit.te
 endif
 
+ifeq ($(shell grep -q infiniband_endport 
$(POLDEV)/include/support/all_perms.spt && echo true),true)
+TARGETS += test_ibendport.te
+endif
+
 ifeq ($(shell grep -q all_file_perms.*map 
$(POLDEV)/include/support/all_perms.spt && echo true),true)
 export M4PARAM = -Dmap_permission_defined
 endif
diff --git a/policy/test_ibendport.te b/policy/test_ibendport.te
new file mode 100644
index 000..2a02c57
--- /dev/null
+++ b/policy/test_ibendport.te
@@ -0,0 +1,40 @@
+#
+#
+# Policy for testing Infiniband Pkey access.
+#
+
+gen_require(`
+   type bin_t;
+   type infiniband_mgmt_device_t;
+')
+
+attribute ibendportdomain;
+
+# Domain for process.
+type test_ibendport_manage_subnet_t;
+domain_type(test_ibendport_manage_subnet_t)
+unconfined_runs_test(test_ibendport_manage_subnet_t)
+typeattribute test_ibendport_manage_subnet_t testdomain;
+typeattribute test_ibendport_manage_subnet_t ibendportdomain;
+
+type test_ibendport_t;
+ifdef(`corenet_ib_endport',`
+corenet_ib_endport(test_ibendport_t)
+')
+
+dev_rw_infiniband_dev(test_ibendport_manage_subnet_t)
+dev_rw_sysfs(test_ibendport_manage_subnet_t)
+
+corecmd_bin_entry_type(test_ibendport_manage_subnet_t)
+
+allow test_ibendport_manage_subnet_t infiniband_mgmt_device_t:chr_file { read 
write open ioctl};
+
+ifdef(`corenet_ib_access_unlabeled_pkeys',`
+corenet_ib_access_unlabeled_pkeys(test_ibendport_manage_subnet_t)
+')
+
+allow test_ibendport_manage_subnet_t test_ibendport_t:infiniband_endport 
manage_subnet;
+
+# Allow all of these domains to be entered from the sysadm domain.
+miscfiles_domain_entry_test_files(ibendportdomain)
+userdom_sysadm_entry_spec_domtrans_to(ibendportdomain)
diff --git a/tests/Makefile b/tests/Makefile
index 7dfe2a8..369b678 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -10,7 +10,7 @@ SUBDIRS:= domain_trans entrypoint execshare exectrace 
execute_no_trans \
task_setnice task_setscheduler task_getscheduler task_getsid \
task_getpgid task_setpgid file ioctl capable_file capable_net \
capable_sys dyntrans dyntrace bounds nnp mmap unix_socket inet_socket \
-   overlay checkreqprot mqueue mac_admin infiniband_pkey
+   overlay checkreqprot mqueue mac_admin 

[PATCH v2 0/2] Selinux tests for Infinfiband

2017-05-30 Thread Dan Jurgens
From: Daniel Jurgens 

Implements new tests for Infiniband pkeys and endports. Because infiniband
isn't widely used, and when it is the configuration is site specific,
configuration files are used to enable the tests and set environment
specific settings. When the tests are disable they always show as passed.

If enabled, the tests require correstponding updates to selinux, refpolicy,
and the linux kernel.

---

v1:
- Synchronize intefrace names with changes to refpolicy.
- Change tests to not assume that default pkey is labeled.
- See patches v1 notes for more detail.

v2:
- Use ifdefs around new corenet_ib* interfaces.
- Exclude endport policy if infiniband_endport class is undefined.
- Use a stub makefile in tests/infinband_endport vs a new SUBDIRS_NO_MAKE
  list in the makefile.
- Style cleanup in new pkey test program.
- Updated README for new dependency.

Daniel Jurgens (2):
  selinux-testsuite: Infiniband pkey tests
  selinux-testsuite: Infiniband endport tests

 README   |  17 +++-
 policy/Makefile  |   7 +-
 policy/test_ibendport.te |  40 
 policy/test_ibpkey.te|  30 ++
 tests/Makefile   |   4 +-
 tests/infiniband_endport/Makefile|   2 +
 tests/infiniband_endport/ibendport_test.conf |  14 +++
 tests/infiniband_endport/test|  49 ++
 tests/infiniband_pkey/Makefile   |   7 ++
 tests/infiniband_pkey/create_modify_qp.c | 136 +++
 tests/infiniband_pkey/ibpkey_test.conf   |  18 
 tests/infiniband_pkey/test   |  84 +
 12 files changed, 404 insertions(+), 4 deletions(-)
 create mode 100644 policy/test_ibendport.te
 create mode 100644 policy/test_ibpkey.te
 create mode 100644 tests/infiniband_endport/Makefile
 create mode 100644 tests/infiniband_endport/ibendport_test.conf
 create mode 100755 tests/infiniband_endport/test
 create mode 100644 tests/infiniband_pkey/Makefile
 create mode 100644 tests/infiniband_pkey/create_modify_qp.c
 create mode 100644 tests/infiniband_pkey/ibpkey_test.conf
 create mode 100755 tests/infiniband_pkey/test

-- 
2.12.2



[PATCH 1/1] semanage: Fix manpage author for ibpkey and ibendport pages.

2017-05-30 Thread Dan Jurgens
From: Daniel Jurgens 

Signed-off-by: Daniel Jurgens 
---
 python/semanage/semanage-ibendport.8 | 2 +-
 python/semanage/semanage-ibpkey.8| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/python/semanage/semanage-ibendport.8 
b/python/semanage/semanage-ibendport.8
index c3753a27..0a29eae1 100644
--- a/python/semanage/semanage-ibendport.8
+++ b/python/semanage/semanage-ibendport.8
@@ -63,4 +63,4 @@ Label mlx4_0 port 2.
 .BR semanage (8)
 
 .SH "AUTHOR"
-This man page was written by Daniel Walsh 
+This man page was written by Daniel Jurgens 
diff --git a/python/semanage/semanage-ibpkey.8 
b/python/semanage/semanage-ibpkey.8
index 2da4f546..51f455ab 100644
--- a/python/semanage/semanage-ibpkey.8
+++ b/python/semanage/semanage-ibpkey.8
@@ -63,4 +63,4 @@ Label pkey 0x8FFF (limited membership default pkey) as a 
default pkey type
 .BR semanage (8)
 
 .SH "AUTHOR"
-This man page was written by Daniel Walsh 
+This man page was written by Daniel Jurgens 
-- 
2.12.2



[PATCH v1 2/2] selinux-testsuite: Infiniband endport tests

2017-05-24 Thread Dan Jurgens
From: Daniel Jurgens 

New tests for Infiniband endports. Most users do not have infiniband
hardware, and if they do the device names can vary.  There is a
configuration file for enabling the tests and setting environment
specific configurations.  If the tests are disabled they always show as
passed.

A special test application was unnecessary, a standard diagnostic
application is used instead.  This required a change to the make file
to avoid trying to build an application in the new subdir.

Signed-off-by: Daniel Jurgens 

---
v1:
- Synchronize interface names with refpolicy changes.
- Allowed access to unlabeled pkeys vs default pkey, default pkey is no
longer labeled in the refpolicy.
---
 README   |  7 +++-
 policy/Makefile  |  2 +-
 policy/test_ibendport.te | 35 
 tests/Makefile   |  4 ++-
 tests/infiniband_endport/ibendport_test.conf | 14 
 tests/infiniband_endport/test| 49 
 6 files changed, 108 insertions(+), 3 deletions(-)
 create mode 100644 policy/test_ibendport.te
 create mode 100644 tests/infiniband_endport/ibendport_test.conf
 create mode 100644 tests/infiniband_endport/test

diff --git a/README b/README
index b64e2de..8e1b391 100644
--- a/README
+++ b/README
@@ -200,7 +200,12 @@ INFINIBAND TESTS
 
 Because running Infiniband tests requires specialized hardware you must
 set up a configuration file for these tests. The tests are disabled by
-default.  See comments in the configuration file for info.
+default.  See comments in the configuration file for info. The endport
+tests use smpquery, for Fedora it's provided by the infiniband-diags
+package.
 
 Infiniband PKey test conf file:
 tests/infiniband_pkey/ibpkey_test.conf
+
+Infiniband Endport test conf file:
+tests/infiniband_endport/ibendport_test.conf
diff --git a/policy/Makefile b/policy/Makefile
index 46c9fb5..694836b 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -23,7 +23,7 @@ TARGETS = \
test_task_getsid.te test_task_setpgid.te test_task_setsched.te \
test_transition.te test_inet_socket.te test_unix_socket.te \
test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te \
-   test_ibpkey.te
+   test_ibpkey.te test_ibendport.te
 
 ifeq ($(shell [ $(POL_VERS) -ge 24 ] && echo true),true)
 TARGETS += test_bounds.te
diff --git a/policy/test_ibendport.te b/policy/test_ibendport.te
new file mode 100644
index 000..8387432
--- /dev/null
+++ b/policy/test_ibendport.te
@@ -0,0 +1,35 @@
+#
+#
+# Policy for testing Infiniband Pkey access.
+#
+
+gen_require(`
+   type bin_t;
+   type infiniband_mgmt_device_t;
+')
+
+attribute ibendportdomain;
+
+# Domain for process.
+type test_ibendport_manage_subnet_t;
+domain_type(test_ibendport_manage_subnet_t)
+unconfined_runs_test(test_ibendport_manage_subnet_t)
+typeattribute test_ibendport_manage_subnet_t testdomain;
+typeattribute test_ibendport_manage_subnet_t ibendportdomain;
+
+type test_ibendport_t;
+corenet_ib_endport(test_ibendport_t)
+
+dev_rw_infiniband_dev(test_ibendport_manage_subnet_t)
+dev_rw_sysfs(test_ibendport_manage_subnet_t)
+
+allow test_ibendport_manage_subnet_t bin_t:file entrypoint;
+allow test_ibendport_manage_subnet_t bin_t:file execute;
+allow test_ibendport_manage_subnet_t infiniband_mgmt_device_t:chr_file { read 
write open ioctl};
+corenet_ib_access_unlabeled_pkeys(test_ibendport_manage_subnet_t)
+
+allow test_ibendport_manage_subnet_t test_ibendport_t:infiniband_endport 
manage_subnet;
+
+# Allow all of these domains to be entered from the sysadm domain.
+miscfiles_domain_entry_test_files(ibendportdomain)
+userdom_sysadm_entry_spec_domtrans_to(ibendportdomain)
diff --git a/tests/Makefile b/tests/Makefile
index 7dfe2a8..63e6f57 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -12,6 +12,8 @@ SUBDIRS:= domain_trans entrypoint execshare exectrace 
execute_no_trans \
capable_sys dyntrans dyntrace bounds nnp mmap unix_socket inet_socket \
overlay checkreqprot mqueue mac_admin infiniband_pkey
 
+SUBDIRS_NO_MAKE:= infiniband_endport
+
 ifeq ($(shell grep -q cap_userns $(POLDEV)/include/support/all_perms.spt && 
echo true),true)
 ifneq ($(shell ./kvercmp $$(uname -r) 4.7),-1)
 SUBDIRS += cap_userns
@@ -56,7 +58,7 @@ all:
 
 test: all
chcon -R -t test_file_t .
-   @SUBDIRS="$(SUBDIRS)" PATH=/usr/bin:/bin:/usr/sbin:/sbin ./runtests.pl
+   @SUBDIRS="$(SUBDIRS) $(SUBDIRS_NO_MAKE)" 
PATH=/usr/bin:/bin:/usr/sbin:/sbin ./runtests.pl
 
 clean:
@for subdir in $(SUBDIRS); do \
diff --git a/tests/infiniband_endport/ibendport_test.conf 
b/tests/infiniband_endport/ibendport_test.conf
new file mode 100644
index 000..601b290
--- /dev/null
+++ b/tests/infiniband_endport/ibendport_test.conf
@@ -0,0 +1,14 @@
+# Enable(1)/Disable 

[PATCH v1 1/2] selinux-testsuite: Infiniband pkey tests

2017-05-24 Thread Dan Jurgens
From: Daniel Jurgens 

New tests for infiniband pkeys. Most users don't have Infiniband
hardware, and if they do the pkey configuration is not standardized.
There is a configuration file for enabling the test and setting
environment specific test configurations. If the tests are disabled they
will always show as passed.

Signed-off-by: Daniel Jurgens 

---
v1:
- Synchronized interface names with refpolicy changes.
- Changed pkey test to not assume the default pkey is labeled, instead
it take a list of indexes with labeled and unlabeled pkeys.  It checks
that the labeled aren't allowed, unlabeled are allowed, and it labels
the unlabeled ones to make sure they aren't allowed when labeled.
---
 README   |   9 ++
 policy/Makefile  |   3 +-
 policy/test_ibpkey.te|  25 ++
 tests/Makefile   |   4 +-
 tests/infiniband_pkey/Makefile   |   7 ++
 tests/infiniband_pkey/create_modify_qp.c | 144 +++
 tests/infiniband_pkey/ibpkey_test.conf   |  18 
 tests/infiniband_pkey/test   |  84 ++
 8 files changed, 291 insertions(+), 3 deletions(-)
 create mode 100644 policy/test_ibpkey.te
 create mode 100644 tests/infiniband_pkey/Makefile
 create mode 100644 tests/infiniband_pkey/create_modify_qp.c
 create mode 100644 tests/infiniband_pkey/ibpkey_test.conf
 create mode 100755 tests/infiniband_pkey/test

diff --git a/README b/README
index deedae5..b64e2de 100644
--- a/README
+++ b/README
@@ -195,3 +195,12 @@ establish a base directory (based on the path of the script
 executable).  This won't always be accurate, but will work for this
 test harness/configuration.
$basedir = $0;  $basedir =~ s|(.*)/[^/]*|$1|;
+
+INFINIBAND TESTS
+
+Because running Infiniband tests requires specialized hardware you must
+set up a configuration file for these tests. The tests are disabled by
+default.  See comments in the configuration file for info.
+
+Infiniband PKey test conf file:
+tests/infiniband_pkey/ibpkey_test.conf
diff --git a/policy/Makefile b/policy/Makefile
index 7bc7f95..46c9fb5 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -22,7 +22,8 @@ TARGETS = \
test_task_create.te test_task_getpgid.te test_task_getsched.te \
test_task_getsid.te test_task_setpgid.te test_task_setsched.te \
test_transition.te test_inet_socket.te test_unix_socket.te \
-   test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te
+   test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te \
+   test_ibpkey.te
 
 ifeq ($(shell [ $(POL_VERS) -ge 24 ] && echo true),true)
 TARGETS += test_bounds.te
diff --git a/policy/test_ibpkey.te b/policy/test_ibpkey.te
new file mode 100644
index 000..b2f5057
--- /dev/null
+++ b/policy/test_ibpkey.te
@@ -0,0 +1,25 @@
+#
+#
+# Policy for testing Infiniband Pkey access.
+#
+
+attribute ibpkeydomain;
+
+# Domain for process.
+type test_ibpkey_access_t;
+domain_type(test_ibpkey_access_t)
+unconfined_runs_test(test_ibpkey_access_t)
+typeattribute test_ibpkey_access_t testdomain;
+typeattribute test_ibpkey_access_t ibpkeydomain;
+
+dev_rw_infiniband_dev(test_ibpkey_access_t)
+dev_rw_sysfs(test_ibpkey_access_t)
+
+# Define a pkey type for labeling pkeys during the test.
+type test_ibpkey_t;
+corenet_ib_pkey(test_ibpkey_t)
+corenet_ib_access_unlabeled_pkeys(test_ibpkey_access_t)
+
+# Allow all of these domains to be entered from the sysadm domain.
+miscfiles_domain_entry_test_files(ibpkeydomain)
+userdom_sysadm_entry_spec_domtrans_to(ibpkeydomain)
diff --git a/tests/Makefile b/tests/Makefile
index fb8a0aa..7dfe2a8 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -4,13 +4,13 @@ export CFLAGS+=-g -O0 -Wall -D_GNU_SOURCE
 
 DISTRO=$(shell ./os_detect)
 
-SUBDIRS:=domain_trans entrypoint execshare exectrace execute_no_trans \
+SUBDIRS:= domain_trans entrypoint execshare exectrace execute_no_trans \
fdreceive inherit link mkdir msg open ptrace readlink relabel rename \
rxdir sem setattr setnice shm sigkill stat sysctl task_create \
task_setnice task_setscheduler task_getscheduler task_getsid \
task_getpgid task_setpgid file ioctl capable_file capable_net \
capable_sys dyntrans dyntrace bounds nnp mmap unix_socket inet_socket \
-   overlay checkreqprot mqueue mac_admin
+   overlay checkreqprot mqueue mac_admin infiniband_pkey
 
 ifeq ($(shell grep -q cap_userns $(POLDEV)/include/support/all_perms.spt && 
echo true),true)
 ifneq ($(shell ./kvercmp $$(uname -r) 4.7),-1)
diff --git a/tests/infiniband_pkey/Makefile b/tests/infiniband_pkey/Makefile
new file mode 100644
index 000..60f0d24
--- /dev/null
+++ b/tests/infiniband_pkey/Makefile
@@ -0,0 +1,7 @@
+TARGETS=create_modify_qp
+
+LDLIBS+= -libverbs
+
+all: $(TARGETS)
+clean:
+   rm -f $(TARGETS)
diff --git 

[PATCH v1 0/2] Selinux tests for Infinfiband

2017-05-24 Thread Dan Jurgens
From: Daniel Jurgens 

Implements new tests for Infiniband pkeys and endports. Because infiniband
isn't widely used, and when it is the configuration is site specific,
configuration files are used to enable the tests and set environment
specific settings. When the tests are disable they always show as passed.

If enabled, the tests require correstponding updates to selinux, refpolicy,
and the linux kernel.

---

v1:
- Synchronize intefrace names with changes to refpolicy.
- Change tests to not assume that default pkey is labeled.
- See patches v1 notes for more detail.

Daniel Jurgens (2):
  selinux-testsuite: Infiniband pkey tests
  selinux-testsuite: Infiniband endport tests

 README   |  14 +++
 policy/Makefile  |   3 +-
 policy/test_ibendport.te |  35 +++
 policy/test_ibpkey.te|  25 +
 tests/Makefile   |   8 +-
 tests/infiniband_endport/ibendport_test.conf |  14 +++
 tests/infiniband_endport/test|  49 +
 tests/infiniband_pkey/Makefile   |   7 ++
 tests/infiniband_pkey/create_modify_qp.c | 144 +++
 tests/infiniband_pkey/ibpkey_test.conf   |  18 
 tests/infiniband_pkey/test   |  84 
 11 files changed, 397 insertions(+), 4 deletions(-)
 create mode 100644 policy/test_ibendport.te
 create mode 100644 policy/test_ibpkey.te
 create mode 100644 tests/infiniband_endport/ibendport_test.conf
 create mode 100644 tests/infiniband_endport/test
 create mode 100644 tests/infiniband_pkey/Makefile
 create mode 100644 tests/infiniband_pkey/create_modify_qp.c
 create mode 100644 tests/infiniband_pkey/ibpkey_test.conf
 create mode 100755 tests/infiniband_pkey/test

-- 
2.12.2



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

2017-05-23 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

v7:
- Exclude IB_QPT_RESERVED* types from enforcement, they are special like
  SMI and GSI.
- Use kcalloc vs kzalloc for port_pkey_list allocation. Parav Pandit

v8:
- Remove LSM security hook initialization merge mistake. Paul Moore
- Cleanup unneccesary gotos in drivers/infiniband/core/security.c. James
Morris
---
 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   | 613 +++
 drivers/infiniband/core/uverbs_cmd.c |  15 +-
 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  |  22 ++
 12 files changed, 907 insertions(+), 9 deletions(-)
 create mode 100644 drivers/infiniband/core/security.c

diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index e426ac877d19..d6c8715593b7 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
 

[PATCH v3 6/9] libsepol: Add IB end port handling to CIL

2017-05-22 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
James Carter:
- Add cil_resolve_ibendportcon prototype in cil_resolve_ast.h
---
 libsepol/cil/src/cil.c | 18 +++
 libsepol/cil/src/cil_binary.c  | 29 +
 libsepol/cil/src/cil_binary.h  | 12 +++
 libsepol/cil/src/cil_build_ast.c   | 65 ++
 libsepol/cil/src/cil_build_ast.h   |  2 ++
 libsepol/cil/src/cil_copy_ast.c| 25 +++
 libsepol/cil/src/cil_flavor.h  |  1 +
 libsepol/cil/src/cil_internal.h|  9 ++
 libsepol/cil/src/cil_policy.c  | 15 +
 libsepol/cil/src/cil_post.c| 42 
 libsepol/cil/src/cil_post.h|  1 +
 libsepol/cil/src/cil_reset_ast.c   | 10 ++
 libsepol/cil/src/cil_resolve_ast.c | 28 
 libsepol/cil/src/cil_resolve_ast.h |  1 +
 libsepol/cil/src/cil_tree.c| 13 
 libsepol/cil/src/cil_verify.c  | 23 ++
 16 files changed, 294 insertions(+)

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 3df670a7..c02a41a5 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -189,6 +189,7 @@ static void cil_init_keys(void)
CIL_KEY_CONTEXT = cil_strpool_add("context");
CIL_KEY_FILECON = cil_strpool_add("filecon");
CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon");
+   CIL_KEY_IBENDPORTCON = cil_strpool_add("ibendportcon");
CIL_KEY_PORTCON = cil_strpool_add("portcon");
CIL_KEY_NODECON = cil_strpool_add("nodecon");
CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -259,6 +260,7 @@ void cil_db_init(struct cil_db **db)
cil_sort_init(&(*db)->filecon);
cil_sort_init(&(*db)->nodecon);
cil_sort_init(&(*db)->ibpkeycon);
+   cil_sort_init(&(*db)->ibendportcon);
cil_sort_init(&(*db)->portcon);
cil_sort_init(&(*db)->pirqcon);
cil_sort_init(&(*db)->iomemcon);
@@ -311,6 +313,7 @@ void cil_db_destroy(struct cil_db **db)
cil_sort_destroy(&(*db)->filecon);
cil_sort_destroy(&(*db)->nodecon);
cil_sort_destroy(&(*db)->ibpkeycon);
+   cil_sort_destroy(&(*db)->ibendportcon);
cil_sort_destroy(&(*db)->portcon);
cil_sort_destroy(&(*db)->pirqcon);
cil_sort_destroy(&(*db)->iomemcon);
@@ -737,6 +740,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_PORTCON:
cil_destroy_portcon(*data);
break;
+   case CIL_IBENDPORTCON:
+   cil_destroy_ibendportcon(*data);
+   break;
case CIL_NODECON:
cil_destroy_nodecon(*data);
break;
@@ -1105,6 +,8 @@ const char * cil_node_to_string(struct cil_tree_node 
*node)
return CIL_KEY_FILECON;
case CIL_IBPKEYCON:
return CIL_KEY_IBPKEYCON;
+   case CIL_IBENDPORTCON:
+   return CIL_KEY_IBENDPORTCON;
case CIL_PORTCON:
return CIL_KEY_PORTCON;
case CIL_NODECON:
@@ -1838,6 +1846,16 @@ void cil_netifcon_init(struct cil_netifcon **netifcon)
(*netifcon)->context_str = NULL;
 }
 
+void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon)
+{
+   *ibendportcon = cil_malloc(sizeof(**ibendportcon));
+
+   (*ibendportcon)->dev_name_str = NULL;
+   (*ibendportcon)->port = 0;
+   (*ibendportcon)->context_str = NULL;
+   (*ibendportcon)->context = NULL;
+}
+
 void cil_context_init(struct cil_context **context)
 {
*context = cil_malloc(sizeof(**context));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 1ddbf21f..c0ca60f2 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3323,6 +3323,30 @@ exit:
return rc;
 }
 
+int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort 
*ibendportcons)
+{
+   int rc = SEPOL_ERR;
+   uint32_t i;
+   ocontext_t *tail = NULL;
+
+   for (i = 0; i < ibendportcons->count; i++) {
+   ocontext_t *new_ocon = 
cil_add_ocontext(>ocontexts[OCON_IBENDPORT], );
+   struct cil_ibendportcon *cil_ibendportcon = 
ibendportcons->array[i];
+
+   new_ocon->u.ibendport.dev_name = 
cil_strdup(cil_ibendportcon->dev_name_str);
+   new_ocon->u.ibendport.port = cil_ibendportcon->port;
+
+   rc = __cil_context_to_sepol_context(pdb, 
cil_ibendportcon->context, _ocon->context[0]);
+   if (rc != SEPOL_OK)
+   goto exit;
+   }
+
+   return SEPOL_OK;
+
+exit:
+   return rc;
+}
+
 int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons)
 {
int rc = SEPOL_ERR;
@@ -3887,6 +3911,11 @@ int __cil_contexts_to_policydb(policydb_t *pdb, const 
struct cil_db *db)
goto exit;

[PATCH v3 2/9] libsepol: Add ibpkey ocontext handling

2017-05-22 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Removed domain and type params from sepol_ibpkey_sid.
- Removed splen param from sepol_ibpkey_sid, it never varied.
- Removed extra XPERMS_IOCTL version from policydb_compat_info.
- Confirm that low order bytes of IPv6 addr for subnet prefix is 0's.

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

v2:
Stephen Smalley:
- Store subnet prefix as 8 bytes. This mooted a couple other comments
  about checking and forcing 0's in the lower 8 bytes.
- Bounds check PKeys values in ocontext_read_selinux.

James Carter:
- Add sorting of pkey ocontexts in kernel_to_common.c
---
 checkpolicy/checkpolicy.c  | 27 +
 libsepol/include/sepol/policydb/services.h |  8 
 libsepol/src/expand.c  |  7 
 libsepol/src/kernel_to_cil.c   | 62 +
 libsepol/src/kernel_to_common.c| 19 +
 libsepol/src/kernel_to_conf.c  | 63 ++
 libsepol/src/libsepol.map.in   |  1 +
 libsepol/src/module_to_cil.c   | 41 +++
 libsepol/src/policydb.c| 37 ++
 libsepol/src/services.c| 37 ++
 libsepol/src/write.c   | 16 
 11 files changed, 318 insertions(+)

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 534fc22e..8aeecc1b 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -22,6 +22,7 @@
  *
  * Policy Module support.
  *
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2005 Tresys Technology, LLC
  * Copyright (C) 2003 Red Hat, Inc., James Morris 
@@ -699,6 +700,7 @@ int main(int argc, char **argv)
printf("h)  change a boolean value\n");
printf("i)  display constraint expressions\n");
printf("j)  display validatetrans expressions\n");
+   printf("k)  Call ibpkey_sid\n");
 #ifdef EQUIVTYPES
printf("z)  Show equivalent types\n");
 #endif
@@ -1220,6 +1222,31 @@ int main(int argc, char **argv)
"\nNo validatetrans expressions found.\n");
}
break;
+   case 'k':
+   {
+   char *p;
+   struct in6_addr addr6;
+   uint64_t subnet_prefix;
+   unsigned int pkey;
+
+   printf("subnet prefix?  ");
+   FGETS(ans, sizeof(ans), stdin);
+   ans[strlen(ans) - 1] = 0;
+   p = (char *)
+
+   if (inet_pton(AF_INET6, ans, p) < 1) {
+   printf("error parsing subnet prefix\n");
+   break;
+   }
+
+   memcpy(_prefix, p, 
sizeof(subnet_prefix));
+   printf("pkey? ");
+   FGETS(ans, sizeof(ans), stdin);
+   pkey = atoi(ans);
+   sepol_ibpkey_sid(subnet_prefix, pkey, );
+   printf("sid %d\n", ssid);
+   }
+   break;
 #ifdef EQUIVTYPES
case 'z':
identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h 
b/libsepol/include/sepol/policydb/services.h
index 9162149a..3f3b95d1 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -188,6 +188,14 @@ extern int sepol_port_sid(uint16_t domain,
  uint16_t port, sepol_security_id_t * out_sid);
 
 /*
+ * Return the SID of the ibpkey specified by
+ * `subnet prefix', and `pkey'.
+ */
+extern int sepol_ibpkey_sid(uint64_t subnet_prefix_p,
+   uint16_t pkey,
+   sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 54bf781d..e4cfc41e 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2004-2005 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2017 Mellanox Technologies, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  

[PATCH v3 5/9] libsepol: Add ibendport ocontext handling

2017-05-22 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

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

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

v2:
James Carter
- Sort ocontexts in kernel_to_common.c
---
 checkpolicy/checkpolicy.c  | 20 ++
 libsepol/include/sepol/policydb/services.h |  8 ++
 libsepol/src/expand.c  |  8 ++
 libsepol/src/kernel_to_cil.c   | 42 ++
 libsepol/src/kernel_to_common.c| 18 +
 libsepol/src/kernel_to_conf.c  | 41 +
 libsepol/src/libsepol.map.in   |  1 +
 libsepol/src/module_to_cil.c   | 14 ++
 libsepol/src/policydb.c| 26 +++---
 libsepol/src/services.c| 37 ++
 libsepol/src/write.c   | 14 ++
 11 files changed, 226 insertions(+), 3 deletions(-)

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 8aeecc1b..b75f2afa 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -701,6 +701,7 @@ int main(int argc, char **argv)
printf("i)  display constraint expressions\n");
printf("j)  display validatetrans expressions\n");
printf("k)  Call ibpkey_sid\n");
+   printf("l)  Call ibendport_sid\n");
 #ifdef EQUIVTYPES
printf("z)  Show equivalent types\n");
 #endif
@@ -1247,6 +1248,25 @@ int main(int argc, char **argv)
printf("sid %d\n", ssid);
}
break;
+   case 'l':
+   printf("device name (eg. mlx4_0)?  ");
+   FGETS(ans, sizeof(ans), stdin);
+   ans[strlen(ans) - 1] = 0;
+
+   name = malloc((strlen(ans) + 1) * sizeof(char));
+   if (!name) {
+   fprintf(stderr, "couldn't malloc string.\n");
+   break;
+   }
+   strcpy(name, ans);
+
+   printf("port? ");
+   FGETS(ans, sizeof(ans), stdin);
+   port = atoi(ans);
+   sepol_ibendport_sid(name, port, );
+   printf("sid %d\n", ssid);
+   free(name);
+   break;
 #ifdef EQUIVTYPES
case 'z':
identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h 
b/libsepol/include/sepol/policydb/services.h
index 3f3b95d1..efdf7de5 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -196,6 +196,14 @@ extern int sepol_ibpkey_sid(uint64_t subnet_prefix_p,
sepol_security_id_t *out_sid);
 
 /*
+ * Return the SID of the ibendport specified by
+ * `dev_name', and `port'.
+ */
+extern int sepol_ibendport_sid(char *dev_name,
+  uint8_t port,
+  sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index e4cfc41e..8f7a25d8 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -2224,6 +2224,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey;
n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey;
break;
+   case OCON_IBENDPORT:
+   n->u.ibendport.dev_name = 
strdup(c->u.ibendport.dev_name);
+   if (!n->u.ibendport.dev_name) {
+   ERR(state->handle, "Out of memory!");
+   return -1;
+   }
+   n->u.ibendport.port = c->u.ibendport.port;
+   break;
case OCON_PORT:
n->u.port.protocol = c->u.port.protocol;
n->u.port.low_port = c->u.port.low_port;
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index d1006186..f4ec8832 100644
--- a/libsepol/src/kernel_to_cil.c
+++ 

[PATCH v3 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys

2017-05-22 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Fixed semanage_pkey_exists -> semanage_ibpkey_exists in delete flow in
seobject.py

Stephen Smalley:
- Subnet prefix can't vary in size always 16 bytes, remove size field.
- Removed extraneous change in libsepol/VERSION
- Removed ifdef DARWIN s6_addr/32 blocks in favor of s6_addr.
- Got rid of magic constant for subnet prefix size.

Jason Zaman:
- Use SETools directly to query types in seobject.py.

v2:
Jason Zaman:
- Use set instead of sorted for valid_types.

Stephen Smalley:
- Fix semanage when ibpkey_type attribute isn't defined.
- Store subnet prefix in 8 bytes.
- Removed a missed #if DARWIN
- Use sizeof(struct in6_addr) vs a define.

v3:
Stephen Smalley:
- Use uint64_t as subnet_prefix type instead of char array.
---
 libsemanage/include/semanage/ibpkey_record.h  |  72 +
 libsemanage/include/semanage/ibpkeys_local.h  |  36 +++
 libsemanage/include/semanage/ibpkeys_policy.h |  28 ++
 libsemanage/include/semanage/semanage.h   |   3 +
 libsemanage/src/direct_api.c  |  29 +-
 libsemanage/src/handle.h  |  36 ++-
 libsemanage/src/ibpkey_internal.h |  52 
 libsemanage/src/ibpkey_record.c   | 182 +
 libsemanage/src/ibpkeys_file.c| 181 
 libsemanage/src/ibpkeys_local.c   | 164 +++
 libsemanage/src/ibpkeys_policy.c  |  52 
 libsemanage/src/ibpkeys_policydb.c|  62 +
 libsemanage/src/libsemanage.map   |   1 +
 libsemanage/src/policy_components.c   |   5 +-
 libsemanage/src/semanage_store.c  |   1 +
 libsemanage/src/semanage_store.h  |   1 +
 libsemanage/src/semanageswig.i|   3 +
 libsemanage/src/semanageswig_python.i |  43 +++
 libsemanage/utils/semanage_migrate_store  |   3 +-
 libsepol/include/sepol/ibpkey_record.h|  75 +
 libsepol/include/sepol/ibpkeys.h  |  44 +++
 libsepol/include/sepol/sepol.h|   2 +
 libsepol/src/ibpkey_internal.h|  21 ++
 libsepol/src/ibpkey_record.c  | 379 ++
 libsepol/src/ibpkeys.c| 251 +
 python/semanage/semanage  |  60 +++-
 python/semanage/seobject.py   | 255 +
 27 files changed, 2025 insertions(+), 16 deletions(-)
 create mode 100644 libsemanage/include/semanage/ibpkey_record.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_local.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_policy.h
 create mode 100644 libsemanage/src/ibpkey_internal.h
 create mode 100644 libsemanage/src/ibpkey_record.c
 create mode 100644 libsemanage/src/ibpkeys_file.c
 create mode 100644 libsemanage/src/ibpkeys_local.c
 create mode 100644 libsemanage/src/ibpkeys_policy.c
 create mode 100644 libsemanage/src/ibpkeys_policydb.c
 create mode 100644 libsepol/include/sepol/ibpkey_record.h
 create mode 100644 libsepol/include/sepol/ibpkeys.h
 create mode 100644 libsepol/src/ibpkey_internal.h
 create mode 100644 libsepol/src/ibpkey_record.c
 create mode 100644 libsepol/src/ibpkeys.c

diff --git a/libsemanage/include/semanage/ibpkey_record.h 
b/libsemanage/include/semanage/ibpkey_record.h
new file mode 100644
index ..9da7dc53
--- /dev/null
+++ b/libsemanage/include/semanage/ibpkey_record.h
@@ -0,0 +1,72 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+#ifndef _SEMANAGE_IBPKEY_RECORD_H_
+#define _SEMANAGE_IBPKEY_RECORD_H_
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef _SEMANAGE_IBPKEY_DEFINED_
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey semanage_ibpkey_t;
+typedef struct semanage_ibpkey_key semanage_ibpkey_key_t;
+#define _SEMANAGE_IBPKEY_DEFINED_
+#endif
+
+extern int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
+  const semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
+   const semanage_ibpkey_t *ibpkey2);
+
+extern int semanage_ibpkey_key_create(semanage_handle_t *handle,
+ const char *subnet_prefix,
+ int low, int high,
+ semanage_ibpkey_key_t **key_ptr);
+
+extern int semanage_ibpkey_key_extract(semanage_handle_t *handle,
+  const semanage_ibpkey_t *ibpkey,
+  semanage_ibpkey_key_t **key_ptr);
+
+extern void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key);
+
+extern int 

[PATCH v3 4/9] checkpolicy: Add support for ibendportcon labels

2017-05-22 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Check IB device name length when parsing policy.
- Use strcmp vs strncmp to compare device names.

v2:
Stephen Smalley:
- Bound check port number when parsing ibendports.
---
 checkpolicy/policy_define.c| 80 ++
 checkpolicy/policy_define.h|  1 +
 checkpolicy/policy_parse.y | 14 +-
 checkpolicy/policy_scan.l  |  2 +
 libsepol/include/sepol/policydb/policydb.h |  9 +++-
 5 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index e73ec8f7..f12ebdbd 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -5164,6 +5164,86 @@ out:
return rc;
 }
 
+int define_ibendport_context(unsigned int port)
+{
+   ocontext_t *newc, *c, *l, *head;
+   char *id;
+   int rc = 0;
+
+   if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+   yyerror("ibendportcon not supported for target");
+   return -1;
+   }
+
+   if (pass == 1) {
+   id = (char *)queue_remove(id_queue);
+   free(id);
+   parse_security_context(NULL);
+   return 0;
+   }
+
+   if (port > 0xff || port == 0) {
+   yyerror("Invalid ibendport port number, should be 0 < port < 
256");
+   return -1;
+   }
+
+   newc = malloc(sizeof(*newc));
+   if (!newc) {
+   yyerror("out of memory");
+   return -1;
+   }
+   memset(newc, 0, sizeof(*newc));
+
+   newc->u.ibendport.dev_name = queue_remove(id_queue);
+   if (!newc->u.ibendport.dev_name) {
+   yyerror("failed to read infiniband device name.");
+   rc = -1;
+   goto out;
+   }
+
+   if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) {
+   yyerror("infiniband device name exceeds max length of 63.");
+   rc = -1;
+   goto out;
+   }
+
+   newc->u.ibendport.port = port;
+
+   if (parse_security_context(>context[0])) {
+   free(newc);
+   return -1;
+   }
+
+   /* Preserve the matching order specified in the configuration. */
+   head = policydbp->ocontexts[OCON_IBENDPORT];
+   for (l = NULL, c = head; c; l = c, c = c->next) {
+   unsigned int port2;
+
+   port2 = c->u.ibendport.port;
+
+   if (port == port2 &&
+   !strcmp(c->u.ibendport.dev_name,
+newc->u.ibendport.dev_name)) {
+   yyerror2("duplicate ibendportcon entry for %s port %u",
+newc->u.ibendport.dev_name, port);
+   rc = -1;
+   goto out;
+   }
+   }
+
+   if (l)
+   l->next = newc;
+   else
+   policydbp->ocontexts[OCON_IBENDPORT] = newc;
+
+   return 0;
+
+out:
+   free(newc->u.ibendport.dev_name);
+   free(newc);
+   return rc;
+}
+
 int define_netif_context(void)
 {
ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 75e3683b..50a7ba78 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -44,6 +44,7 @@ int define_netif_context(void);
 int define_permissive(void);
 int define_polcap(void);
 int define_ibpkey_context(unsigned int low, unsigned int high);
+int define_ibendport_context(unsigned int port);
 int define_port_context(unsigned int low, unsigned int high);
 int define_pirq_context(unsigned int pirq);
 int define_iomem_context(uint64_t low, uint64_t high);
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index 35b433bd..6b406c85 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -137,6 +137,7 @@ typedef int (* require_func_t)(int pass);
 %token SAMEUSER
 %token FSCON PORTCON NETIFCON NODECON 
 %token IBPKEYCON
+%token IBENDPORTCON
 %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
 %token FSUSEXATTR FSUSETASK FSUSETRANS
 %token GENFSCON
@@ -172,7 +173,7 @@ base_policy : { if (define_policy(pass, 0) == 
-1) return -1; }
  opt_default_rules opt_mls te_rbac users 
opt_constraints 
  { if (pass == 1) { if 
(policydb_index_bools(policydbp)) return -1;}
   else if (pass == 2) { if 
(policydb_index_others(NULL, policydbp, 0)) return -1;}}
- initial_sid_contexts opt_fs_contexts opt_fs_uses 
opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts
+ initial_sid_contexts opt_fs_contexts 

[PATCH v3 1/9] checkpolicy: Add support for ibpkeycon labels

2017-05-22 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Always use s6_addr instead of s6_addr32.
- Add comment about POLICYDB_VERSION_INFINIBAND being linux specific.

v2:
Stephen Smalley:
- Store subnet_prefix as 8 bytes.
---
 checkpolicy/policy_define.c| 107 +
 checkpolicy/policy_define.h|   1 +
 checkpolicy/policy_parse.y |  15 +++-
 checkpolicy/policy_scan.l  |   3 +
 libsepol/include/sepol/policydb/policydb.h |  30 +---
 5 files changed, 144 insertions(+), 12 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 8fab214b..e73ec8f7 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -20,6 +20,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2008 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2017 Mellanox Techonologies Inc.
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 2.
@@ -5057,6 +5058,112 @@ int define_port_context(unsigned int low, unsigned int 
high)
return -1;
 }
 
+int define_ibpkey_context(unsigned int low, unsigned int high)
+{
+   ocontext_t *newc, *c, *l, *head;
+   struct in6_addr subnet_prefix;
+   char *id;
+   int rc = 0;
+
+   if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+   yyerror("ibpkeycon not supported for target");
+   return -1;
+   }
+
+   if (pass == 1) {
+   id = (char *)queue_remove(id_queue);
+   free(id);
+   parse_security_context(NULL);
+   return 0;
+   }
+
+   newc = malloc(sizeof(*newc));
+   if (!newc) {
+   yyerror("out of memory");
+   return -1;
+   }
+   memset(newc, 0, sizeof(*newc));
+
+   id = queue_remove(id_queue);
+   if (!id) {
+   yyerror("failed to read the subnet prefix");
+   rc = -1;
+   goto out;
+   }
+
+   rc = inet_pton(AF_INET6, id, _prefix);
+   free(id);
+   if (rc < 1) {
+   yyerror("failed to parse the subnet prefix");
+   if (rc == 0)
+   rc = -1;
+   goto out;
+   }
+
+   if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) {
+   yyerror("subnet prefix should be 0's in the low order 64 
bits.");
+   rc = -1;
+   goto out;
+   }
+
+   if (low > 0x || high > 0x) {
+   yyerror("pkey value too large, pkeys are 16 bits.");
+   rc = -1;
+   goto out;
+   }
+
+   memcpy(>u.ibpkey.subnet_prefix, _prefix.s6_addr[0],
+  sizeof(newc->u.ibpkey.subnet_prefix));
+
+   newc->u.ibpkey.low_pkey = low;
+   newc->u.ibpkey.high_pkey = high;
+
+   if (low > high) {
+   yyerror2("low pkey %d exceeds high pkey %d", low, high);
+   rc = -1;
+   goto out;
+   }
+
+   rc = parse_security_context(>context[0]);
+   if (rc)
+   goto out;
+
+   /* Preserve the matching order specified in the configuration. */
+   head = policydbp->ocontexts[OCON_IBPKEY];
+   for (l = NULL, c = head; c; l = c, c = c->next) {
+   unsigned int low2, high2;
+
+   low2 = c->u.ibpkey.low_pkey;
+   high2 = c->u.ibpkey.high_pkey;
+
+   if (low == low2 && high == high2 &&
+   c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
+   yyerror2("duplicate ibpkeycon entry for %d-%d ",
+low, high);
+   rc = -1;
+   goto out;
+   }
+   if (low2 <= low && high2 >= high &&
+   c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
+   yyerror2("ibpkeycon entry for %d-%d hidden by earlier 
entry for %d-%d",
+low, high, low2, high2);
+   rc = -1;
+   goto out;
+   }
+   }
+
+   if (l)
+   l->next = newc;
+   else
+   policydbp->ocontexts[OCON_IBPKEY] = newc;
+
+   return 0;
+
+out:
+   free(newc);
+   return rc;
+}
+
 int define_netif_context(void)
 {
ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 9f4b6d0d..75e3683b 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h

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

2017-05-22 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

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

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

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

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

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

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

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

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

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

---
v1:
- Fixed seobject ibpkey delete all name bug (pkey vs ibpkey).

Stephen Smalley:
- Always use s6_addr vs s6_addr32, remove DARWIN #ifdefs.
- Removed unused parameters from new sepol_*_sid functions.
- Got rid of variable length subnet prefix handling, it never varied. 

James Carter:
- Add kernel_to_cil and kernel_to_conf implementations for new OCONs.

Jason Zaman:
- Use SETools directly to query types by attribute in seobject.py.


- See individual patches for more detailed changes.

v2:
- Rebased over Stephens MOD_VERSION change.

Stephen Smalley:
- Bound check new ocontext fields
- Only store 8 bytes of subnet prefix in binary policy
- Make it so semanage doesn't crash if ipbkey_type or ibendport_type are
  undefined.
- Don't define INET6_ADDRLEN, use sizeof(struct in6_addr)

James Carter:
- Sort new ocontexts in kernel_to_common.c

- Additional smaller changes noted in specific patches.

v3:
Stephen Smalley:
- Store subnet prefix as uint64_t vs char* in ibpkey record and key types.

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

 checkpolicy/checkpolicy.c|  47 +++
 checkpolicy/policy_define.c  | 187 +
 checkpolicy/policy_define.h  |   2 +
 checkpolicy/policy_parse.y   |  27 +-
 checkpolicy/policy_scan.l|   5 +
 libsemanage/include/semanage/ibendport_record.h  |  62 +++
 libsemanage/include/semanage/ibendports_local.h  |  36 ++
 libsemanage/include/semanage/ibendports_policy.h |  28 ++
 libsemanage/include/semanage/ibpkey_record.h |  72 
 libsemanage/include/semanage/ibpkeys_local.h |  36 ++
 libsemanage/include/semanage/ibpkeys_policy.h|  28 ++
 libsemanage/include/semanage/semanage.h  |   6 +
 

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

2017-05-19 Thread Dan Jurgens
From: Daniel Jurgens <dani...@mellanox.com>

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 <dani...@mellanox.com>

---
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 7b63215..0664527 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -38,6 +38,8 @@
 #include 
 
 #include 
+#include 
+#include "mad_priv.h"
 
 struct pkey_index_qp_list {
struct list_headpkey_index_list;
@@ -189,6 +191,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,
@@ -206,7 +213,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)
 {
 }
@@ -255,5 +274,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 57f231f..46b3c98 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"
@@ -369,6 +371,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_agen

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

2017-05-19 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

v4:
- removed unneeded brackets in ocontext_read. Paul Moore

v7:
- Synchronized ocontext naming with userspace patches. Stephen Smalley

 security/selinux/include/security.h |   3 +-
 security/selinux/ss/policydb.c  | 112 +++-
 security/selinux/ss/policydb.h  |  27 ++---
 3 files changed, 118 insertions(+), 24 deletions(-)

diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index f979c35..e202448 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -36,10 +36,11 @@
 #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
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_XPERMS_IOCTL
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_INFINIBAND
 
 /* Mask for just the mount related flags */
 #define SE_MNTMASK 0x0f
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 87d645d..aa6500a 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 v7 8/9] selinux: Add IB Port SMP access vector

2017-05-19 Thread Dan Jurgens
From: Daniel Jurgens 

Add a type for Infiniband ports and an access vector for subnet
management packets. Implement the ib_port_smp hook to check that the
caller has permission to send and receive SMPs on the end port specified
by the device name and port. Add interface to query the SID for a IB
port, which walks the IB_PORT ocontexts to find an entry for the
given name and port.

Signed-off-by: Daniel Jurgens 

---
v2:
- Shorted ib_end_port. Paul Moore
- Pass void blobs to security hooks. Paul Moore
- Log specific IB port info in audit log. Paul Moore
- Don't create a new intial sid, use unlabeled. Stephen Smalley
- Changed "smp" to "manage_subnet". Paul Moore

v3:
- ib_port -> ib_endport. Paul Moore
- Don't log device name as untrusted string. Paul Moore
- Reorder parameters of LSM hook. Paul Moore

v6:
- Remove brakets around single statement else. James Morris

v7:
- Synch ocontext names with userspace.  Also change lsm_audit_data names
  to the same style.  Stephen Smalley

 include/linux/lsm_audit.h   |  8 
 security/lsm_audit.c|  5 +
 security/selinux/hooks.c| 25 ++
 security/selinux/include/classmap.h |  2 ++
 security/selinux/include/security.h |  2 ++
 security/selinux/ss/services.c  | 41 +
 6 files changed, 83 insertions(+)

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 0df5639..22b5d4e 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct lsm_network_audit {
int netif;
@@ -50,6 +51,11 @@ struct lsm_ibpkey_audit {
u16 pkey;
 };
 
+struct lsm_ibendport_audit {
+   chardev_name[IB_DEVICE_NAME_MAX];
+   u8  port;
+};
+
 /* Auxiliary data to use in generating the audit record. */
 struct common_audit_data {
char type;
@@ -66,6 +72,7 @@ struct common_audit_data {
 #define LSM_AUDIT_DATA_IOCTL_OP11
 #define LSM_AUDIT_DATA_FILE12
 #define LSM_AUDIT_DATA_IBPKEY  13
+#define LSM_AUDIT_DATA_IBENDPORT 14
union   {
struct path path;
struct dentry *dentry;
@@ -84,6 +91,7 @@ struct common_audit_data {
struct lsm_ioctlop_audit *op;
struct file *file;
struct lsm_ibpkey_audit *ibpkey;
+   struct lsm_ibendport_audit *ibendport;
} u;
/* this union contains LSM specific data */
union {
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index c22c99f..28d4c3a 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -421,6 +421,11 @@ static void dump_common_audit_data(struct audit_buffer *ab,
 a->u.ibpkey->pkey, _pfx);
break;
}
+   case LSM_AUDIT_DATA_IBENDPORT:
+   audit_log_format(ab, " device=%s port_num=%u",
+a->u.ibendport->dev_name,
+a->u.ibendport->port);
+   break;
} /* switch (a->type) */
 }
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b8add3a..da5fffe 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6181,6 +6181,29 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 
subnet_prefix, u16 pkey_val)
INFINIBAND_PKEY__ACCESS, );
 }
 
+static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
+   u8 port_num)
+{
+   struct common_audit_data ad;
+   int err;
+   u32 sid = 0;
+   struct ib_security_struct *sec = ib_sec;
+   struct lsm_ibendport_audit ibendport;
+
+   err = security_ib_endport_sid(dev_name, port_num, );
+
+   if (err)
+   return err;
+
+   ad.type = LSM_AUDIT_DATA_IBENDPORT;
+   strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
+   ibendport.port = port_num;
+   ad.u.ibendport = 
+   return avc_has_perm(sec->sid, sid,
+   SECCLASS_INFINIBAND_ENDPORT,
+   INFINIBAND_ENDPORT__MANAGE_SUBNET, );
+}
+
 static int selinux_ib_alloc_security(void **ib_sec)
 {
struct ib_security_struct *sec;
@@ -6386,6 +6409,8 @@ static struct security_hook_list selinux_hooks[] 
__lsm_ro_after_init = {
LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
 #ifdef CONFIG_SECURITY_INFINIBAND
LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
+   LSM_HOOK_INIT(ib_endport_manage_subnet,
+ selinux_ib_endport_manage_subnet),
LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
 #endif
diff --git a/security/selinux/include/classmap.h 
b/security/selinux/include/classmap.h
index 0fec1c5..b9fe343 100644
--- 

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

2017-05-19 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

v4:
- Seperate avc callback for LSM notifier. Paul Moore

v5:
- Fix link error when CONFIG_SECURITY is not set. Build Robot

 drivers/infiniband/core/device.c | 53 
 include/linux/security.h | 23 +
 security/security.c  | 20 +++
 security/selinux/hooks.c | 11 +
 security/selinux/selinuxfs.c |  2 ++
 5 files changed, 109 insertions(+)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 92e0b89..63ebaab 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)
 {
@@ -341,6 +351,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
@@ -1104,10 +1148,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:
@@ -1127,6 +1179,7 @@ static int __init ib_core_init(void)
 
 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 8c73ee0..f96e333 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -69,6 +69,10 @@ struct audit_krule;
 struct user_namespace;
 struct timezone;
 
+enum lsm_event {
+   LSM_POLICY_CHANGE,
+};
+
 /* These functions are in security/commoncap.c */
 extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
   int cap, int audit);
@@ -164,6 +168,10 @@ struct security_mnt_opts {
int num_mnt_opts;
 };
 
+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);
+
 static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
 {
opts->mnt_opts = NULL;
@@ -382,6 +390,21 @@ int security_inode_getsecctx(struct inode *inode, void 
**ctx, u32 *ctxlen);
 

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

2017-05-19 Thread Dan Jurgens
From: Daniel Jurgens <dani...@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 <jmor...@redhat.com> and Paul Moore
<p...@paul-moore.com> (see security/selinux/netif.c and
security/selinux/netport.c for more information)

Signed-off-by: Daniel Jurgens <dani...@mellanox.com>

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

v6:
- Fixed sel_pkey_sid_slow error handling. James Morris

v7:
- Renamed sel_pkey* to sel_ib_pkey* in the pkey cache.

 security/selinux/Makefile |   2 +-
 security/selinux/hooks.c  |   7 +-
 security/selinux/ibpkey.c | 245 ++
 security/selinux/include/ibpkey.h |  31 +
 security/selinux/include/objsec.h |   6 +
 5 files changed, 288 insertions(+), 3 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 da5fffe..b14e2eb 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -91,6 +91,7 @@
 #include "netif.h"
 #include "netnode.h"
 #include "netport.h"
+#include "ibpkey.h"
 #include "xfrm.h"
 #include "netlabel.h"
 #include "audit.h"
@@ -174,8 +175,10 @@ static int selinux_netcache_avc_callback(u32 event)
 
 static int selinux_lsm_notifier_avc_callback(u32 event)
 {
-   if (event == AVC_CALLBACK_RESET)
+   if (event == AVC_CALLBACK_RESET) {
+   sel_ib_pkey_flush();
call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
+   }
 
return 0;
 }
@@ -6168,7 +6171,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_ibpkey_audit ibpkey;
 
-   err = security_ib_pkey_sid(subnet_prefix, pkey_val, );
+   err = sel_ib_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..e3614ee
--- /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 <jmor...@redhat.com> and
+ * Paul Moore <p...@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 
+#include 
+#include 
+#include 
+
+#include "ibpkey.h"
+#include "objsec.h"
+
+#define SEL_PKEY_HASH_SIZE   256
+#define SEL_PKEY_HASH_BKT_LIMIT   16
+
+struct sel_ib_pkey_bkt {
+   int size;
+   struct list_head list;
+};
+
+struct sel_ib_pkey {
+   struct pkey_security_struct psec;
+   struct list_head list;
+   struct rcu_head rcu;
+};
+
+static LIST_HEAD(sel_ib_pkey_list);
+static DEFINE_SPINLOCK(sel_ib_pkey_lock);
+static struct sel_ib_pkey_bkt sel_ib_pkey_hash[SEL_PKEY_HASH_SIZE];
+
+/**
+ * sel_ib_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_ib_pkey_hashfn(u16 pkey)
+{
+   return (pke

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

2017-05-19 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

v7:
- Exclude IB_QPT_RESERVED* types from enforcement, they are special like
  SMI and GSI.
- Use kcalloc vs kzalloc for port_pkey_list allocation. Parav Pandit

 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   | 618 +++
 drivers/infiniband/core/uverbs_cmd.c |  15 +-
 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  | 385 ++
 12 files changed, 1275 insertions(+), 9 deletions(-)
 create mode 100644 drivers/infiniband/core/security.c

diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index e426ac8..d6c8715 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
 ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o
diff 

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

2017-05-19 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

v6:
- Remove blank lines and brackets on single statement else. James Morris

v7:
- Synch ocontext naming with userspace. Also changed the LSM audit
  structure to be of the same style.  Stephen Smalley
- changed security_pkey_sid function to security_ib_pkey_sid.

 include/linux/lsm_audit.h   |  7 +++
 security/lsm_audit.c| 11 ++
 security/selinux/hooks.c| 22 
 security/selinux/include/classmap.h |  2 ++
 security/selinux/include/security.h |  2 ++
 security/selinux/ss/services.c  | 40 +
 6 files changed, 84 insertions(+)

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index e58e577..0df5639 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_ibpkey_audit {
+   u64 subnet_prefix;
+   u16 pkey;
+};
+
 /* Auxiliary data to use in generating the audit record. */
 struct common_audit_data {
char type;
@@ -60,6 +65,7 @@ struct common_audit_data {
 #define LSM_AUDIT_DATA_DENTRY  10
 #define LSM_AUDIT_DATA_IOCTL_OP11
 #define LSM_AUDIT_DATA_FILE12
+#define LSM_AUDIT_DATA_IBPKEY  13
union   {
struct path path;
struct dentry *dentry;
@@ -77,6 +83,7 @@ struct common_audit_data {
char *kmod_name;
struct lsm_ioctlop_audit *op;
struct file *file;
+   struct lsm_ibpkey_audit *ibpkey;
} u;
/* this union contains LSM specific data */
union {
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 37f04da..c22c99f 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -410,6 +410,17 @@ 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_IBPKEY: {
+   struct in6_addr sbn_pfx;
+
+   memset(_pfx.s6_addr, 0,
+  sizeof(sbn_pfx.s6_addr));
+   memcpy(_pfx.s6_addr, >u.ibpkey->subnet_prefix,
+  sizeof(a->u.ibpkey->subnet_prefix));
+   audit_log_format(ab, " pkey=0x%x subnet_prefix=%pI6c",
+a->u.ibpkey->pkey, _pfx);
+   break;
+   }
} /* switch (a->type) */
 }
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d580268..b8add3a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6160,6 +6160,27 @@ 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_ibpkey_audit ibpkey;
+
+   err = security_ib_pkey_sid(subnet_prefix, pkey_val, );
+   if (err)
+   return err;
+
+   ad.type = LSM_AUDIT_DATA_IBPKEY;
+   ibpkey.subnet_prefix = subnet_prefix;
+   ibpkey.pkey = pkey_val;
+   ad.u.ibpkey = 
+   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;
@@ -6364,6 +6385,7 @@ static struct security_hook_list selinux_hooks[] 
__lsm_ro_after_init = {
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 3e49a78..0fec1c5 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -231,6 +231,8 @@ struct security_class_mapping secclass_map[] = {
  { COMMON_SOCK_PERMS, NULL } },
{ "smc_socket",
  { COMMON_SOCK_PERMS, NULL } },
+  

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

2017-05-19 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 bc77c56..d580268 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,
@@ -6156,7 +6157,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[] __lsm_ro_after_init = {
@@ -6343,7 +6363,10 @@ static struct security_hook_list selinux_hooks[] 
__lsm_ro_after_init = {
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 c03cdcd..b7f15f7 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,
@@ -139,6 +140,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_ */
-- 
2.7.4



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

2017-05-19 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.

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 | 22 ++
 drivers/infiniband/core/core_priv.h |  3 +++
 include/rdma/ib_verbs.h |  1 +
 3 files changed, 26 insertions(+)

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index b1371eb..b9c0066 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -911,6 +911,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.ports[p].subnet_prefix;
+   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.ports[port - rdma_start_port(device)].port_state =
tprops->state;
 
+   device->cache.ports[port - rdma_start_port(device)].subnet_prefix =
+   tprops->subnet_prefix;
write_unlock_irq(>cache.lock);
 
kfree(gid_cache);
diff --git a/drivers/infiniband/core/core_priv.h 
b/drivers/infiniband/core/core_priv.h
index cb7d372..249e3ed 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -176,4 +176,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 99e4423..23486d3 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1841,6 +1841,7 @@ enum ib_mad_result {
 #define IB_DEVICE_NAME_MAX 64
 
 struct ib_port_cache {
+   u64   subnet_prefix;
struct ib_pkey_cache  *pkey;
struct ib_gid_table   *gid;
u8 lmc;
-- 
2.7.4



[PATCH v2 6/9] libsepol: Add IB end port handling to CIL

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
James Carter:
- Add cil_resolve_ibendportcon prototype in cil_resolve_ast.h
---
 libsepol/cil/src/cil.c | 18 +++
 libsepol/cil/src/cil_binary.c  | 29 +
 libsepol/cil/src/cil_binary.h  | 12 +++
 libsepol/cil/src/cil_build_ast.c   | 65 ++
 libsepol/cil/src/cil_build_ast.h   |  2 ++
 libsepol/cil/src/cil_copy_ast.c| 25 +++
 libsepol/cil/src/cil_flavor.h  |  1 +
 libsepol/cil/src/cil_internal.h|  9 ++
 libsepol/cil/src/cil_policy.c  | 15 +
 libsepol/cil/src/cil_post.c| 42 
 libsepol/cil/src/cil_post.h|  1 +
 libsepol/cil/src/cil_reset_ast.c   | 10 ++
 libsepol/cil/src/cil_resolve_ast.c | 28 
 libsepol/cil/src/cil_resolve_ast.h |  1 +
 libsepol/cil/src/cil_tree.c| 13 
 libsepol/cil/src/cil_verify.c  | 23 ++
 16 files changed, 294 insertions(+)

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 3df670a7..c02a41a5 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -189,6 +189,7 @@ static void cil_init_keys(void)
CIL_KEY_CONTEXT = cil_strpool_add("context");
CIL_KEY_FILECON = cil_strpool_add("filecon");
CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon");
+   CIL_KEY_IBENDPORTCON = cil_strpool_add("ibendportcon");
CIL_KEY_PORTCON = cil_strpool_add("portcon");
CIL_KEY_NODECON = cil_strpool_add("nodecon");
CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -259,6 +260,7 @@ void cil_db_init(struct cil_db **db)
cil_sort_init(&(*db)->filecon);
cil_sort_init(&(*db)->nodecon);
cil_sort_init(&(*db)->ibpkeycon);
+   cil_sort_init(&(*db)->ibendportcon);
cil_sort_init(&(*db)->portcon);
cil_sort_init(&(*db)->pirqcon);
cil_sort_init(&(*db)->iomemcon);
@@ -311,6 +313,7 @@ void cil_db_destroy(struct cil_db **db)
cil_sort_destroy(&(*db)->filecon);
cil_sort_destroy(&(*db)->nodecon);
cil_sort_destroy(&(*db)->ibpkeycon);
+   cil_sort_destroy(&(*db)->ibendportcon);
cil_sort_destroy(&(*db)->portcon);
cil_sort_destroy(&(*db)->pirqcon);
cil_sort_destroy(&(*db)->iomemcon);
@@ -737,6 +740,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_PORTCON:
cil_destroy_portcon(*data);
break;
+   case CIL_IBENDPORTCON:
+   cil_destroy_ibendportcon(*data);
+   break;
case CIL_NODECON:
cil_destroy_nodecon(*data);
break;
@@ -1105,6 +,8 @@ const char * cil_node_to_string(struct cil_tree_node 
*node)
return CIL_KEY_FILECON;
case CIL_IBPKEYCON:
return CIL_KEY_IBPKEYCON;
+   case CIL_IBENDPORTCON:
+   return CIL_KEY_IBENDPORTCON;
case CIL_PORTCON:
return CIL_KEY_PORTCON;
case CIL_NODECON:
@@ -1838,6 +1846,16 @@ void cil_netifcon_init(struct cil_netifcon **netifcon)
(*netifcon)->context_str = NULL;
 }
 
+void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon)
+{
+   *ibendportcon = cil_malloc(sizeof(**ibendportcon));
+
+   (*ibendportcon)->dev_name_str = NULL;
+   (*ibendportcon)->port = 0;
+   (*ibendportcon)->context_str = NULL;
+   (*ibendportcon)->context = NULL;
+}
+
 void cil_context_init(struct cil_context **context)
 {
*context = cil_malloc(sizeof(**context));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 1ddbf21f..c0ca60f2 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3323,6 +3323,30 @@ exit:
return rc;
 }
 
+int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort 
*ibendportcons)
+{
+   int rc = SEPOL_ERR;
+   uint32_t i;
+   ocontext_t *tail = NULL;
+
+   for (i = 0; i < ibendportcons->count; i++) {
+   ocontext_t *new_ocon = 
cil_add_ocontext(>ocontexts[OCON_IBENDPORT], );
+   struct cil_ibendportcon *cil_ibendportcon = 
ibendportcons->array[i];
+
+   new_ocon->u.ibendport.dev_name = 
cil_strdup(cil_ibendportcon->dev_name_str);
+   new_ocon->u.ibendport.port = cil_ibendportcon->port;
+
+   rc = __cil_context_to_sepol_context(pdb, 
cil_ibendportcon->context, _ocon->context[0]);
+   if (rc != SEPOL_OK)
+   goto exit;
+   }
+
+   return SEPOL_OK;
+
+exit:
+   return rc;
+}
+
 int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons)
 {
int rc = SEPOL_ERR;
@@ -3887,6 +3911,11 @@ int __cil_contexts_to_policydb(policydb_t *pdb, const 
struct cil_db *db)
goto exit;

[PATCH v2 4/9] checkpolicy: Add support for ibendportcon labels

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Check IB device name length when parsing policy.
- Use strcmp vs strncmp to compare device names.

v2:
Stephen Smalley:
- Bound check port number when parsing ibendports.
---
 checkpolicy/policy_define.c| 80 ++
 checkpolicy/policy_define.h|  1 +
 checkpolicy/policy_parse.y | 14 +-
 checkpolicy/policy_scan.l  |  2 +
 libsepol/include/sepol/policydb/policydb.h |  9 +++-
 5 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index e73ec8f7..f12ebdbd 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -5164,6 +5164,86 @@ out:
return rc;
 }
 
+int define_ibendport_context(unsigned int port)
+{
+   ocontext_t *newc, *c, *l, *head;
+   char *id;
+   int rc = 0;
+
+   if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+   yyerror("ibendportcon not supported for target");
+   return -1;
+   }
+
+   if (pass == 1) {
+   id = (char *)queue_remove(id_queue);
+   free(id);
+   parse_security_context(NULL);
+   return 0;
+   }
+
+   if (port > 0xff || port == 0) {
+   yyerror("Invalid ibendport port number, should be 0 < port < 
256");
+   return -1;
+   }
+
+   newc = malloc(sizeof(*newc));
+   if (!newc) {
+   yyerror("out of memory");
+   return -1;
+   }
+   memset(newc, 0, sizeof(*newc));
+
+   newc->u.ibendport.dev_name = queue_remove(id_queue);
+   if (!newc->u.ibendport.dev_name) {
+   yyerror("failed to read infiniband device name.");
+   rc = -1;
+   goto out;
+   }
+
+   if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) {
+   yyerror("infiniband device name exceeds max length of 63.");
+   rc = -1;
+   goto out;
+   }
+
+   newc->u.ibendport.port = port;
+
+   if (parse_security_context(>context[0])) {
+   free(newc);
+   return -1;
+   }
+
+   /* Preserve the matching order specified in the configuration. */
+   head = policydbp->ocontexts[OCON_IBENDPORT];
+   for (l = NULL, c = head; c; l = c, c = c->next) {
+   unsigned int port2;
+
+   port2 = c->u.ibendport.port;
+
+   if (port == port2 &&
+   !strcmp(c->u.ibendport.dev_name,
+newc->u.ibendport.dev_name)) {
+   yyerror2("duplicate ibendportcon entry for %s port %u",
+newc->u.ibendport.dev_name, port);
+   rc = -1;
+   goto out;
+   }
+   }
+
+   if (l)
+   l->next = newc;
+   else
+   policydbp->ocontexts[OCON_IBENDPORT] = newc;
+
+   return 0;
+
+out:
+   free(newc->u.ibendport.dev_name);
+   free(newc);
+   return rc;
+}
+
 int define_netif_context(void)
 {
ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 75e3683b..50a7ba78 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -44,6 +44,7 @@ int define_netif_context(void);
 int define_permissive(void);
 int define_polcap(void);
 int define_ibpkey_context(unsigned int low, unsigned int high);
+int define_ibendport_context(unsigned int port);
 int define_port_context(unsigned int low, unsigned int high);
 int define_pirq_context(unsigned int pirq);
 int define_iomem_context(uint64_t low, uint64_t high);
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index 35b433bd..6b406c85 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -137,6 +137,7 @@ typedef int (* require_func_t)(int pass);
 %token SAMEUSER
 %token FSCON PORTCON NETIFCON NODECON 
 %token IBPKEYCON
+%token IBENDPORTCON
 %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
 %token FSUSEXATTR FSUSETASK FSUSETRANS
 %token GENFSCON
@@ -172,7 +173,7 @@ base_policy : { if (define_policy(pass, 0) == 
-1) return -1; }
  opt_default_rules opt_mls te_rbac users 
opt_constraints 
  { if (pass == 1) { if 
(policydb_index_bools(policydbp)) return -1;}
   else if (pass == 2) { if 
(policydb_index_others(NULL, policydbp, 0)) return -1;}}
- initial_sid_contexts opt_fs_contexts opt_fs_uses 
opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts
+ initial_sid_contexts opt_fs_contexts 

[PATCH v2 9/9] semanage: Update man pages for infiniband

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/python/semanage/semanage-ibendport.8 
b/python/semanage/semanage-ibendport.8
new file mode 100644
index ..c3753a27
--- /dev/null
+++ b/python/semanage/semanage-ibendport.8
@@ -0,0 +1,66 @@
+.TH "semanage-ibendport" "8" "20170508" "" ""
+.SH "NAME"
+.B semanage\-ibendport \- SELinux Policy Management ibendport mapping tool
+.SH "SYNOPSIS"
+.B semanage ibendport [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add \-t TYPE \-z 
IBDEV_NAME \-r RANGE port | \-\-delete \-z IBDEV_NAME port | \-\-deleteall  | 
\-\-extract  | \-\-list [\-C] | \-\-modify \-t TYPE \-z IBDEV_NAME \-r RANGE 
port ]
+
+.SH "DESCRIPTION"
+semanage is used to configure certain elements of SELinux policy without 
requiring modification to or recompilation from policy sources.  semanage 
ibendport controls the ibendport number to ibendport type definitions.
+
+.SH "OPTIONS"
+.TP
+.I  \-h, \-\-help
+show this help message and exit
+.TP
+.I   \-n, \-\-noheading
+Do not print heading when listing the specified object type
+.TP
+.I   \-N, \-\-noreload
+Do not reload policy after commit
+.TP
+.I   \-S STORE, \-\-store STORE
+Select an alternate SELinux Policy Store to manage
+.TP
+.I   \-C, \-\-locallist
+List local customizations
+.TP
+.I   \-a, \-\-add
+Add a record of the specified object type
+.TP
+.I   \-d, \-\-delete
+Delete a record of the specified object type
+.TP
+.I   \-m, \-\-modify
+Modify a record of the specified object type
+.TP
+.I   \-l, \-\-list
+List records of the specified object type
+.TP
+.I   \-E, \-\-extract
+Extract customizable commands, for use within a transaction
+.TP
+.I   \-D, \-\-deleteall
+Remove all local customizations
+.TP
+.I   \-t TYPE, \-\-type TYPE
+SELinux type for the object
+.TP
+.I   \-r RANGE, \-\-range RANGE
+MLS/MCS Security Range (MLS/MCS Systems only) SELinux Range for SELinux login 
mapping defaults to the SELinux user record range. SELinux Range for SELinux 
user defaults to s0.
+.TP
+.I \-z IBDEV_NAME, \-\-ibdev_name IBDEV_NAME
+The name of the infiniband device for the port to be labeled.  (ex. mlx5_0)
+
+.SH EXAMPLE
+.nf
+List all ibendport definitions
+# semanage ibendport \-l
+Label mlx4_0 port 2.
+# semanage ibendport \-a \-t allowed_ibendport_t \-z mlx4_0 2
+
+.SH "SEE ALSO"
+.BR selinux (8),
+.BR semanage (8)
+
+.SH "AUTHOR"
+This man page was written by Daniel Walsh 
diff --git a/python/semanage/semanage-ibpkey.8 
b/python/semanage/semanage-ibpkey.8
new file mode 100644
index ..2da4f546
--- /dev/null
+++ b/python/semanage/semanage-ibpkey.8
@@ -0,0 +1,66 @@
+.TH "semanage-ibpkey" "8" "20170508" "" ""
+.SH "NAME"
+.B semanage\-ibpkey \- SELinux Policy Management ibpkey mapping tool
+.SH "SYNOPSIS"
+.B semanage ibpkey [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add \-t TYPE \-x 
SUBNET_PREFIX \-r RANGE ibpkey_name | ibpkey_range | \-\-delete \-x 
SUBNET_PREFIX ibpkey_name | ibpkey_range | \-\-deleteall  | \-\-extract  | 
\-\-list [\-C] | \-\-modify \-t TYPE \-x SUBNET_PREFIX \-r RANGE ibpkey_name | 
ibpkey_range ]
+
+.SH "DESCRIPTION"
+semanage is used to configure certain elements of SELinux policy without 
requiring modification to or recompilation from policy sources.  semanage 
ibpkey controls the ibpkey number to ibpkey type definitions.
+
+.SH "OPTIONS"
+.TP
+.I  \-h, \-\-help
+show this help message and exit
+.TP
+.I   \-n, \-\-noheading
+Do not print heading when listing the specified object type
+.TP
+.I   \-N, \-\-noreload
+Do not reload policy after commit
+.TP
+.I   \-S STORE, \-\-store STORE
+Select an alternate SELinux Policy Store to manage
+.TP
+.I   \-C, \-\-locallist
+List local customizations
+.TP
+.I   \-a, \-\-add
+Add a record of the specified object type
+.TP
+.I   \-d, \-\-delete
+Delete a record of the specified object type
+.TP
+.I   \-m, \-\-modify
+Modify a record of the specified object type
+.TP
+.I   \-l, \-\-list
+List records of the specified object type
+.TP
+.I   \-E, \-\-extract
+Extract customizable commands, for use within a transaction
+.TP
+.I   \-D, \-\-deleteall
+Remove all local customizations
+.TP
+.I   \-t TYPE, \-\-type TYPE
+SELinux type for the object
+.TP
+.I   \-r RANGE, \-\-range RANGE
+MLS/MCS Security Range (MLS/MCS Systems only) SELinux Range for SELinux login 
mapping defaults to the SELinux user record range. SELinux Range for SELinux 
user defaults to s0.
+.TP
+.I \-x SUBNET_PREFIX, \-\-subnet_prefix SUBNET_PREFIX
+Subnet prefix for the specified pkey or 

[PATCH v2 8/9] semanage: Update semanage to allow runtime labeling of ibendports

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Jason Zaman:
- Use SETools directly to query types in seobject.py

v2:
Jason Zaman:
- Use set instead of sorted for valid_types.

Stephen Smalley:
- Fix semanage when ibendport_type attribute isn't defined.
---
 libsemanage/include/semanage/ibendport_record.h  |  62 +
 libsemanage/include/semanage/ibendports_local.h  |  36 +++
 libsemanage/include/semanage/ibendports_policy.h |  28 +++
 libsemanage/include/semanage/semanage.h  |   3 +
 libsemanage/src/direct_api.c |  40 ++-
 libsemanage/src/handle.h |  38 ++-
 libsemanage/src/ibendport_internal.h |  48 
 libsemanage/src/ibendport_record.c   | 154 
 libsemanage/src/ibendports_file.c| 157 
 libsemanage/src/ibendports_local.c   | 153 
 libsemanage/src/ibendports_policy.c  |  55 +
 libsemanage/src/ibendports_policydb.c|  62 +
 libsemanage/src/libsemanage.map  |   1 +
 libsemanage/src/policy_components.c  |   4 +
 libsemanage/src/semanage_store.c |   1 +
 libsemanage/src/semanage_store.h |   1 +
 libsemanage/src/semanageswig.i   |   3 +
 libsemanage/src/semanageswig_python.i|  43 
 libsemanage/utils/semanage_migrate_store |   3 +-
 libsepol/include/sepol/ibendport_record.h|  68 ++
 libsepol/include/sepol/ibendports.h  |  45 
 libsepol/include/sepol/sepol.h   |   2 +
 libsepol/src/ibendport_internal.h|  18 ++
 libsepol/src/ibendport_record.c  | 298 +++
 libsepol/src/ibendports.c| 255 +++
 python/semanage/semanage |  58 -
 python/semanage/seobject.py  | 239 ++
 27 files changed, 1854 insertions(+), 21 deletions(-)
 create mode 100644 libsemanage/include/semanage/ibendport_record.h
 create mode 100644 libsemanage/include/semanage/ibendports_local.h
 create mode 100644 libsemanage/include/semanage/ibendports_policy.h
 create mode 100644 libsemanage/src/ibendport_internal.h
 create mode 100644 libsemanage/src/ibendport_record.c
 create mode 100644 libsemanage/src/ibendports_file.c
 create mode 100644 libsemanage/src/ibendports_local.c
 create mode 100644 libsemanage/src/ibendports_policy.c
 create mode 100644 libsemanage/src/ibendports_policydb.c
 create mode 100644 libsepol/include/sepol/ibendport_record.h
 create mode 100644 libsepol/include/sepol/ibendports.h
 create mode 100644 libsepol/src/ibendport_internal.h
 create mode 100644 libsepol/src/ibendport_record.c
 create mode 100644 libsepol/src/ibendports.c

diff --git a/libsemanage/include/semanage/ibendport_record.h 
b/libsemanage/include/semanage/ibendport_record.h
new file mode 100644
index ..153eea02
--- /dev/null
+++ b/libsemanage/include/semanage/ibendport_record.h
@@ -0,0 +1,62 @@
+/*Copyright (C) 2005 Red Hat, Inc. */
+
+#ifndef _SEMANAGE_IBENDPORT_RECORD_H_
+#define _SEMANAGE_IBENDPORT_RECORD_H_
+
+#include 
+#include 
+#include 
+
+#ifndef _SEMANAGE_IBENDPORT_DEFINED_
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport semanage_ibendport_t;
+typedef struct semanage_ibendport_key semanage_ibendport_key_t;
+#define _SEMANAGE_IBENDPORT_DEFINED_
+#endif
+
+extern int semanage_ibendport_compare(const semanage_ibendport_t *ibendport,
+ const semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport,
+  const semanage_ibendport_t *ibendport2);
+
+extern int semanage_ibendport_key_create(semanage_handle_t *handle,
+const char *ibdev_name,
+int port,
+semanage_ibendport_key_t **key_ptr);
+
+extern int semanage_ibendport_key_extract(semanage_handle_t *handle,
+ const semanage_ibendport_t *ibendport,
+ semanage_ibendport_key_t **key_ptr);
+
+extern void semanage_ibendport_key_free(semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle,
+const semanage_ibendport_t 
*ibendport,
+char **ibdev_name_ptr);
+
+extern int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle,
+ 

[PATCH v2 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Fixed semanage_pkey_exists -> semanage_ibpkey_exists in delete flow in
seobject.py

Stephen Smalley:
- Subnet prefix can't vary in size always 16 bytes, remove size field.
- Removed extraneous change in libsepol/VERSION
- Removed ifdef DARWIN s6_addr/32 blocks in favor of s6_addr.
- Got rid of magic constant for subnet prefix size.

Jason Zaman:
- Use SETools directly to query types in seobject.py.

v2:
Jason Zaman:
- Use set instead of sorted for valid_types.

Stephen Smalley:
- Fix semanage when ibpkey_type attribute isn't defined.
- Store subnet prefix in 8 bytes.
- Removed a missed #if DARWIN
- Use sizeof(struct in6_addr) vs a define.
---
 libsemanage/include/semanage/ibpkey_record.h  |  74 +
 libsemanage/include/semanage/ibpkeys_local.h  |  36 +++
 libsemanage/include/semanage/ibpkeys_policy.h |  28 ++
 libsemanage/include/semanage/semanage.h   |   3 +
 libsemanage/src/direct_api.c  |  29 +-
 libsemanage/src/handle.h  |  36 ++-
 libsemanage/src/ibpkey_internal.h |  52 +++
 libsemanage/src/ibpkey_record.c   | 185 +++
 libsemanage/src/ibpkeys_file.c| 181 +++
 libsemanage/src/ibpkeys_local.c   | 179 +++
 libsemanage/src/ibpkeys_policy.c  |  52 +++
 libsemanage/src/ibpkeys_policydb.c|  62 
 libsemanage/src/libsemanage.map   |   1 +
 libsemanage/src/policy_components.c   |   5 +-
 libsemanage/src/semanage_store.c  |   1 +
 libsemanage/src/semanage_store.h  |   1 +
 libsemanage/src/semanageswig.i|   3 +
 libsemanage/src/semanageswig_python.i |  43 +++
 libsemanage/utils/semanage_migrate_store  |   3 +-
 libsepol/include/sepol/ibpkey_record.h|  77 +
 libsepol/include/sepol/ibpkeys.h  |  44 +++
 libsepol/include/sepol/sepol.h|   2 +
 libsepol/src/ibpkey_internal.h|  21 ++
 libsepol/src/ibpkey_record.c  | 445 ++
 libsepol/src/ibpkeys.c| 269 
 python/semanage/semanage  |  60 +++-
 python/semanage/seobject.py   | 255 +++
 27 files changed, 2131 insertions(+), 16 deletions(-)
 create mode 100644 libsemanage/include/semanage/ibpkey_record.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_local.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_policy.h
 create mode 100644 libsemanage/src/ibpkey_internal.h
 create mode 100644 libsemanage/src/ibpkey_record.c
 create mode 100644 libsemanage/src/ibpkeys_file.c
 create mode 100644 libsemanage/src/ibpkeys_local.c
 create mode 100644 libsemanage/src/ibpkeys_policy.c
 create mode 100644 libsemanage/src/ibpkeys_policydb.c
 create mode 100644 libsepol/include/sepol/ibpkey_record.h
 create mode 100644 libsepol/include/sepol/ibpkeys.h
 create mode 100644 libsepol/src/ibpkey_internal.h
 create mode 100644 libsepol/src/ibpkey_record.c
 create mode 100644 libsepol/src/ibpkeys.c

diff --git a/libsemanage/include/semanage/ibpkey_record.h 
b/libsemanage/include/semanage/ibpkey_record.h
new file mode 100644
index ..59d5ff4a
--- /dev/null
+++ b/libsemanage/include/semanage/ibpkey_record.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+#ifndef _SEMANAGE_IBPKEY_RECORD_H_
+#define _SEMANAGE_IBPKEY_RECORD_H_
+
+#include 
+#include 
+#include 
+
+#ifndef _SEMANAGE_IBPKEY_DEFINED_
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey semanage_ibpkey_t;
+typedef struct semanage_ibpkey_key semanage_ibpkey_key_t;
+#define _SEMANAGE_IBPKEY_DEFINED_
+#endif
+
+extern int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
+  const semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
+   const semanage_ibpkey_t *ibpkey2);
+
+extern int semanage_ibpkey_key_create(semanage_handle_t *handle,
+ const char *subnet_prefix,
+ int low, int high,
+ semanage_ibpkey_key_t **key_ptr);
+
+extern int semanage_ibpkey_key_extract(semanage_handle_t *handle,
+  const semanage_ibpkey_t *ibpkey,
+  semanage_ibpkey_key_t **key_ptr);
+
+extern void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle,
+const 

[PATCH v2 3/9] libsepol: Add Infiniband Pkey handling to CIL

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 9b9ccc36..3df670a7 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -188,6 +188,7 @@ static void cil_init_keys(void)
CIL_KEY_MLSVALIDATETRANS = cil_strpool_add("mlsvalidatetrans");
CIL_KEY_CONTEXT = cil_strpool_add("context");
CIL_KEY_FILECON = cil_strpool_add("filecon");
+   CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon");
CIL_KEY_PORTCON = cil_strpool_add("portcon");
CIL_KEY_NODECON = cil_strpool_add("nodecon");
CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -257,6 +258,7 @@ void cil_db_init(struct cil_db **db)
cil_sort_init(&(*db)->genfscon);
cil_sort_init(&(*db)->filecon);
cil_sort_init(&(*db)->nodecon);
+   cil_sort_init(&(*db)->ibpkeycon);
cil_sort_init(&(*db)->portcon);
cil_sort_init(&(*db)->pirqcon);
cil_sort_init(&(*db)->iomemcon);
@@ -308,6 +310,7 @@ void cil_db_destroy(struct cil_db **db)
cil_sort_destroy(&(*db)->genfscon);
cil_sort_destroy(&(*db)->filecon);
cil_sort_destroy(&(*db)->nodecon);
+   cil_sort_destroy(&(*db)->ibpkeycon);
cil_sort_destroy(&(*db)->portcon);
cil_sort_destroy(&(*db)->pirqcon);
cil_sort_destroy(&(*db)->iomemcon);
@@ -728,6 +731,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_FILECON:
cil_destroy_filecon(*data);
break;
+   case CIL_IBPKEYCON:
+   cil_destroy_ibpkeycon(*data);
+   break;
case CIL_PORTCON:
cil_destroy_portcon(*data);
break;
@@ -1097,6 +1103,8 @@ const char * cil_node_to_string(struct cil_tree_node 
*node)
return CIL_KEY_FSUSE;
case CIL_FILECON:
return CIL_KEY_FILECON;
+   case CIL_IBPKEYCON:
+   return CIL_KEY_IBPKEYCON;
case CIL_PORTCON:
return CIL_KEY_PORTCON;
case CIL_NODECON:
@@ -2255,6 +2263,17 @@ void cil_filecon_init(struct cil_filecon **filecon)
(*filecon)->context = NULL;
 }
 
+void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon)
+{
+   *ibpkeycon = cil_malloc(sizeof(**ibpkeycon));
+
+   (*ibpkeycon)->subnet_prefix_str = NULL;
+   (*ibpkeycon)->pkey_low = 0;
+   (*ibpkeycon)->pkey_high = 0;
+   (*ibpkeycon)->context_str = NULL;
+   (*ibpkeycon)->context = NULL;
+}
+
 void cil_portcon_init(struct cil_portcon **portcon)
 {
*portcon = cil_malloc(sizeof(**portcon));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index e1481a43..1ddbf21f 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3218,6 +3218,40 @@ exit:
return rc;
 }
 
+int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons)
+{
+   int rc = SEPOL_ERR;
+   uint32_t i = 0;
+   ocontext_t *tail = NULL;
+   struct in6_addr subnet_prefix;
+
+   for (i = 0; i < ibpkeycons->count; i++) {
+   struct cil_ibpkeycon *cil_ibpkeycon = ibpkeycons->array[i];
+   ocontext_t *new_ocon = 
cil_add_ocontext(>ocontexts[OCON_IBPKEY], );
+
+   rc = inet_pton(AF_INET6, cil_ibpkeycon->subnet_prefix_str, 
_prefix);
+   if (rc != 1) {
+   cil_log(CIL_ERR, "ibpkeycon subnet prefix not in valid 
IPV6 format\n");
+   rc = SEPOL_ERR;
+   goto exit;
+   }
+
+   memcpy(_ocon->u.ibpkey.subnet_prefix, 
_prefix.s6_addr[0],
+  sizeof(new_ocon->u.ibpkey.subnet_prefix));
+   new_ocon->u.ibpkey.low_pkey = cil_ibpkeycon->pkey_low;
+   new_ocon->u.ibpkey.high_pkey = cil_ibpkeycon->pkey_high;
+
+   rc = __cil_context_to_sepol_context(pdb, 

[PATCH v2 2/9] libsepol: Add ibpkey ocontext handling

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Removed domain and type params from sepol_ibpkey_sid.
- Removed splen param from sepol_ibpkey_sid, it never varied.
- Removed extra XPERMS_IOCTL version from policydb_compat_info.
- Confirm that low order bytes of IPv6 addr for subnet prefix is 0's.

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

v2:
Stephen Smalley:
- Store subnet prefix as 8 bytes. This mooted a couple other comments
  about checking and forcing 0's in the lower 8 bytes.
- Bounds check PKeys values in ocontext_read_selinux.

James Carter:
- Add sorting of pkey ocontexts in kernel_to_common.c
---
 checkpolicy/checkpolicy.c  | 27 +
 libsepol/include/sepol/policydb/services.h |  8 
 libsepol/src/expand.c  |  7 
 libsepol/src/kernel_to_cil.c   | 62 +
 libsepol/src/kernel_to_common.c| 19 +
 libsepol/src/kernel_to_conf.c  | 63 ++
 libsepol/src/libsepol.map.in   |  1 +
 libsepol/src/module_to_cil.c   | 41 +++
 libsepol/src/policydb.c| 37 ++
 libsepol/src/services.c| 37 ++
 libsepol/src/write.c   | 16 
 11 files changed, 318 insertions(+)

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 534fc22e..8aeecc1b 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -22,6 +22,7 @@
  *
  * Policy Module support.
  *
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2005 Tresys Technology, LLC
  * Copyright (C) 2003 Red Hat, Inc., James Morris 
@@ -699,6 +700,7 @@ int main(int argc, char **argv)
printf("h)  change a boolean value\n");
printf("i)  display constraint expressions\n");
printf("j)  display validatetrans expressions\n");
+   printf("k)  Call ibpkey_sid\n");
 #ifdef EQUIVTYPES
printf("z)  Show equivalent types\n");
 #endif
@@ -1220,6 +1222,31 @@ int main(int argc, char **argv)
"\nNo validatetrans expressions found.\n");
}
break;
+   case 'k':
+   {
+   char *p;
+   struct in6_addr addr6;
+   uint64_t subnet_prefix;
+   unsigned int pkey;
+
+   printf("subnet prefix?  ");
+   FGETS(ans, sizeof(ans), stdin);
+   ans[strlen(ans) - 1] = 0;
+   p = (char *)
+
+   if (inet_pton(AF_INET6, ans, p) < 1) {
+   printf("error parsing subnet prefix\n");
+   break;
+   }
+
+   memcpy(_prefix, p, 
sizeof(subnet_prefix));
+   printf("pkey? ");
+   FGETS(ans, sizeof(ans), stdin);
+   pkey = atoi(ans);
+   sepol_ibpkey_sid(subnet_prefix, pkey, );
+   printf("sid %d\n", ssid);
+   }
+   break;
 #ifdef EQUIVTYPES
case 'z':
identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h 
b/libsepol/include/sepol/policydb/services.h
index 9162149a..3f3b95d1 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -188,6 +188,14 @@ extern int sepol_port_sid(uint16_t domain,
  uint16_t port, sepol_security_id_t * out_sid);
 
 /*
+ * Return the SID of the ibpkey specified by
+ * `subnet prefix', and `pkey'.
+ */
+extern int sepol_ibpkey_sid(uint64_t subnet_prefix_p,
+   uint16_t pkey,
+   sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 54bf781d..e4cfc41e 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2004-2005 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2017 Mellanox Technologies, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  

[PATCH v2 1/9] checkpolicy: Add support for ibpkeycon labels

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Always use s6_addr instead of s6_addr32.
- Add comment about POLICYDB_VERSION_INFINIBAND being linux specific.

v2:
Stephen Smalley:
- Store subnet_prefix as 8 bytes.
---
 checkpolicy/policy_define.c| 107 +
 checkpolicy/policy_define.h|   1 +
 checkpolicy/policy_parse.y |  15 +++-
 checkpolicy/policy_scan.l  |   3 +
 libsepol/include/sepol/policydb/policydb.h |  30 +---
 5 files changed, 144 insertions(+), 12 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 8fab214b..e73ec8f7 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -20,6 +20,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2008 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2017 Mellanox Techonologies Inc.
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 2.
@@ -5057,6 +5058,112 @@ int define_port_context(unsigned int low, unsigned int 
high)
return -1;
 }
 
+int define_ibpkey_context(unsigned int low, unsigned int high)
+{
+   ocontext_t *newc, *c, *l, *head;
+   struct in6_addr subnet_prefix;
+   char *id;
+   int rc = 0;
+
+   if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+   yyerror("ibpkeycon not supported for target");
+   return -1;
+   }
+
+   if (pass == 1) {
+   id = (char *)queue_remove(id_queue);
+   free(id);
+   parse_security_context(NULL);
+   return 0;
+   }
+
+   newc = malloc(sizeof(*newc));
+   if (!newc) {
+   yyerror("out of memory");
+   return -1;
+   }
+   memset(newc, 0, sizeof(*newc));
+
+   id = queue_remove(id_queue);
+   if (!id) {
+   yyerror("failed to read the subnet prefix");
+   rc = -1;
+   goto out;
+   }
+
+   rc = inet_pton(AF_INET6, id, _prefix);
+   free(id);
+   if (rc < 1) {
+   yyerror("failed to parse the subnet prefix");
+   if (rc == 0)
+   rc = -1;
+   goto out;
+   }
+
+   if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) {
+   yyerror("subnet prefix should be 0's in the low order 64 
bits.");
+   rc = -1;
+   goto out;
+   }
+
+   if (low > 0x || high > 0x) {
+   yyerror("pkey value too large, pkeys are 16 bits.");
+   rc = -1;
+   goto out;
+   }
+
+   memcpy(>u.ibpkey.subnet_prefix, _prefix.s6_addr[0],
+  sizeof(newc->u.ibpkey.subnet_prefix));
+
+   newc->u.ibpkey.low_pkey = low;
+   newc->u.ibpkey.high_pkey = high;
+
+   if (low > high) {
+   yyerror2("low pkey %d exceeds high pkey %d", low, high);
+   rc = -1;
+   goto out;
+   }
+
+   rc = parse_security_context(>context[0]);
+   if (rc)
+   goto out;
+
+   /* Preserve the matching order specified in the configuration. */
+   head = policydbp->ocontexts[OCON_IBPKEY];
+   for (l = NULL, c = head; c; l = c, c = c->next) {
+   unsigned int low2, high2;
+
+   low2 = c->u.ibpkey.low_pkey;
+   high2 = c->u.ibpkey.high_pkey;
+
+   if (low == low2 && high == high2 &&
+   c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
+   yyerror2("duplicate ibpkeycon entry for %d-%d ",
+low, high);
+   rc = -1;
+   goto out;
+   }
+   if (low2 <= low && high2 >= high &&
+   c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
+   yyerror2("ibpkeycon entry for %d-%d hidden by earlier 
entry for %d-%d",
+low, high, low2, high2);
+   rc = -1;
+   goto out;
+   }
+   }
+
+   if (l)
+   l->next = newc;
+   else
+   policydbp->ocontexts[OCON_IBPKEY] = newc;
+
+   return 0;
+
+out:
+   free(newc);
+   return rc;
+}
+
 int define_netif_context(void)
 {
ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 9f4b6d0d..75e3683b 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h

[PATCH v2 5/9] libsepol: Add ibendport ocontext handling

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

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

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

v2:
James Carter
- Sort ocontexts in kernel_to_common.c
---
 checkpolicy/checkpolicy.c  | 20 ++
 libsepol/include/sepol/policydb/services.h |  8 ++
 libsepol/src/expand.c  |  8 ++
 libsepol/src/kernel_to_cil.c   | 42 ++
 libsepol/src/kernel_to_common.c| 18 +
 libsepol/src/kernel_to_conf.c  | 41 +
 libsepol/src/libsepol.map.in   |  1 +
 libsepol/src/module_to_cil.c   | 14 ++
 libsepol/src/policydb.c| 26 +++---
 libsepol/src/services.c| 37 ++
 libsepol/src/write.c   | 14 ++
 11 files changed, 226 insertions(+), 3 deletions(-)

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 8aeecc1b..b75f2afa 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -701,6 +701,7 @@ int main(int argc, char **argv)
printf("i)  display constraint expressions\n");
printf("j)  display validatetrans expressions\n");
printf("k)  Call ibpkey_sid\n");
+   printf("l)  Call ibendport_sid\n");
 #ifdef EQUIVTYPES
printf("z)  Show equivalent types\n");
 #endif
@@ -1247,6 +1248,25 @@ int main(int argc, char **argv)
printf("sid %d\n", ssid);
}
break;
+   case 'l':
+   printf("device name (eg. mlx4_0)?  ");
+   FGETS(ans, sizeof(ans), stdin);
+   ans[strlen(ans) - 1] = 0;
+
+   name = malloc((strlen(ans) + 1) * sizeof(char));
+   if (!name) {
+   fprintf(stderr, "couldn't malloc string.\n");
+   break;
+   }
+   strcpy(name, ans);
+
+   printf("port? ");
+   FGETS(ans, sizeof(ans), stdin);
+   port = atoi(ans);
+   sepol_ibendport_sid(name, port, );
+   printf("sid %d\n", ssid);
+   free(name);
+   break;
 #ifdef EQUIVTYPES
case 'z':
identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h 
b/libsepol/include/sepol/policydb/services.h
index 3f3b95d1..efdf7de5 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -196,6 +196,14 @@ extern int sepol_ibpkey_sid(uint64_t subnet_prefix_p,
sepol_security_id_t *out_sid);
 
 /*
+ * Return the SID of the ibendport specified by
+ * `dev_name', and `port'.
+ */
+extern int sepol_ibendport_sid(char *dev_name,
+  uint8_t port,
+  sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index e4cfc41e..8f7a25d8 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -2224,6 +2224,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey;
n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey;
break;
+   case OCON_IBENDPORT:
+   n->u.ibendport.dev_name = 
strdup(c->u.ibendport.dev_name);
+   if (!n->u.ibendport.dev_name) {
+   ERR(state->handle, "Out of memory!");
+   return -1;
+   }
+   n->u.ibendport.port = c->u.ibendport.port;
+   break;
case OCON_PORT:
n->u.port.protocol = c->u.port.protocol;
n->u.port.low_port = c->u.port.low_port;
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index d1006186..f4ec8832 100644
--- a/libsepol/src/kernel_to_cil.c
+++ 

[PATCH v2 0/9] SELinux user space support for Infiniband RDMA

2017-05-18 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

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

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

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

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

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

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

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

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

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

---
v1:
- Fixed seobject ibpkey delete all name bug (pkey vs ibpkey).

Stephen Smalley:
- Always use s6_addr vs s6_addr32, remove DARWIN #ifdefs.
- Removed unused parameters from new sepol_*_sid functions.
- Got rid of variable length subnet prefix handling, it never varied. 

James Carter:
- Add kernel_to_cil and kernel_to_conf implementations for new OCONs.

Jason Zaman:
- Use SETools directly to query types by attribute in seobject.py.


- See individual patches for more detailed changes.

v2:
- Rebased over Stephens MOD_VERSION change.

Stephen Smalley:
- Bound check new ocontext fields
- Only store 8 bytes of subnet prefix in binary policy
- Make it so semanage doesn't crash if ipbkey_type or ibendport_type are
  undefined.
- Don't define INET6_ADDRLEN, use sizeof(struct in6_addr)

James Carter:
- Sort new ocontexts in kernel_to_common.c

- Additional smaller changes noted in specific patches.

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

 checkpolicy/checkpolicy.c|  47 +++
 checkpolicy/policy_define.c  | 187 +
 checkpolicy/policy_define.h  |   2 +
 checkpolicy/policy_parse.y   |  27 +-
 checkpolicy/policy_scan.l|   5 +
 libsemanage/include/semanage/ibendport_record.h  |  62 +++
 libsemanage/include/semanage/ibendports_local.h  |  36 ++
 libsemanage/include/semanage/ibendports_policy.h |  28 ++
 libsemanage/include/semanage/ibpkey_record.h |  74 
 libsemanage/include/semanage/ibpkeys_local.h |  36 ++
 libsemanage/include/semanage/ibpkeys_policy.h|  28 ++
 libsemanage/include/semanage/semanage.h  |   6 +
 libsemanage/src/direct_api.c |  57 ++-
 libsemanage/src/handle.h | 

[PATCH 2/2] selinux-testsuite: Infiniband endport tests

2017-05-17 Thread Dan Jurgens
From: Daniel Jurgens 

New tests for Infiniband endports. Most users do not have infiniband
hardware, and if they do the device names can vary.  There is a
configuration file for enabling the tests and setting environment
specific configurations.  If the tests are disabled they always show as
passed.

A special test application was unnecessary, a standard diagnostic
application is used instead.  This required a change to the make file
to avoid trying to build an application in the new subdir.

Signed-off-by: Daniel Jurgens 
---
 README   |  7 +++-
 policy/Makefile  |  2 +-
 policy/test_ibendport.te | 37 +
 tests/Makefile   |  4 ++-
 tests/infiniband_endport/ibendport_test.conf | 14 
 tests/infiniband_endport/test| 49 
 6 files changed, 110 insertions(+), 3 deletions(-)
 create mode 100644 policy/test_ibendport.te
 create mode 100644 tests/infiniband_endport/ibendport_test.conf
 create mode 100644 tests/infiniband_endport/test

diff --git a/README b/README
index b64e2de..8e1b391 100644
--- a/README
+++ b/README
@@ -200,7 +200,12 @@ INFINIBAND TESTS
 
 Because running Infiniband tests requires specialized hardware you must
 set up a configuration file for these tests. The tests are disabled by
-default.  See comments in the configuration file for info.
+default.  See comments in the configuration file for info. The endport
+tests use smpquery, for Fedora it's provided by the infiniband-diags
+package.
 
 Infiniband PKey test conf file:
 tests/infiniband_pkey/ibpkey_test.conf
+
+Infiniband Endport test conf file:
+tests/infiniband_endport/ibendport_test.conf
diff --git a/policy/Makefile b/policy/Makefile
index ab58d3b..dcefdb5 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -21,7 +21,7 @@ TARGETS = \
test_task_getsid.te test_task_setpgid.te test_task_setsched.te \
test_transition.te test_inet_socket.te test_unix_socket.te \
test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te \
-   test_ibpkey.te
+   test_ibpkey.te test_ibendport.te
 
 ifeq ($(shell [ $(POL_VERS) -ge 24 ] && echo true),true)
 TARGETS += test_bounds.te
diff --git a/policy/test_ibendport.te b/policy/test_ibendport.te
new file mode 100644
index 000..9f0294d
--- /dev/null
+++ b/policy/test_ibendport.te
@@ -0,0 +1,37 @@
+#
+#
+# Policy for testing Infiniband Pkey access.
+#
+
+gen_require(`
+   type bin_t;
+   type infiniband_mgmt_device_t;
+')
+
+attribute ibendportdomain;
+
+# Domain for process.
+type test_ibendport_manage_subnet_t;
+domain_type(test_ibendport_manage_subnet_t)
+unconfined_runs_test(test_ibendport_manage_subnet_t)
+typeattribute test_ibendport_manage_subnet_t testdomain;
+typeattribute test_ibendport_manage_subnet_t ibendportdomain;
+
+type test_ibendport_t;
+corenet_ibendport(test_ibendport_t)
+
+dev_rw_infiniband_dev(test_ibendport_manage_subnet_t)
+dev_rw_sysfs(test_ibendport_manage_subnet_t)
+
+allow test_ibendport_manage_subnet_t bin_t:file entrypoint;
+allow test_ibendport_manage_subnet_t bin_t:file execute;
+allow test_ibendport_manage_subnet_t infiniband_mgmt_device_t:chr_file { read 
write open ioctl};
+allow test_ibendport_manage_subnet_t default_ibpkey_t:infiniband_pkey access;
+corenet_ibpkey_access_default_pkey(test_ibendport_manage_subnet_t)
+
+
+allow test_ibendport_manage_subnet_t test_ibendport_t:infiniband_endport 
manage_subnet;
+
+# Allow all of these domains to be entered from the sysadm domain.
+miscfiles_domain_entry_test_files(ibendportdomain)
+userdom_sysadm_entry_spec_domtrans_to(ibendportdomain)
diff --git a/tests/Makefile b/tests/Makefile
index 7dfe2a8..63e6f57 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -12,6 +12,8 @@ SUBDIRS:= domain_trans entrypoint execshare exectrace 
execute_no_trans \
capable_sys dyntrans dyntrace bounds nnp mmap unix_socket inet_socket \
overlay checkreqprot mqueue mac_admin infiniband_pkey
 
+SUBDIRS_NO_MAKE:= infiniband_endport
+
 ifeq ($(shell grep -q cap_userns $(POLDEV)/include/support/all_perms.spt && 
echo true),true)
 ifneq ($(shell ./kvercmp $$(uname -r) 4.7),-1)
 SUBDIRS += cap_userns
@@ -56,7 +58,7 @@ all:
 
 test: all
chcon -R -t test_file_t .
-   @SUBDIRS="$(SUBDIRS)" PATH=/usr/bin:/bin:/usr/sbin:/sbin ./runtests.pl
+   @SUBDIRS="$(SUBDIRS) $(SUBDIRS_NO_MAKE)" 
PATH=/usr/bin:/bin:/usr/sbin:/sbin ./runtests.pl
 
 clean:
@for subdir in $(SUBDIRS); do \
diff --git a/tests/infiniband_endport/ibendport_test.conf 
b/tests/infiniband_endport/ibendport_test.conf
new file mode 100644
index 000..601b290
--- /dev/null
+++ b/tests/infiniband_endport/ibendport_test.conf
@@ -0,0 +1,14 @@
+# Enable(1)/Disable these tests.
+SELINUX_INFINIBAND_ENDPORT_TEST=0
+
+# Device/port pair that should allow 

[PATCH 1/2] selinux-testsuite: Infiniband pkey tests

2017-05-17 Thread Dan Jurgens
From: Daniel Jurgens 

New tests for infiniband pkeys. Most users don't have Infiniband
hardware, and if they do the pkey configuration is not standardized.
There is a configuration file for enabling the test and setting
environment specific test configurations. If the tests are disable they
will always show as passed.

Signed-off-by: Daniel Jurgens 
---
 README   |   9 ++
 policy/Makefile  |   3 +-
 policy/test_ibpkey.te|  23 +
 tests/Makefile   |   4 +-
 tests/infiniband_pkey/Makefile   |   7 ++
 tests/infiniband_pkey/create_modify_qp.c | 144 +++
 tests/infiniband_pkey/ibpkey_test.conf   |  14 +++
 tests/infiniband_pkey/test   |  45 ++
 8 files changed, 246 insertions(+), 3 deletions(-)
 create mode 100644 policy/test_ibpkey.te
 create mode 100644 tests/infiniband_pkey/Makefile
 create mode 100644 tests/infiniband_pkey/create_modify_qp.c
 create mode 100644 tests/infiniband_pkey/ibpkey_test.conf
 create mode 100644 tests/infiniband_pkey/test

diff --git a/README b/README
index deedae5..b64e2de 100644
--- a/README
+++ b/README
@@ -195,3 +195,12 @@ establish a base directory (based on the path of the script
 executable).  This won't always be accurate, but will work for this
 test harness/configuration.
$basedir = $0;  $basedir =~ s|(.*)/[^/]*|$1|;
+
+INFINIBAND TESTS
+
+Because running Infiniband tests requires specialized hardware you must
+set up a configuration file for these tests. The tests are disabled by
+default.  See comments in the configuration file for info.
+
+Infiniband PKey test conf file:
+tests/infiniband_pkey/ibpkey_test.conf
diff --git a/policy/Makefile b/policy/Makefile
index 661f27a..ab58d3b 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -20,7 +20,8 @@ TARGETS = \
test_task_create.te test_task_getpgid.te test_task_getsched.te \
test_task_getsid.te test_task_setpgid.te test_task_setsched.te \
test_transition.te test_inet_socket.te test_unix_socket.te \
-   test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te
+   test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te \
+   test_ibpkey.te
 
 ifeq ($(shell [ $(POL_VERS) -ge 24 ] && echo true),true)
 TARGETS += test_bounds.te
diff --git a/policy/test_ibpkey.te b/policy/test_ibpkey.te
new file mode 100644
index 000..0ff6da4
--- /dev/null
+++ b/policy/test_ibpkey.te
@@ -0,0 +1,23 @@
+#
+#
+# Policy for testing Infiniband Pkey access.
+#
+
+attribute ibpkeydomain;
+
+# Domain for process.
+type test_ibpkey_modify_t;
+domain_type(test_ibpkey_modify_t)
+unconfined_runs_test(test_ibpkey_modify_t)
+typeattribute test_ibpkey_modify_t testdomain;
+typeattribute test_ibpkey_modify_t ibpkeydomain;
+
+dev_rw_infiniband_dev(test_ibpkey_modify_t)
+dev_rw_sysfs(test_ibpkey_modify_t)
+
+# client can connect to the server via the socket file or via abstract sockets.
+corenet_ibpkey_access_default_pkey(test_ibpkey_modify_t)
+
+# Allow all of these domains to be entered from the sysadm domain.
+miscfiles_domain_entry_test_files(ibpkeydomain)
+userdom_sysadm_entry_spec_domtrans_to(ibpkeydomain)
diff --git a/tests/Makefile b/tests/Makefile
index fb8a0aa..7dfe2a8 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -4,13 +4,13 @@ export CFLAGS+=-g -O0 -Wall -D_GNU_SOURCE
 
 DISTRO=$(shell ./os_detect)
 
-SUBDIRS:=domain_trans entrypoint execshare exectrace execute_no_trans \
+SUBDIRS:= domain_trans entrypoint execshare exectrace execute_no_trans \
fdreceive inherit link mkdir msg open ptrace readlink relabel rename \
rxdir sem setattr setnice shm sigkill stat sysctl task_create \
task_setnice task_setscheduler task_getscheduler task_getsid \
task_getpgid task_setpgid file ioctl capable_file capable_net \
capable_sys dyntrans dyntrace bounds nnp mmap unix_socket inet_socket \
-   overlay checkreqprot mqueue mac_admin
+   overlay checkreqprot mqueue mac_admin infiniband_pkey
 
 ifeq ($(shell grep -q cap_userns $(POLDEV)/include/support/all_perms.spt && 
echo true),true)
 ifneq ($(shell ./kvercmp $$(uname -r) 4.7),-1)
diff --git a/tests/infiniband_pkey/Makefile b/tests/infiniband_pkey/Makefile
new file mode 100644
index 000..60f0d24
--- /dev/null
+++ b/tests/infiniband_pkey/Makefile
@@ -0,0 +1,7 @@
+TARGETS=create_modify_qp
+
+LDLIBS+= -libverbs
+
+all: $(TARGETS)
+clean:
+   rm -f $(TARGETS)
diff --git a/tests/infiniband_pkey/create_modify_qp.c 
b/tests/infiniband_pkey/create_modify_qp.c
new file mode 100644
index 000..495ef5b
--- /dev/null
+++ b/tests/infiniband_pkey/create_modify_qp.c
@@ -0,0 +1,144 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct ibv_qp *qp;
+struct ibv_context *context;
+struct ibv_pd   

[PATCH v1 9/9] semanage: Update man pages for infiniband

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/python/semanage/semanage-ibendport.8 
b/python/semanage/semanage-ibendport.8
new file mode 100644
index 000..c3753a2
--- /dev/null
+++ b/python/semanage/semanage-ibendport.8
@@ -0,0 +1,66 @@
+.TH "semanage-ibendport" "8" "20170508" "" ""
+.SH "NAME"
+.B semanage\-ibendport \- SELinux Policy Management ibendport mapping tool
+.SH "SYNOPSIS"
+.B semanage ibendport [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add \-t TYPE \-z 
IBDEV_NAME \-r RANGE port | \-\-delete \-z IBDEV_NAME port | \-\-deleteall  | 
\-\-extract  | \-\-list [\-C] | \-\-modify \-t TYPE \-z IBDEV_NAME \-r RANGE 
port ]
+
+.SH "DESCRIPTION"
+semanage is used to configure certain elements of SELinux policy without 
requiring modification to or recompilation from policy sources.  semanage 
ibendport controls the ibendport number to ibendport type definitions.
+
+.SH "OPTIONS"
+.TP
+.I  \-h, \-\-help
+show this help message and exit
+.TP
+.I   \-n, \-\-noheading
+Do not print heading when listing the specified object type
+.TP
+.I   \-N, \-\-noreload
+Do not reload policy after commit
+.TP
+.I   \-S STORE, \-\-store STORE
+Select an alternate SELinux Policy Store to manage
+.TP
+.I   \-C, \-\-locallist
+List local customizations
+.TP
+.I   \-a, \-\-add
+Add a record of the specified object type
+.TP
+.I   \-d, \-\-delete
+Delete a record of the specified object type
+.TP
+.I   \-m, \-\-modify
+Modify a record of the specified object type
+.TP
+.I   \-l, \-\-list
+List records of the specified object type
+.TP
+.I   \-E, \-\-extract
+Extract customizable commands, for use within a transaction
+.TP
+.I   \-D, \-\-deleteall
+Remove all local customizations
+.TP
+.I   \-t TYPE, \-\-type TYPE
+SELinux type for the object
+.TP
+.I   \-r RANGE, \-\-range RANGE
+MLS/MCS Security Range (MLS/MCS Systems only) SELinux Range for SELinux login 
mapping defaults to the SELinux user record range. SELinux Range for SELinux 
user defaults to s0.
+.TP
+.I \-z IBDEV_NAME, \-\-ibdev_name IBDEV_NAME
+The name of the infiniband device for the port to be labeled.  (ex. mlx5_0)
+
+.SH EXAMPLE
+.nf
+List all ibendport definitions
+# semanage ibendport \-l
+Label mlx4_0 port 2.
+# semanage ibendport \-a \-t allowed_ibendport_t \-z mlx4_0 2
+
+.SH "SEE ALSO"
+.BR selinux (8),
+.BR semanage (8)
+
+.SH "AUTHOR"
+This man page was written by Daniel Walsh 
diff --git a/python/semanage/semanage-ibpkey.8 
b/python/semanage/semanage-ibpkey.8
new file mode 100644
index 000..2da4f54
--- /dev/null
+++ b/python/semanage/semanage-ibpkey.8
@@ -0,0 +1,66 @@
+.TH "semanage-ibpkey" "8" "20170508" "" ""
+.SH "NAME"
+.B semanage\-ibpkey \- SELinux Policy Management ibpkey mapping tool
+.SH "SYNOPSIS"
+.B semanage ibpkey [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add \-t TYPE \-x 
SUBNET_PREFIX \-r RANGE ibpkey_name | ibpkey_range | \-\-delete \-x 
SUBNET_PREFIX ibpkey_name | ibpkey_range | \-\-deleteall  | \-\-extract  | 
\-\-list [\-C] | \-\-modify \-t TYPE \-x SUBNET_PREFIX \-r RANGE ibpkey_name | 
ibpkey_range ]
+
+.SH "DESCRIPTION"
+semanage is used to configure certain elements of SELinux policy without 
requiring modification to or recompilation from policy sources.  semanage 
ibpkey controls the ibpkey number to ibpkey type definitions.
+
+.SH "OPTIONS"
+.TP
+.I  \-h, \-\-help
+show this help message and exit
+.TP
+.I   \-n, \-\-noheading
+Do not print heading when listing the specified object type
+.TP
+.I   \-N, \-\-noreload
+Do not reload policy after commit
+.TP
+.I   \-S STORE, \-\-store STORE
+Select an alternate SELinux Policy Store to manage
+.TP
+.I   \-C, \-\-locallist
+List local customizations
+.TP
+.I   \-a, \-\-add
+Add a record of the specified object type
+.TP
+.I   \-d, \-\-delete
+Delete a record of the specified object type
+.TP
+.I   \-m, \-\-modify
+Modify a record of the specified object type
+.TP
+.I   \-l, \-\-list
+List records of the specified object type
+.TP
+.I   \-E, \-\-extract
+Extract customizable commands, for use within a transaction
+.TP
+.I   \-D, \-\-deleteall
+Remove all local customizations
+.TP
+.I   \-t TYPE, \-\-type TYPE
+SELinux type for the object
+.TP
+.I   \-r RANGE, \-\-range RANGE
+MLS/MCS Security Range (MLS/MCS Systems only) SELinux Range for SELinux login 
mapping defaults to the SELinux user record range. SELinux Range for SELinux 
user defaults to s0.
+.TP
+.I \-x SUBNET_PREFIX, \-\-subnet_prefix SUBNET_PREFIX
+Subnet prefix for the specified pkey or range 

[PATCH v1 6/9] libsepol: Add IB end port handling to CIL

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
James Carter:
- Add cil_resolve_ibendportcon prototype in cil_resolve_ast.h

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

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 3df670a..c02a41a 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -189,6 +189,7 @@ static void cil_init_keys(void)
CIL_KEY_CONTEXT = cil_strpool_add("context");
CIL_KEY_FILECON = cil_strpool_add("filecon");
CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon");
+   CIL_KEY_IBENDPORTCON = cil_strpool_add("ibendportcon");
CIL_KEY_PORTCON = cil_strpool_add("portcon");
CIL_KEY_NODECON = cil_strpool_add("nodecon");
CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -259,6 +260,7 @@ void cil_db_init(struct cil_db **db)
cil_sort_init(&(*db)->filecon);
cil_sort_init(&(*db)->nodecon);
cil_sort_init(&(*db)->ibpkeycon);
+   cil_sort_init(&(*db)->ibendportcon);
cil_sort_init(&(*db)->portcon);
cil_sort_init(&(*db)->pirqcon);
cil_sort_init(&(*db)->iomemcon);
@@ -311,6 +313,7 @@ void cil_db_destroy(struct cil_db **db)
cil_sort_destroy(&(*db)->filecon);
cil_sort_destroy(&(*db)->nodecon);
cil_sort_destroy(&(*db)->ibpkeycon);
+   cil_sort_destroy(&(*db)->ibendportcon);
cil_sort_destroy(&(*db)->portcon);
cil_sort_destroy(&(*db)->pirqcon);
cil_sort_destroy(&(*db)->iomemcon);
@@ -737,6 +740,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_PORTCON:
cil_destroy_portcon(*data);
break;
+   case CIL_IBENDPORTCON:
+   cil_destroy_ibendportcon(*data);
+   break;
case CIL_NODECON:
cil_destroy_nodecon(*data);
break;
@@ -1105,6 +,8 @@ const char * cil_node_to_string(struct cil_tree_node 
*node)
return CIL_KEY_FILECON;
case CIL_IBPKEYCON:
return CIL_KEY_IBPKEYCON;
+   case CIL_IBENDPORTCON:
+   return CIL_KEY_IBENDPORTCON;
case CIL_PORTCON:
return CIL_KEY_PORTCON;
case CIL_NODECON:
@@ -1838,6 +1846,16 @@ void cil_netifcon_init(struct cil_netifcon **netifcon)
(*netifcon)->context_str = NULL;
 }
 
+void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon)
+{
+   *ibendportcon = cil_malloc(sizeof(**ibendportcon));
+
+   (*ibendportcon)->dev_name_str = NULL;
+   (*ibendportcon)->port = 0;
+   (*ibendportcon)->context_str = NULL;
+   (*ibendportcon)->context = NULL;
+}
+
 void cil_context_init(struct cil_context **context)
 {
*context = cil_malloc(sizeof(**context));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 75398ff..fb65698 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3323,6 +3323,30 @@ exit:
return rc;
 }
 
+int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort 
*ibendportcons)
+{
+   int rc = SEPOL_ERR;
+   uint32_t i;
+   ocontext_t *tail = NULL;
+
+   for (i = 0; i < ibendportcons->count; i++) {
+   ocontext_t *new_ocon = 
cil_add_ocontext(>ocontexts[OCON_IBENDPORT], );
+   struct cil_ibendportcon *cil_ibendportcon = 
ibendportcons->array[i];
+
+   new_ocon->u.ibendport.dev_name = 
cil_strdup(cil_ibendportcon->dev_name_str);
+   new_ocon->u.ibendport.port = cil_ibendportcon->port;
+
+   rc = __cil_context_to_sepol_context(pdb, 
cil_ibendportcon->context, _ocon->context[0]);
+   if (rc != SEPOL_OK)
+   goto exit;
+   }
+
+   return SEPOL_OK;
+
+exit:
+   return rc;
+}
+
 int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons)
 {
int rc = SEPOL_ERR;
@@ -3887,6 +3911,11 @@ int __cil_contexts_to_policydb(policydb_t *pdb, 

[PATCH v1 4/9] checkpolicy: Add support for ibendportcon labels

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Check IB device name length when parsing policy.
- Use strcmp vs strncmp to compare device names.

Signed-off-by: Daniel Jurgens 
---
 checkpolicy/policy_define.c| 75 ++
 checkpolicy/policy_define.h|  1 +
 checkpolicy/policy_parse.y | 14 +-
 checkpolicy/policy_scan.l  |  2 +
 libsepol/include/sepol/policydb/policydb.h |  9 +++-
 5 files changed, 98 insertions(+), 3 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index ffdc5f8..239ca37 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -5162,6 +5162,81 @@ out:
return rc;
 }
 
+int define_ibendport_context(unsigned int port)
+{
+   ocontext_t *newc, *c, *l, *head;
+   char *id;
+   int rc = 0;
+
+   if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+   yyerror("ibendportcon not supported for target");
+   return -1;
+   }
+
+   if (pass == 1) {
+   id = (char *)queue_remove(id_queue);
+   free(id);
+   parse_security_context(NULL);
+   return 0;
+   }
+
+   newc = malloc(sizeof(*newc));
+   if (!newc) {
+   yyerror("out of memory");
+   return -1;
+   }
+   memset(newc, 0, sizeof(*newc));
+
+   newc->u.ibendport.dev_name = queue_remove(id_queue);
+   if (!newc->u.ibendport.dev_name) {
+   yyerror("failed to read infiniband device name.");
+   rc = -1;
+   goto out;
+   }
+
+   if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) {
+   yyerror("infiniband device name exceeds max length of 63.");
+   rc = -1;
+   goto out;
+   }
+
+   newc->u.ibendport.port = port;
+
+   if (parse_security_context(>context[0])) {
+   free(newc);
+   return -1;
+   }
+
+   /* Preserve the matching order specified in the configuration. */
+   head = policydbp->ocontexts[OCON_IBENDPORT];
+   for (l = NULL, c = head; c; l = c, c = c->next) {
+   unsigned int port2;
+
+   port2 = c->u.ibendport.port;
+
+   if (port == port2 &&
+   !strcmp(c->u.ibendport.dev_name,
+newc->u.ibendport.dev_name)) {
+   yyerror2("duplicate ibendportcon entry for %s port %u",
+newc->u.ibendport.dev_name, port);
+   rc = -1;
+   goto out;
+   }
+   }
+
+   if (l)
+   l->next = newc;
+   else
+   policydbp->ocontexts[OCON_IBENDPORT] = newc;
+
+   return 0;
+
+out:
+   free(newc->u.ibendport.dev_name);
+   free(newc);
+   return rc;
+}
+
 int define_netif_context(void)
 {
ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 75e3683..50a7ba7 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -44,6 +44,7 @@ int define_netif_context(void);
 int define_permissive(void);
 int define_polcap(void);
 int define_ibpkey_context(unsigned int low, unsigned int high);
+int define_ibendport_context(unsigned int port);
 int define_port_context(unsigned int low, unsigned int high);
 int define_pirq_context(unsigned int pirq);
 int define_iomem_context(uint64_t low, uint64_t high);
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index 35b433b..6b406c8 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -137,6 +137,7 @@ typedef int (* require_func_t)(int pass);
 %token SAMEUSER
 %token FSCON PORTCON NETIFCON NODECON 
 %token IBPKEYCON
+%token IBENDPORTCON
 %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
 %token FSUSEXATTR FSUSETASK FSUSETRANS
 %token GENFSCON
@@ -172,7 +173,7 @@ base_policy : { if (define_policy(pass, 0) == 
-1) return -1; }
  opt_default_rules opt_mls te_rbac users 
opt_constraints 
  { if (pass == 1) { if 
(policydb_index_bools(policydbp)) return -1;}
   else if (pass == 2) { if 
(policydb_index_others(NULL, policydbp, 0)) return -1;}}
- initial_sid_contexts opt_fs_contexts opt_fs_uses 
opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts
+ initial_sid_contexts opt_fs_contexts opt_fs_uses 
opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts 
opt_ibendport_contexts
;
 classes: class_def 
  

[PATCH v1 8/9] semanage: Update semanage to allow runtime labeling of ibendports

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Jason Zaman:
- Use SETools directly to query types in seobject.py

Signed-off-by: Daniel Jurgens 
---
 libsemanage/include/semanage/ibendport_record.h  |  62 +
 libsemanage/include/semanage/ibendports_local.h  |  36 +++
 libsemanage/include/semanage/ibendports_policy.h |  28 +++
 libsemanage/include/semanage/semanage.h  |   3 +
 libsemanage/src/direct_api.c |  40 ++-
 libsemanage/src/handle.h |  38 ++-
 libsemanage/src/ibendport_internal.h |  48 
 libsemanage/src/ibendport_record.c   | 154 
 libsemanage/src/ibendports_file.c| 157 
 libsemanage/src/ibendports_local.c   | 153 
 libsemanage/src/ibendports_policy.c  |  55 +
 libsemanage/src/ibendports_policydb.c|  62 +
 libsemanage/src/libsemanage.map  |   1 +
 libsemanage/src/policy_components.c  |   4 +
 libsemanage/src/semanage_store.c |   1 +
 libsemanage/src/semanage_store.h |   1 +
 libsemanage/src/semanageswig.i   |   3 +
 libsemanage/src/semanageswig_python.i|  43 
 libsemanage/utils/semanage_migrate_store |   3 +-
 libsepol/include/sepol/ibendport_record.h|  68 ++
 libsepol/include/sepol/ibendports.h  |  45 
 libsepol/include/sepol/sepol.h   |   2 +
 libsepol/src/ibendport_internal.h|  18 ++
 libsepol/src/ibendport_record.c  | 298 +++
 libsepol/src/ibendports.c| 255 +++
 python/semanage/semanage |  58 -
 python/semanage/seobject.py  | 239 ++
 27 files changed, 1854 insertions(+), 21 deletions(-)
 create mode 100644 libsemanage/include/semanage/ibendport_record.h
 create mode 100644 libsemanage/include/semanage/ibendports_local.h
 create mode 100644 libsemanage/include/semanage/ibendports_policy.h
 create mode 100644 libsemanage/src/ibendport_internal.h
 create mode 100644 libsemanage/src/ibendport_record.c
 create mode 100644 libsemanage/src/ibendports_file.c
 create mode 100644 libsemanage/src/ibendports_local.c
 create mode 100644 libsemanage/src/ibendports_policy.c
 create mode 100644 libsemanage/src/ibendports_policydb.c
 create mode 100644 libsepol/include/sepol/ibendport_record.h
 create mode 100644 libsepol/include/sepol/ibendports.h
 create mode 100644 libsepol/src/ibendport_internal.h
 create mode 100644 libsepol/src/ibendport_record.c
 create mode 100644 libsepol/src/ibendports.c

diff --git a/libsemanage/include/semanage/ibendport_record.h 
b/libsemanage/include/semanage/ibendport_record.h
new file mode 100644
index 000..153eea0
--- /dev/null
+++ b/libsemanage/include/semanage/ibendport_record.h
@@ -0,0 +1,62 @@
+/*Copyright (C) 2005 Red Hat, Inc. */
+
+#ifndef _SEMANAGE_IBENDPORT_RECORD_H_
+#define _SEMANAGE_IBENDPORT_RECORD_H_
+
+#include 
+#include 
+#include 
+
+#ifndef _SEMANAGE_IBENDPORT_DEFINED_
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport semanage_ibendport_t;
+typedef struct semanage_ibendport_key semanage_ibendport_key_t;
+#define _SEMANAGE_IBENDPORT_DEFINED_
+#endif
+
+extern int semanage_ibendport_compare(const semanage_ibendport_t *ibendport,
+ const semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport,
+  const semanage_ibendport_t *ibendport2);
+
+extern int semanage_ibendport_key_create(semanage_handle_t *handle,
+const char *ibdev_name,
+int port,
+semanage_ibendport_key_t **key_ptr);
+
+extern int semanage_ibendport_key_extract(semanage_handle_t *handle,
+ const semanage_ibendport_t *ibendport,
+ semanage_ibendport_key_t **key_ptr);
+
+extern void semanage_ibendport_key_free(semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle,
+const semanage_ibendport_t 
*ibendport,
+char **ibdev_name_ptr);
+
+extern int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle,
+semanage_ibendport_t *ibendport,
+

[PATCH v1 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Fixed semanage_pkey_exists -> semanage_ibpkey_exists in delete flow in
seobject.py

Stephen Smalley:
- Subnet prefix can't vary in size always 16 bytes, remove size field.
- Removed extraneous change in libsepol/VERSION
- Removed ifdef DARWIN s6_addr/32 blocks in favor of s6_addr.
- Got rid of magic constant for subnet prefix size.

Jason Zaman:
- Use SETools directly to query types in seobject.py.

Signed-off-by: Daniel Jurgens 
---
 libsemanage/include/semanage/ibpkey_record.h  |  76 +
 libsemanage/include/semanage/ibpkeys_local.h  |  36 +++
 libsemanage/include/semanage/ibpkeys_policy.h |  28 ++
 libsemanage/include/semanage/semanage.h   |   3 +
 libsemanage/src/direct_api.c  |  29 +-
 libsemanage/src/handle.h  |  36 ++-
 libsemanage/src/ibpkey_internal.h |  52 +++
 libsemanage/src/ibpkey_record.c   | 185 +++
 libsemanage/src/ibpkeys_file.c| 181 +++
 libsemanage/src/ibpkeys_local.c   | 178 ++
 libsemanage/src/ibpkeys_policy.c  |  52 +++
 libsemanage/src/ibpkeys_policydb.c|  62 
 libsemanage/src/libsemanage.map   |   1 +
 libsemanage/src/policy_components.c   |   5 +-
 libsemanage/src/semanage_store.c  |   1 +
 libsemanage/src/semanage_store.h  |   1 +
 libsemanage/src/semanageswig.i|   3 +
 libsemanage/src/semanageswig_python.i |  43 +++
 libsemanage/utils/semanage_migrate_store  |   3 +-
 libsepol/include/sepol/ibpkey_record.h|  77 +
 libsepol/include/sepol/ibpkeys.h  |  44 +++
 libsepol/include/sepol/sepol.h|   2 +
 libsepol/src/ibpkey_internal.h|  21 ++
 libsepol/src/ibpkey_record.c  | 448 ++
 libsepol/src/ibpkeys.c| 263 +++
 python/semanage/semanage  |  60 +++-
 python/semanage/seobject.py   | 255 +++
 27 files changed, 2129 insertions(+), 16 deletions(-)
 create mode 100644 libsemanage/include/semanage/ibpkey_record.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_local.h
 create mode 100644 libsemanage/include/semanage/ibpkeys_policy.h
 create mode 100644 libsemanage/src/ibpkey_internal.h
 create mode 100644 libsemanage/src/ibpkey_record.c
 create mode 100644 libsemanage/src/ibpkeys_file.c
 create mode 100644 libsemanage/src/ibpkeys_local.c
 create mode 100644 libsemanage/src/ibpkeys_policy.c
 create mode 100644 libsemanage/src/ibpkeys_policydb.c
 create mode 100644 libsepol/include/sepol/ibpkey_record.h
 create mode 100644 libsepol/include/sepol/ibpkeys.h
 create mode 100644 libsepol/src/ibpkey_internal.h
 create mode 100644 libsepol/src/ibpkey_record.c
 create mode 100644 libsepol/src/ibpkeys.c

diff --git a/libsemanage/include/semanage/ibpkey_record.h 
b/libsemanage/include/semanage/ibpkey_record.h
new file mode 100644
index 000..d76aaae
--- /dev/null
+++ b/libsemanage/include/semanage/ibpkey_record.h
@@ -0,0 +1,76 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+#ifndef _SEMANAGE_IBPKEY_RECORD_H_
+#define _SEMANAGE_IBPKEY_RECORD_H_
+
+#include 
+#include 
+#include 
+
+#ifndef _SEMANAGE_IBPKEY_DEFINED_
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey semanage_ibpkey_t;
+typedef struct semanage_ibpkey_key semanage_ibpkey_key_t;
+#define _SEMANAGE_IBPKEY_DEFINED_
+#endif
+
+#define INET6_ADDRLEN 16
+
+extern int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
+  const semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
+   const semanage_ibpkey_t *ibpkey2);
+
+extern int semanage_ibpkey_key_create(semanage_handle_t *handle,
+ const char *subnet_prefix,
+ int low, int high,
+ semanage_ibpkey_key_t **key_ptr);
+
+extern int semanage_ibpkey_key_extract(semanage_handle_t *handle,
+  const semanage_ibpkey_t *ibpkey,
+  semanage_ibpkey_key_t **key_ptr);
+
+extern void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle,
+const semanage_ibpkey_t *ibpkey,
+char **subnet_prefix_ptr);
+
+extern int semanage_ibpkey_get_subnet_prefix_bytes(semanage_handle_t 

[PATCH v1 3/9] libsepol: Add Infiniband Pkey handling to CIL

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 9b9ccc3..3df670a 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -188,6 +188,7 @@ static void cil_init_keys(void)
CIL_KEY_MLSVALIDATETRANS = cil_strpool_add("mlsvalidatetrans");
CIL_KEY_CONTEXT = cil_strpool_add("context");
CIL_KEY_FILECON = cil_strpool_add("filecon");
+   CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon");
CIL_KEY_PORTCON = cil_strpool_add("portcon");
CIL_KEY_NODECON = cil_strpool_add("nodecon");
CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -257,6 +258,7 @@ void cil_db_init(struct cil_db **db)
cil_sort_init(&(*db)->genfscon);
cil_sort_init(&(*db)->filecon);
cil_sort_init(&(*db)->nodecon);
+   cil_sort_init(&(*db)->ibpkeycon);
cil_sort_init(&(*db)->portcon);
cil_sort_init(&(*db)->pirqcon);
cil_sort_init(&(*db)->iomemcon);
@@ -308,6 +310,7 @@ void cil_db_destroy(struct cil_db **db)
cil_sort_destroy(&(*db)->genfscon);
cil_sort_destroy(&(*db)->filecon);
cil_sort_destroy(&(*db)->nodecon);
+   cil_sort_destroy(&(*db)->ibpkeycon);
cil_sort_destroy(&(*db)->portcon);
cil_sort_destroy(&(*db)->pirqcon);
cil_sort_destroy(&(*db)->iomemcon);
@@ -728,6 +731,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_FILECON:
cil_destroy_filecon(*data);
break;
+   case CIL_IBPKEYCON:
+   cil_destroy_ibpkeycon(*data);
+   break;
case CIL_PORTCON:
cil_destroy_portcon(*data);
break;
@@ -1097,6 +1103,8 @@ const char * cil_node_to_string(struct cil_tree_node 
*node)
return CIL_KEY_FSUSE;
case CIL_FILECON:
return CIL_KEY_FILECON;
+   case CIL_IBPKEYCON:
+   return CIL_KEY_IBPKEYCON;
case CIL_PORTCON:
return CIL_KEY_PORTCON;
case CIL_NODECON:
@@ -2255,6 +2263,17 @@ void cil_filecon_init(struct cil_filecon **filecon)
(*filecon)->context = NULL;
 }
 
+void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon)
+{
+   *ibpkeycon = cil_malloc(sizeof(**ibpkeycon));
+
+   (*ibpkeycon)->subnet_prefix_str = NULL;
+   (*ibpkeycon)->pkey_low = 0;
+   (*ibpkeycon)->pkey_high = 0;
+   (*ibpkeycon)->context_str = NULL;
+   (*ibpkeycon)->context = NULL;
+}
+
 void cil_portcon_init(struct cil_portcon **portcon)
 {
*portcon = cil_malloc(sizeof(**portcon));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index e1481a4..75398ff 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3218,6 +3218,40 @@ exit:
return rc;
 }
 
+int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons)
+{
+   int rc = SEPOL_ERR;
+   uint32_t i = 0;
+   ocontext_t *tail = NULL;
+   struct in6_addr subnet_prefix;
+
+   for (i = 0; i < ibpkeycons->count; i++) {
+   struct cil_ibpkeycon *cil_ibpkeycon = ibpkeycons->array[i];
+   ocontext_t *new_ocon = 
cil_add_ocontext(>ocontexts[OCON_IBPKEY], );
+
+   rc = inet_pton(AF_INET6, cil_ibpkeycon->subnet_prefix_str, 
_prefix);
+   if (rc != 1) {
+   cil_log(CIL_ERR, "ibpkeycon subnet prefix not in valid 
IPV6 format\n");
+   rc = SEPOL_ERR;
+   goto exit;
+   }
+
+   memcpy(new_ocon->u.ibpkey.subnet_prefix, 
_prefix.s6_addr[0],
+  sizeof(*new_ocon->u.ibpkey.subnet_prefix));
+   new_ocon->u.ibpkey.low_pkey = cil_ibpkeycon->pkey_low;
+   new_ocon->u.ibpkey.high_pkey = cil_ibpkeycon->pkey_high;
+
+   rc = __cil_context_to_sepol_context(pdb, 

[PATCH v1 1/9] checkpolicy: Add support for ibpkeycon labels

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Always use s6_addr instead of s6_addr32.
- Add comment about POLICYDB_VERSION_INFINIBAND being linux specific.

Signed-off-by: Daniel Jurgens 
---
 checkpolicy/policy_define.c| 105 +
 checkpolicy/policy_define.h|   1 +
 checkpolicy/policy_parse.y |  15 -
 checkpolicy/policy_scan.l  |   3 +
 libsepol/include/sepol/policydb/policydb.h |  32 +
 5 files changed, 143 insertions(+), 13 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 8fab214..ffdc5f8 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -20,6 +20,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2008 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2017 Mellanox Techonologies Inc.
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 2.
@@ -5057,6 +5058,110 @@ int define_port_context(unsigned int low, unsigned int 
high)
return -1;
 }
 
+int define_ibpkey_context(unsigned int low, unsigned int high)
+{
+   ocontext_t *newc, *c, *l, *head;
+   struct in6_addr subnet_prefix;
+   char *id;
+   int rc = 0;
+
+   if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+   yyerror("ibpkeycon not supported for target");
+   return -1;
+   }
+
+   if (pass == 1) {
+   id = (char *)queue_remove(id_queue);
+   free(id);
+   parse_security_context(NULL);
+   return 0;
+   }
+
+   newc = malloc(sizeof(*newc));
+   if (!newc) {
+   yyerror("out of memory");
+   return -1;
+   }
+   memset(newc, 0, sizeof(*newc));
+
+   id = queue_remove(id_queue);
+   if (!id) {
+   yyerror("failed to read the subnet prefix");
+   rc = -1;
+   goto out;
+   }
+
+   rc = inet_pton(AF_INET6, id, _prefix);
+   free(id);
+   if (rc < 1) {
+   yyerror("failed to parse the subnet prefix");
+   if (rc == 0)
+   rc = -1;
+   goto out;
+   }
+
+   if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) {
+   yyerror("subnet prefix should be 0's in the low order 64 
bits.");
+   rc = -1;
+   goto out;
+   }
+
+   memcpy(>u.ibpkey.subnet_prefix[0], _prefix.s6_addr[0],
+  sizeof(newc->u.ibpkey.subnet_prefix));
+
+   newc->u.ibpkey.low_pkey = low;
+   newc->u.ibpkey.high_pkey = high;
+
+   if (low > high) {
+   yyerror2("low pkey %d exceeds high pkey %d", low, high);
+   rc = -1;
+   goto out;
+   }
+
+   rc = parse_security_context(>context[0]);
+   if (rc)
+   goto out;
+
+   /* Preserve the matching order specified in the configuration. */
+   head = policydbp->ocontexts[OCON_IBPKEY];
+   for (l = NULL, c = head; c; l = c, c = c->next) {
+   unsigned int low2, high2;
+
+   low2 = c->u.ibpkey.low_pkey;
+   high2 = c->u.ibpkey.high_pkey;
+
+   if (low == low2 && high == high2 &&
+   !memcmp(>u.ibpkey.subnet_prefix[0],
+   >u.ibpkey.subnet_prefix[0],
+   sizeof(c->u.ibpkey.subnet_prefix))) {
+   yyerror2("duplicate ibpkeycon entry for %d-%d ",
+low, high);
+   rc = -1;
+   goto out;
+   }
+   if (low2 <= low && high2 >= high &&
+   !memcmp(>u.ibpkey.subnet_prefix[0],
+   >u.ibpkey.subnet_prefix[0],
+   sizeof(c->u.ibpkey.subnet_prefix))) {
+   yyerror2("ibpkeycon entry for %d-%d hidden by earlier 
entry for %d-%d",
+low, high, low2, high2);
+   rc = -1;
+   goto out;
+   }
+   }
+
+   if (l)
+   l->next = newc;
+   else
+   policydbp->ocontexts[OCON_IBPKEY] = newc;
+
+   return 0;
+
+out:
+   free(newc);
+   return rc;
+}
+
 int define_netif_context(void)
 {
ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 9f4b6d0..75e3683 100644
--- a/checkpolicy/policy_define.h
+++ 

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

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

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

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

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

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index d0e46ba..94bf083 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -701,6 +701,7 @@ int main(int argc, char **argv)
printf("i)  display constraint expressions\n");
printf("j)  display validatetrans expressions\n");
printf("k)  Call ibpkey_sid\n");
+   printf("l)  Call ibendport_sid\n");
 #ifdef EQUIVTYPES
printf("z)  Show equivalent types\n");
 #endif
@@ -1245,6 +1246,25 @@ int main(int argc, char **argv)
printf("sid %d\n", ssid);
}
break;
+   case 'l':
+   printf("device name (eg. mlx4_0)?  ");
+   FGETS(ans, sizeof(ans), stdin);
+   ans[strlen(ans) - 1] = 0;
+
+   name = malloc((strlen(ans) + 1) * sizeof(char));
+   if (!name) {
+   fprintf(stderr, "couldn't malloc string.\n");
+   break;
+   }
+   strcpy(name, ans);
+
+   printf("port? ");
+   FGETS(ans, sizeof(ans), stdin);
+   port = atoi(ans);
+   sepol_ibendport_sid(name, port, );
+   printf("sid %d\n", ssid);
+   free(name);
+   break;
 #ifdef EQUIVTYPES
case 'z':
identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h 
b/libsepol/include/sepol/policydb/services.h
index 459254e..e4f2f11 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -196,6 +196,14 @@ extern int sepol_ibpkey_sid(void *subnet_prefix_p,
sepol_security_id_t *out_sid);
 
 /*
+ * Return the SID of the ibendport specified by
+ * `dev_name', and `port'.
+ */
+extern int sepol_ibendport_sid(char *dev_name,
+  uint8_t port,
+  sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index c45ecbe..061945e 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -2226,6 +2226,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey;
n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey;
break;
+   case OCON_IBENDPORT:
+   n->u.ibendport.dev_name = 
strdup(c->u.ibendport.dev_name);
+   if (!n->u.ibendport.dev_name) {
+   ERR(state->handle, "Out of memory!");
+   return -1;
+   }
+   n->u.ibendport.port = c->u.ibendport.port;
+   break;
case OCON_PORT:
n->u.port.protocol = c->u.port.protocol;
n->u.port.low_port = c->u.port.low_port;
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index fcfd0e0..6587ff4 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -2837,6 +2837,43 @@ exit:
return rc;
 }
 
+static int 

[PATCH v1 2/9] libsepol: Add ibpkey ocontext handling

2017-05-15 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 

---
v1:
Stephen Smalley:
- Removed domain and type params from sepol_ibpkey_sid.
- Removed splen param from sepol_ibpkey_sid, it never varied.
- Removed extra XPERMS_IOCTL version from policydb_compat_info.
- Confirm that low order bytes of IPv6 addr for subnet prefix is 0's.

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

Signed-off-by: Daniel Jurgens 
---
 checkpolicy/checkpolicy.c  | 25 +
 libsepol/include/sepol/policydb/services.h |  8 
 libsepol/src/expand.c  |  9 +
 libsepol/src/kernel_to_cil.c   | 58 +
 libsepol/src/kernel_to_conf.c  | 59 ++
 libsepol/src/libsepol.map.in   |  1 +
 libsepol/src/module_to_cil.c   | 38 +++
 libsepol/src/policydb.c| 37 +++
 libsepol/src/services.c| 51 ++
 libsepol/src/write.c   | 16 
 10 files changed, 302 insertions(+)

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 534fc22..d0e46ba 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -22,6 +22,7 @@
  *
  * Policy Module support.
  *
+ * Copyright (C) 2017 Mellanox Technologies Inc.
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2005 Tresys Technology, LLC
  * Copyright (C) 2003 Red Hat, Inc., James Morris 
@@ -699,6 +700,7 @@ int main(int argc, char **argv)
printf("h)  change a boolean value\n");
printf("i)  display constraint expressions\n");
printf("j)  display validatetrans expressions\n");
+   printf("k)  Call ibpkey_sid\n");
 #ifdef EQUIVTYPES
printf("z)  Show equivalent types\n");
 #endif
@@ -1220,6 +1222,29 @@ int main(int argc, char **argv)
"\nNo validatetrans expressions found.\n");
}
break;
+   case 'k':
+   {
+   char *p;
+   struct in6_addr addr6;
+   unsigned int pkey;
+
+   printf("subnet prefix?  ");
+   FGETS(ans, sizeof(ans), stdin);
+   ans[strlen(ans) - 1] = 0;
+   p = (char *)
+
+   if (inet_pton(AF_INET6, ans, p) < 1) {
+   printf("error parsing subnet prefix\n");
+   break;
+   }
+
+   printf("pkey? ");
+   FGETS(ans, sizeof(ans), stdin);
+   pkey = atoi(ans);
+   sepol_ibpkey_sid(p, pkey, );
+   printf("sid %d\n", ssid);
+   }
+   break;
 #ifdef EQUIVTYPES
case 'z':
identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h 
b/libsepol/include/sepol/policydb/services.h
index 9162149..459254e 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -188,6 +188,14 @@ extern int sepol_port_sid(uint16_t domain,
  uint16_t port, sepol_security_id_t * out_sid);
 
 /*
+ * Return the SID of the ibpkey specified by
+ * `subnet prefix', and `pkey'.
+ */
+extern int sepol_ibpkey_sid(void *subnet_prefix_p,
+   uint16_t pkey,
+   sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 54bf781..c45ecbe 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2004-2005 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2017 Mellanox Technologies, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -2217,6 +2218,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
return -1;
}
break;
+   case OCON_IBPKEY:
+   n->u.ibpkey.subnet_prefix[0] = 
c->u.ibpkey.subnet_prefix[0];
+ 

[PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/libsemanage/include/semanage/ibpkey_record.h 
b/libsemanage/include/semanage/ibpkey_record.h
new file mode 100644
index 000..45fe59e
--- /dev/null
+++ b/libsemanage/include/semanage/ibpkey_record.h
@@ -0,0 +1,76 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+#ifndef _SEMANAGE_IBPKEY_RECORD_H_
+#define _SEMANAGE_IBPKEY_RECORD_H_
+
+#include 
+#include 
+#include 
+
+#ifndef _SEMANAGE_IBPKEY_DEFINED_
+struct semanage_ibpkey;
+struct semanage_ibpkey_key;
+typedef struct semanage_ibpkey semanage_ibpkey_t;
+typedef struct semanage_ibpkey_key semanage_ibpkey_key_t;
+#define _SEMANAGE_IBPKEY_DEFINED_
+#endif
+
+extern int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
+  const semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
+   const semanage_ibpkey_t *ibpkey2);
+
+extern int semanage_ibpkey_key_create(semanage_handle_t *handle,
+ const char *subnet_prefix,
+ int low, int high,
+ semanage_ibpkey_key_t **key_ptr);
+
+extern int semanage_ibpkey_key_extract(semanage_handle_t *handle,
+  const semanage_ibpkey_t *ibpkey,
+  semanage_ibpkey_key_t **key_ptr);
+
+extern void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key);
+
+extern int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle,
+const semanage_ibpkey_t *ibpkey,
+char **subnet_prefix_ptr);
+
+extern int semanage_ibpkey_get_subnet_prefix_bytes(semanage_handle_t *handle,
+  const semanage_ibpkey_t 
*ibpkey,
+  char **subnet_prefix,
+  size_t *subnet_prefix_sz);
+
+extern int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle,
+semanage_ibpkey_t *ibpkey,
+   

[PATCH 3/9] libsepol: Add Infiniband Pkey handling to CIL

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index a64c528..6b51b8f 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -187,6 +187,7 @@ static void cil_init_keys(void)
CIL_KEY_MLSVALIDATETRANS = cil_strpool_add("mlsvalidatetrans");
CIL_KEY_CONTEXT = cil_strpool_add("context");
CIL_KEY_FILECON = cil_strpool_add("filecon");
+   CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon");
CIL_KEY_PORTCON = cil_strpool_add("portcon");
CIL_KEY_NODECON = cil_strpool_add("nodecon");
CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -256,6 +257,7 @@ void cil_db_init(struct cil_db **db)
cil_sort_init(&(*db)->genfscon);
cil_sort_init(&(*db)->filecon);
cil_sort_init(&(*db)->nodecon);
+   cil_sort_init(&(*db)->ibpkeycon);
cil_sort_init(&(*db)->portcon);
cil_sort_init(&(*db)->pirqcon);
cil_sort_init(&(*db)->iomemcon);
@@ -307,6 +309,7 @@ void cil_db_destroy(struct cil_db **db)
cil_sort_destroy(&(*db)->genfscon);
cil_sort_destroy(&(*db)->filecon);
cil_sort_destroy(&(*db)->nodecon);
+   cil_sort_destroy(&(*db)->ibpkeycon);
cil_sort_destroy(&(*db)->portcon);
cil_sort_destroy(&(*db)->pirqcon);
cil_sort_destroy(&(*db)->iomemcon);
@@ -724,6 +727,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_FILECON:
cil_destroy_filecon(*data);
break;
+   case CIL_IBPKEYCON:
+   cil_destroy_ibpkeycon(*data);
+   break;
case CIL_PORTCON:
cil_destroy_portcon(*data);
break;
@@ -1091,6 +1097,8 @@ const char * cil_node_to_string(struct cil_tree_node 
*node)
return CIL_KEY_FSUSE;
case CIL_FILECON:
return CIL_KEY_FILECON;
+   case CIL_IBPKEYCON:
+   return CIL_KEY_IBPKEYCON;
case CIL_PORTCON:
return CIL_KEY_PORTCON;
case CIL_NODECON:
@@ -2240,6 +2248,17 @@ void cil_filecon_init(struct cil_filecon **filecon)
(*filecon)->context = NULL;
 }
 
+void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon)
+{
+   *ibpkeycon = cil_malloc(sizeof(**ibpkeycon));
+
+   (*ibpkeycon)->subnet_prefix_str = NULL;
+   (*ibpkeycon)->pkey_low = 0;
+   (*ibpkeycon)->pkey_high = 0;
+   (*ibpkeycon)->context_str = NULL;
+   (*ibpkeycon)->context = NULL;
+}
+
 void cil_portcon_init(struct cil_portcon **portcon)
 {
*portcon = cil_malloc(sizeof(**portcon));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index e1481a4..75398ff 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3218,6 +3218,40 @@ exit:
return rc;
 }
 
+int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons)
+{
+   int rc = SEPOL_ERR;
+   uint32_t i = 0;
+   ocontext_t *tail = NULL;
+   struct in6_addr subnet_prefix;
+
+   for (i = 0; i < ibpkeycons->count; i++) {
+   struct cil_ibpkeycon *cil_ibpkeycon = ibpkeycons->array[i];
+   ocontext_t *new_ocon = 
cil_add_ocontext(>ocontexts[OCON_IBPKEY], );
+
+   rc = inet_pton(AF_INET6, cil_ibpkeycon->subnet_prefix_str, 
_prefix);
+   if (rc != 1) {
+   cil_log(CIL_ERR, "ibpkeycon subnet prefix not in valid 
IPV6 format\n");
+   rc = SEPOL_ERR;
+   goto exit;
+   }
+
+   memcpy(new_ocon->u.ibpkey.subnet_prefix, 
_prefix.s6_addr[0],
+  sizeof(*new_ocon->u.ibpkey.subnet_prefix));
+   new_ocon->u.ibpkey.low_pkey = cil_ibpkeycon->pkey_low;
+   new_ocon->u.ibpkey.high_pkey = cil_ibpkeycon->pkey_high;
+
+   rc = 

[PATCH 6/9] libsepol: Add IB end port handling to CIL

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 6b51b8f..f3849ef 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -188,6 +188,7 @@ static void cil_init_keys(void)
CIL_KEY_CONTEXT = cil_strpool_add("context");
CIL_KEY_FILECON = cil_strpool_add("filecon");
CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon");
+   CIL_KEY_IBENDPORTCON = cil_strpool_add("ibendportcon");
CIL_KEY_PORTCON = cil_strpool_add("portcon");
CIL_KEY_NODECON = cil_strpool_add("nodecon");
CIL_KEY_GENFSCON = cil_strpool_add("genfscon");
@@ -258,6 +259,7 @@ void cil_db_init(struct cil_db **db)
cil_sort_init(&(*db)->filecon);
cil_sort_init(&(*db)->nodecon);
cil_sort_init(&(*db)->ibpkeycon);
+   cil_sort_init(&(*db)->ibendportcon);
cil_sort_init(&(*db)->portcon);
cil_sort_init(&(*db)->pirqcon);
cil_sort_init(&(*db)->iomemcon);
@@ -310,6 +312,7 @@ void cil_db_destroy(struct cil_db **db)
cil_sort_destroy(&(*db)->filecon);
cil_sort_destroy(&(*db)->nodecon);
cil_sort_destroy(&(*db)->ibpkeycon);
+   cil_sort_destroy(&(*db)->ibendportcon);
cil_sort_destroy(&(*db)->portcon);
cil_sort_destroy(&(*db)->pirqcon);
cil_sort_destroy(&(*db)->iomemcon);
@@ -733,6 +736,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_PORTCON:
cil_destroy_portcon(*data);
break;
+   case CIL_IBENDPORTCON:
+   cil_destroy_ibendportcon(*data);
+   break;
case CIL_NODECON:
cil_destroy_nodecon(*data);
break;
@@ -1099,6 +1105,8 @@ const char * cil_node_to_string(struct cil_tree_node 
*node)
return CIL_KEY_FILECON;
case CIL_IBPKEYCON:
return CIL_KEY_IBPKEYCON;
+   case CIL_IBENDPORTCON:
+   return CIL_KEY_IBENDPORTCON;
case CIL_PORTCON:
return CIL_KEY_PORTCON;
case CIL_NODECON:
@@ -1832,6 +1840,16 @@ void cil_netifcon_init(struct cil_netifcon **netifcon)
(*netifcon)->context_str = NULL;
 }
 
+void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon)
+{
+   *ibendportcon = cil_malloc(sizeof(**ibendportcon));
+
+   (*ibendportcon)->dev_name_str = NULL;
+   (*ibendportcon)->port = 0;
+   (*ibendportcon)->context_str = NULL;
+   (*ibendportcon)->context = NULL;
+}
+
 void cil_context_init(struct cil_context **context)
 {
*context = cil_malloc(sizeof(**context));
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 75398ff..fb65698 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -3323,6 +3323,30 @@ exit:
return rc;
 }
 
+int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort 
*ibendportcons)
+{
+   int rc = SEPOL_ERR;
+   uint32_t i;
+   ocontext_t *tail = NULL;
+
+   for (i = 0; i < ibendportcons->count; i++) {
+   ocontext_t *new_ocon = 
cil_add_ocontext(>ocontexts[OCON_IBENDPORT], );
+   struct cil_ibendportcon *cil_ibendportcon = 
ibendportcons->array[i];
+
+   new_ocon->u.ibendport.dev_name = 
cil_strdup(cil_ibendportcon->dev_name_str);
+   new_ocon->u.ibendport.port = cil_ibendportcon->port;
+
+   rc = __cil_context_to_sepol_context(pdb, 
cil_ibendportcon->context, _ocon->context[0]);
+   if (rc != SEPOL_OK)
+   goto exit;
+   }
+
+   return SEPOL_OK;
+
+exit:
+   return rc;
+}
+
 int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons)
 {
int rc = SEPOL_ERR;
@@ -3887,6 +3911,11 @@ int __cil_contexts_to_policydb(policydb_t *pdb, const 
struct cil_db *db)
goto exit;
}
 
+   rc = cil_ibendportcon_to_policydb(pdb, db->ibendportcon);
+   if (rc != 

[PATCH 4/9] checkpolicy: Add support for ibendportcon labels

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 6f92bc5..2926f18 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -5085,6 +5085,76 @@ out:
return rc;
 }
 
+int define_ibendport_context(unsigned int port)
+{
+   ocontext_t *newc, *c, *l, *head;
+   char *id;
+   int rc = 0;
+
+   if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+   yyerror("ibendportcon not supported for target");
+   return -1;
+   }
+
+   if (pass == 1) {
+   id = (char *)queue_remove(id_queue);
+   free(id);
+   parse_security_context(NULL);
+   return 0;
+   }
+
+   newc = malloc(sizeof(*newc));
+   if (!newc) {
+   yyerror("out of memory");
+   return -1;
+   }
+   memset(newc, 0, sizeof(*newc));
+
+   newc->u.ibendport.dev_name = queue_remove(id_queue);
+   if (!newc->u.ibendport.dev_name) {
+   yyerror("failed to read subnet management interface device 
name.");
+   rc = -1;
+   goto out;
+   }
+
+   newc->u.ibendport.port = port;
+
+   if (parse_security_context(>context[0])) {
+   free(newc);
+   return -1;
+   }
+
+   /* Preserve the matching order specified in the configuration. */
+   head = policydbp->ocontexts[OCON_IBENDPORT];
+   for (l = NULL, c = head; c; l = c, c = c->next) {
+   unsigned int port2;
+
+   port2 = c->u.ibendport.port;
+
+   if (port == port2 &&
+   !strncmp(c->u.ibendport.dev_name,
+newc->u.ibendport.dev_name,
+64)) {
+   yyerror2("duplicate ibendportcon entry for %s port %u",
+newc->u.ibendport.dev_name, port);
+   rc = -1;
+   goto out;
+   }
+   }
+
+   if (l)
+   l->next = newc;
+   else
+   policydbp->ocontexts[OCON_IBENDPORT] = newc;
+
+   return 0;
+
+out:
+   free(newc->u.ibendport.dev_name);
+   free(newc);
+   return rc;
+}
+
 int define_netif_context(void)
 {
ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index b019b1a..3282aed 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -44,6 +44,7 @@ int define_netif_context(void);
 int define_permissive(void);
 int define_polcap(void);
 int define_ibpkey_context(unsigned int low, unsigned int high);
+int define_ibendport_context(unsigned int port);
 int define_port_context(unsigned int low, unsigned int high);
 int define_pirq_context(unsigned int pirq);
 int define_iomem_context(uint64_t low, uint64_t high);
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index f50eab1..35b7a33 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -136,6 +136,7 @@ typedef int (* require_func_t)(int pass);
 %token SAMEUSER
 %token FSCON PORTCON NETIFCON NODECON 
 %token IBPKEYCON
+%token IBENDPORTCON
 %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
 %token FSUSEXATTR FSUSETASK FSUSETRANS
 %token GENFSCON
@@ -171,7 +172,7 @@ base_policy : { if (define_policy(pass, 0) == 
-1) return -1; }
  opt_default_rules opt_mls te_rbac users 
opt_constraints 
  { if (pass == 1) { if 
(policydb_index_bools(policydbp)) return -1;}
   else if (pass == 2) { if 
(policydb_index_others(NULL, policydbp, 0)) return -1;}}
- initial_sid_contexts opt_fs_contexts opt_fs_uses 
opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts
+ initial_sid_contexts opt_fs_contexts opt_fs_uses 
opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts 
opt_ibendport_contexts
;
 classes: class_def 
| classes class_def
@@ -697,7 +698,7 @@ fs_contexts : fs_context_def
 fs_context_def : FSCON number number security_context_def 
security_context_def
{if (define_fs_context($2,$3)) return -1;}
;
-net_contexts   : opt_port_contexts opt_netif_contexts 

[PATCH 9/9] semanage: Update man pages for infiniband

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/python/semanage/semanage-ibendport.8 
b/python/semanage/semanage-ibendport.8
new file mode 100644
index 000..c3753a2
--- /dev/null
+++ b/python/semanage/semanage-ibendport.8
@@ -0,0 +1,66 @@
+.TH "semanage-ibendport" "8" "20170508" "" ""
+.SH "NAME"
+.B semanage\-ibendport \- SELinux Policy Management ibendport mapping tool
+.SH "SYNOPSIS"
+.B semanage ibendport [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add \-t TYPE \-z 
IBDEV_NAME \-r RANGE port | \-\-delete \-z IBDEV_NAME port | \-\-deleteall  | 
\-\-extract  | \-\-list [\-C] | \-\-modify \-t TYPE \-z IBDEV_NAME \-r RANGE 
port ]
+
+.SH "DESCRIPTION"
+semanage is used to configure certain elements of SELinux policy without 
requiring modification to or recompilation from policy sources.  semanage 
ibendport controls the ibendport number to ibendport type definitions.
+
+.SH "OPTIONS"
+.TP
+.I  \-h, \-\-help
+show this help message and exit
+.TP
+.I   \-n, \-\-noheading
+Do not print heading when listing the specified object type
+.TP
+.I   \-N, \-\-noreload
+Do not reload policy after commit
+.TP
+.I   \-S STORE, \-\-store STORE
+Select an alternate SELinux Policy Store to manage
+.TP
+.I   \-C, \-\-locallist
+List local customizations
+.TP
+.I   \-a, \-\-add
+Add a record of the specified object type
+.TP
+.I   \-d, \-\-delete
+Delete a record of the specified object type
+.TP
+.I   \-m, \-\-modify
+Modify a record of the specified object type
+.TP
+.I   \-l, \-\-list
+List records of the specified object type
+.TP
+.I   \-E, \-\-extract
+Extract customizable commands, for use within a transaction
+.TP
+.I   \-D, \-\-deleteall
+Remove all local customizations
+.TP
+.I   \-t TYPE, \-\-type TYPE
+SELinux type for the object
+.TP
+.I   \-r RANGE, \-\-range RANGE
+MLS/MCS Security Range (MLS/MCS Systems only) SELinux Range for SELinux login 
mapping defaults to the SELinux user record range. SELinux Range for SELinux 
user defaults to s0.
+.TP
+.I \-z IBDEV_NAME, \-\-ibdev_name IBDEV_NAME
+The name of the infiniband device for the port to be labeled.  (ex. mlx5_0)
+
+.SH EXAMPLE
+.nf
+List all ibendport definitions
+# semanage ibendport \-l
+Label mlx4_0 port 2.
+# semanage ibendport \-a \-t allowed_ibendport_t \-z mlx4_0 2
+
+.SH "SEE ALSO"
+.BR selinux (8),
+.BR semanage (8)
+
+.SH "AUTHOR"
+This man page was written by Daniel Walsh 
diff --git a/python/semanage/semanage-ibpkey.8 
b/python/semanage/semanage-ibpkey.8
new file mode 100644
index 000..2da4f54
--- /dev/null
+++ b/python/semanage/semanage-ibpkey.8
@@ -0,0 +1,66 @@
+.TH "semanage-ibpkey" "8" "20170508" "" ""
+.SH "NAME"
+.B semanage\-ibpkey \- SELinux Policy Management ibpkey mapping tool
+.SH "SYNOPSIS"
+.B semanage ibpkey [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add \-t TYPE \-x 
SUBNET_PREFIX \-r RANGE ibpkey_name | ibpkey_range | \-\-delete \-x 
SUBNET_PREFIX ibpkey_name | ibpkey_range | \-\-deleteall  | \-\-extract  | 
\-\-list [\-C] | \-\-modify \-t TYPE \-x SUBNET_PREFIX \-r RANGE ibpkey_name | 
ibpkey_range ]
+
+.SH "DESCRIPTION"
+semanage is used to configure certain elements of SELinux policy without 
requiring modification to or recompilation from policy sources.  semanage 
ibpkey controls the ibpkey number to ibpkey type definitions.
+
+.SH "OPTIONS"
+.TP
+.I  \-h, \-\-help
+show this help message and exit
+.TP
+.I   \-n, \-\-noheading
+Do not print heading when listing the specified object type
+.TP
+.I   \-N, \-\-noreload
+Do not reload policy after commit
+.TP
+.I   \-S STORE, \-\-store STORE
+Select an alternate SELinux Policy Store to manage
+.TP
+.I   \-C, \-\-locallist
+List local customizations
+.TP
+.I   \-a, \-\-add
+Add a record of the specified object type
+.TP
+.I   \-d, \-\-delete
+Delete a record of the specified object type
+.TP
+.I   \-m, \-\-modify
+Modify a record of the specified object type
+.TP
+.I   \-l, \-\-list
+List records of the specified object type
+.TP
+.I   \-E, \-\-extract
+Extract customizable commands, for use within a transaction
+.TP
+.I   \-D, \-\-deleteall
+Remove all local customizations
+.TP
+.I   \-t TYPE, \-\-type TYPE
+SELinux type for the object
+.TP
+.I   \-r RANGE, \-\-range RANGE
+MLS/MCS Security Range (MLS/MCS Systems only) SELinux Range for SELinux login 
mapping defaults to the SELinux user record range. SELinux Range for SELinux 
user defaults to s0.
+.TP
+.I \-x SUBNET_PREFIX, \-\-subnet_prefix SUBNET_PREFIX
+Subnet prefix for the specified pkey or range 

[PATCH 5/9] libsepol: Add ibendport ocontext handling

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 0f12347..72431d6 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -701,6 +701,7 @@ int main(int argc, char **argv)
printf("i)  display constraint expressions\n");
printf("j)  display validatetrans expressions\n");
printf("k)  Call ibpkey_sid\n");
+   printf("l)  Call ibendport_sid\n");
 #ifdef EQUIVTYPES
printf("z)  Show equivalent types\n");
 #endif
@@ -1247,6 +1248,25 @@ int main(int argc, char **argv)
printf("sid %d\n", ssid);
}
break;
+   case 'l':
+   printf("device name (eg. mlx4_0)?  ");
+   FGETS(ans, sizeof(ans), stdin);
+   ans[strlen(ans) - 1] = 0;
+
+   name = malloc((strlen(ans) + 1) * sizeof(char));
+   if (!name) {
+   fprintf(stderr, "couldn't malloc string.\n");
+   break;
+   }
+   strcpy(name, ans);
+
+   printf("port? ");
+   FGETS(ans, sizeof(ans), stdin);
+   port = atoi(ans);
+   sepol_ibendport_sid(0, 0, name, port, );
+   printf("sid %d\n", ssid);
+   free(name);
+   break;
 #ifdef EQUIVTYPES
case 'z':
identify_equiv_types();
diff --git a/libsepol/include/sepol/policydb/services.h 
b/libsepol/include/sepol/policydb/services.h
index 2d7aed1..aa8d718 100644
--- a/libsepol/include/sepol/policydb/services.h
+++ b/libsepol/include/sepol/policydb/services.h
@@ -199,6 +199,16 @@ extern int sepol_ibpkey_sid(uint16_t domain,
  sepol_security_id_t *out_sid);
 
 /*
+ * Return the SID of the ibendport specified by
+ * `domain', `type', `dev_name', and `port'.
+ */
+extern int sepol_ibendport_sid(uint16_t domain,
+  uint16_t type,
+  char *dev_name,
+  uint8_t port,
+  sepol_security_id_t *out_sid);
+
+/*
  * Return the SIDs to use for a network interface
  * with the name `name'.  The `if_sid' SID is returned for 
  * the interface and the `msg_sid' SID is returned as
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index c45ecbe..061945e 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -2226,6 +2226,14 @@ static int ocontext_copy_selinux(expand_state_t *state)
n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey;
n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey;
break;
+   case OCON_IBENDPORT:
+   n->u.ibendport.dev_name = 
strdup(c->u.ibendport.dev_name);
+   if (!n->u.ibendport.dev_name) {
+   ERR(state->handle, "Out of memory!");
+   return -1;
+   }
+   n->u.ibendport.port = c->u.ibendport.port;
+   break;
case OCON_PORT:
n->u.port.protocol = c->u.port.protocol;
n->u.port.low_port = c->u.port.low_port;
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index 36225d1..dd1fec2 100644
--- a/libsepol/src/libsepol.map.in
+++ b/libsepol/src/libsepol.map.in
@@ -7,6 +7,7 @@ LIBSEPOL_1.0 {
sepol_iface_*; 
sepol_port_*;
sepol_ibpkey_*;
+   sepol_ibendport_*;
sepol_node_*;
sepol_user_*; sepol_genusers; sepol_set_delusers;
sepol_msg_*; sepol_debug;
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index db3f9c8..4b9f2c8 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -2585,6 +2585,7 @@ static int ocontext_selinux_isid_to_cil(struct policydb 
*pdb, 

[PATCH 1/9] checkpolicy: Add support for ibpkeycon labels

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 949ca71..6f92bc5 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -20,6 +20,7 @@
  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2008 Tresys Technology, LLC
  * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2017 Mellanox Techonologies Inc.
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 2.
@@ -4975,6 +4976,115 @@ int define_port_context(unsigned int low, unsigned int 
high)
return -1;
 }
 
+int define_ibpkey_context(unsigned int low, unsigned int high)
+{
+   ocontext_t *newc, *c, *l, *head;
+   struct in6_addr subnet_prefix;
+   char *id;
+   int rc = 0;
+
+   if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
+   yyerror("ibpkeycon not supported for target");
+   return -1;
+   }
+
+   if (pass == 1) {
+   id = (char *)queue_remove(id_queue);
+   free(id);
+   parse_security_context(NULL);
+   return 0;
+   }
+
+   newc = malloc(sizeof(*newc));
+   if (!newc) {
+   yyerror("out of memory");
+   return -1;
+   }
+   memset(newc, 0, sizeof(*newc));
+
+   id = queue_remove(id_queue);
+   if (!id) {
+   yyerror("failed to read the subnet prefix");
+   rc = -1;
+   goto out;
+   }
+
+   rc = inet_pton(AF_INET6, id, _prefix);
+   free(id);
+   if (rc < 1) {
+   yyerror("failed to parse the subnet prefix");
+   if (rc == 0)
+   rc = -1;
+   goto out;
+   }
+
+   if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) {
+   yyerror("subnet prefix should be 0's in the low order 64 
bits.");
+   rc = -1;
+   goto out;
+   }
+
+#ifdef DARWIN
+   memcpy(>u.ibpkey.subnet_prefix[0], _prefix.s6_addr[0],
+  sizeof(newc->u.ibpkey.subnet_prefix));
+#else
+   memcpy(>u.ibpkey.subnet_prefix[0], _prefix.s6_addr32[0],
+  sizeof(newc->u.ibpkey.subnet_prefix));
+#endif
+
+   newc->u.ibpkey.low_pkey = low;
+   newc->u.ibpkey.high_pkey = high;
+
+   if (low > high) {
+   yyerror2("low pkey %d exceeds high pkey %d", low, high);
+   rc = -1;
+   goto out;
+   }
+
+   rc = parse_security_context(>context[0]);
+   if (rc)
+   goto out;
+
+   /* Preserve the matching order specified in the configuration. */
+   head = policydbp->ocontexts[OCON_IBPKEY];
+   for (l = NULL, c = head; c; l = c, c = c->next) {
+   unsigned int low2, high2;
+
+   low2 = c->u.ibpkey.low_pkey;
+   high2 = c->u.ibpkey.high_pkey;
+
+   if (low == low2 && high == high2 &&
+   !memcmp(>u.ibpkey.subnet_prefix[0],
+   >u.ibpkey.subnet_prefix[0],
+   sizeof(c->u.ibpkey.subnet_prefix))) {
+   yyerror2("duplicate ibpkeycon entry for %d-%d ",
+low, high);
+   rc = -1;
+   goto out;
+   }
+   if (low2 <= low && high2 >= high &&
+   !memcmp(>u.ibpkey.subnet_prefix[0],
+   >u.ibpkey.subnet_prefix[0],
+   sizeof(c->u.ibpkey.subnet_prefix))) {
+   yyerror2("ibpkeycon entry for %d-%d hidden by earlier 
entry for %d-%d",
+low, high, low2, high2);
+   rc = -1;
+   goto out;
+   }
+   }
+
+   if (l)
+   l->next = newc;
+   else
+   policydbp->ocontexts[OCON_IBPKEY] = newc;
+
+   return 0;
+
+out:
+   free(newc);
+   return rc;
+}
+
 int define_netif_context(void)
 {
ocontext_t *newc, *c, *head;
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index 964baae..b019b1a 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -43,6 +43,7 @@ int 

[PATCH 8/9] semanage: Update semanage to allow runtime labeling of ibendports

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

diff --git a/libsemanage/include/semanage/ibendport_record.h 
b/libsemanage/include/semanage/ibendport_record.h
new file mode 100644
index 000..153eea0
--- /dev/null
+++ b/libsemanage/include/semanage/ibendport_record.h
@@ -0,0 +1,62 @@
+/*Copyright (C) 2005 Red Hat, Inc. */
+
+#ifndef _SEMANAGE_IBENDPORT_RECORD_H_
+#define _SEMANAGE_IBENDPORT_RECORD_H_
+
+#include 
+#include 
+#include 
+
+#ifndef _SEMANAGE_IBENDPORT_DEFINED_
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport semanage_ibendport_t;
+typedef struct semanage_ibendport_key semanage_ibendport_key_t;
+#define _SEMANAGE_IBENDPORT_DEFINED_
+#endif
+
+extern int semanage_ibendport_compare(const semanage_ibendport_t *ibendport,
+ const semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport,
+  const semanage_ibendport_t *ibendport2);
+
+extern int semanage_ibendport_key_create(semanage_handle_t *handle,
+const char *ibdev_name,
+int port,
+semanage_ibendport_key_t **key_ptr);
+
+extern int semanage_ibendport_key_extract(semanage_handle_t *handle,
+ const semanage_ibendport_t *ibendport,
+ semanage_ibendport_key_t **key_ptr);
+
+extern void semanage_ibendport_key_free(semanage_ibendport_key_t *key);
+
+extern int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle,
+const semanage_ibendport_t 
*ibendport,
+char **ibdev_name_ptr);
+
+extern int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle,
+semanage_ibendport_t *ibendport,
+const char *ibdev_name);
+
+extern int semanage_ibendport_get_port(const semanage_ibendport_t *ibendport);

[PATCH 0/9] SELinux user space support for Infiniband RDMA

2017-05-09 Thread Dan Jurgens
From: Daniel Jurgens 

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

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

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

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

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

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

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

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

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

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

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

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

 checkpolicy/checkpolicy.c|   47 ++
 checkpolicy/policy_define.c  |  180 
 checkpolicy/policy_define.h  |2 +
 checkpolicy/policy_parse.y   |   27 ++-
 checkpolicy/policy_scan.l|5 +
 libsemanage/include/semanage/ibendport_record.h  |   62 +++
 libsemanage/include/semanage/ibendports_local.h  |   36 ++
 libsemanage/include/semanage/ibendports_policy.h |   28 ++
 libsemanage/include/semanage/ibpey_record.h |   76 
 libsemanage/include/semanage/ibpkeys_local.h |   36 ++
 libsemanage/include/semanage/ibpkeys_policy.h|   28 ++
 libsemanage/include/semanage/semanage.h  |6 +
 libsemanage/src/direct_api.c |   57 +++-
 libsemanage/src/handle.h |   50 ++-
 libsemanage/src/ibendport_internal.h |   48 +++
 libsemanage/src/ibendport_record.c   |  154 +++
 libsemanage/src/ibendports_file.c|  157 +++
 libsemanage/src/ibendports_local.c   |  153 +++
 libsemanage/src/ibendports_policy.c  |   55 +++
 libsemanage/src/ibendports_policydb.c|   62 +++
 libsemanage/src/ibpkey_internal.h|   52 +++
 libsemanage/src/ibpkey_record.c  |  187 
 libsemanage/src/ibpkeys_file.c   |  181 
 libsemanage/src/ibpkeys_local.c  |  182 
 libsemanage/src/ibpkeys_policy.c |   52 +++
 libsemanage/src/ibpkeys_policydb.c   |   62 +++
 libsemanage/src/libsemanage.map  |2 +
 libsemanage/src/policy_components.c  |9 +-
 

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

2016-11-23 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

v4:
- removed unneeded brackets in ocontext_read. Paul Moore
---
 security/selinux/include/security.h |   3 +-
 security/selinux/ss/policydb.c  | 129 +++-
 security/selinux/ss/policydb.h  |  27 +---
 3 files changed, 135 insertions(+), 24 deletions(-)

diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index 308a286..6bb9b0a 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -36,10 +36,11 @@
 #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
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_XPERMS_IOCTL
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_INFINIBAND
 
 /* Mask for just the mount related flags */
 #define SE_MNTMASK 0x0f
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index d719db4..24e16da 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  

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

2016-11-23 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 affc8ef..48eaeca 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -53,6 +53,7 @@ struct ib_update_work {
 

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

2016-11-23 Thread Dan Jurgens
From: Daniel Jurgens <dani...@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 <jmor...@redhat.com> and Paul Moore
<p...@paul-moore.com> (see security/selinux/netif.c and
security/selinux/netport.c for more information)

Signed-off-by: Daniel Jurgens <dani...@mellanox.com>

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

v6:
- Fixed sel_pkey_sid_slow error handling. James Morris
---
 security/selinux/Makefile |   2 +-
 security/selinux/hooks.c  |   7 +-
 security/selinux/ibpkey.c | 245 ++
 security/selinux/include/ibpkey.h |  31 +
 security/selinux/include/objsec.h |   6 +
 5 files changed, 288 insertions(+), 3 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 55b18b3..7ee9854 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"
@@ -173,8 +174,10 @@ static int selinux_netcache_avc_callback(u32 event)
 
 static int selinux_lsm_notifier_avc_callback(u32 event)
 {
-   if (event == AVC_CALLBACK_RESET)
+   if (event == AVC_CALLBACK_RESET) {
+   sel_pkey_flush();
call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
+   }
 
return 0;
 }
@@ -6094,7 +6097,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..2ce12bb
--- /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 <jmor...@redhat.com> and
+ * Paul Moore <p...@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 
+#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

[PATCH v6 8/9] selinux: Add IB Port SMP access vector

2016-11-23 Thread Dan Jurgens
From: Daniel Jurgens 

Add a type for Infiniband ports and an access vector for subnet
management packets. Implement the ib_port_smp hook to check that the
caller has permission to send and receive SMPs on the end port specified
by the device name and port. Add interface to query the SID for a IB
port, which walks the IB_PORT ocontexts to find an entry for the
given name and port.

Signed-off-by: Daniel Jurgens 

---
v2:
- Shorted ib_end_port. Paul Moore
- Pass void blobs to security hooks. Paul Moore
- Log specific IB port info in audit log. Paul Moore
- Don't create a new intial sid, use unlabeled. Stephen Smalley
- Changed "smp" to "manage_subnet". Paul Moore

v3:
- ib_port -> ib_endport. Paul Moore
- Don't log device name as untrusted string. Paul Moore
- Reorder parameters of LSM hook. Paul Moore

v6:
- Remove brakets around single statement else. James Morris
---
 include/linux/lsm_audit.h   |  8 
 security/lsm_audit.c|  5 +
 security/selinux/hooks.c| 25 ++
 security/selinux/include/classmap.h |  2 ++
 security/selinux/include/security.h |  2 ++
 security/selinux/ss/services.c  | 41 +
 6 files changed, 83 insertions(+)

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 402b770..7047b4c 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct lsm_network_audit {
int netif;
@@ -50,6 +51,11 @@ struct lsm_pkey_audit {
u16 pkey;
 };
 
+struct lsm_ib_endport_audit {
+   chardev_name[IB_DEVICE_NAME_MAX];
+   u8  port_num;
+};
+
 /* Auxiliary data to use in generating the audit record. */
 struct common_audit_data {
char type;
@@ -66,6 +72,7 @@ struct common_audit_data {
 #define LSM_AUDIT_DATA_IOCTL_OP11
 #define LSM_AUDIT_DATA_FILE12
 #define LSM_AUDIT_DATA_PKEY13
+#define LSM_AUDIT_DATA_IB_ENDPORT 14
union   {
struct path path;
struct dentry *dentry;
@@ -84,6 +91,7 @@ struct common_audit_data {
struct lsm_ioctlop_audit *op;
struct file *file;
struct lsm_pkey_audit *pkey;
+   struct lsm_ib_endport_audit *ib_endport;
} u;
/* this union contains LSM specific data */
union {
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 8911360..d8d58ec 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -421,6 +421,11 @@ static void dump_common_audit_data(struct audit_buffer *ab,
 a->u.pkey->pkey, _pfx);
break;
}
+   case LSM_AUDIT_DATA_IB_ENDPORT:
+   audit_log_format(ab, " device=%s port_num=%u",
+a->u.ib_endport->dev_name,
+a->u.ib_endport->port_num);
+   break;
} /* switch (a->type) */
 }
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 94eef1b..55b18b3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6107,6 +6107,29 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 
subnet_prefix, u16 pkey_val)
INFINIBAND_PKEY__ACCESS, );
 }
 
+static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
+   u8 port_num)
+{
+   struct common_audit_data ad;
+   int err;
+   u32 sid = 0;
+   struct ib_security_struct *sec = ib_sec;
+   struct lsm_ib_endport_audit ib_endport;
+
+   err = security_ib_endport_sid(dev_name, port_num, );
+
+   if (err)
+   return err;
+
+   ad.type = LSM_AUDIT_DATA_IB_ENDPORT;
+   strncpy(ib_endport.dev_name, dev_name, sizeof(ib_endport.dev_name));
+   ib_endport.port_num = port_num;
+   ad.u.ib_endport = _endport;
+   return avc_has_perm(sec->sid, sid,
+   SECCLASS_INFINIBAND_ENDPORT,
+   INFINIBAND_ENDPORT__MANAGE_SUBNET, );
+}
+
 static int selinux_ib_alloc_security(void **ib_sec)
 {
struct ib_security_struct *sec;
@@ -6312,6 +6335,8 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
 #ifdef CONFIG_SECURITY_INFINIBAND
LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
+   LSM_HOOK_INIT(ib_endport_manage_subnet,
+ selinux_ib_endport_manage_subnet),
LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
 #endif
diff --git a/security/selinux/include/classmap.h 
b/security/selinux/include/classmap.h
index d42dd4d..f93b64b 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -167,5 +167,7 @@ struct security_class_mapping 

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

2016-11-23 Thread Dan Jurgens
From: Daniel Jurgens <dani...@mellanox.com>

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

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

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

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

An Infiniband port is labeled by device name and port number. There is a single
access vector for IB 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, collectively
known as a Queue Pair (QP). A QP must be initialized by privileged system calls
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 control 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 and move logic to IB security. Dan 
Jurgens
- Changed ib_end_port to ib_port. Paul Moore
- Changed ib_port access vector

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

2016-11-23 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 1a2984c..affc8ef 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -934,6 +934,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,
@@ -1110,6 +1130,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);
@@ -1168,9 +1190,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;
}
 
@@ -1213,6 +1244,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 5ad43a4..db178fd 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1761,6 +1761,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 {
-- 
2.7.4

___
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 v5 5/9] selinux: Create policydb version for Infiniband support

2016-11-22 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

v4:
- removed unneeded brackets in ocontext_read. Paul Moore
---
 security/selinux/include/security.h |   3 +-
 security/selinux/ss/policydb.c  | 129 +++-
 security/selinux/ss/policydb.h  |  27 +---
 3 files changed, 135 insertions(+), 24 deletions(-)

diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index 308a286..6bb9b0a 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -36,10 +36,11 @@
 #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
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_XPERMS_IOCTL
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_INFINIBAND
 
 /* Mask for just the mount related flags */
 #define SE_MNTMASK 0x0f
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index d719db4..24e16da 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  

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

2016-11-22 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 affc8ef..48eaeca 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -53,6 +53,7 @@ struct ib_update_work {
 

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

2016-11-22 Thread Dan Jurgens
From: Daniel Jurgens <dani...@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 <jmor...@redhat.com> and Paul Moore
<p...@paul-moore.com> (see security/selinux/netif.c and
security/selinux/netport.c for more information)

Signed-off-by: Daniel Jurgens <dani...@mellanox.com>

---
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  |   7 +-
 security/selinux/ibpkey.c | 245 ++
 security/selinux/include/ibpkey.h |  31 +
 security/selinux/include/objsec.h |   6 +
 5 files changed, 288 insertions(+), 3 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 0954dfe..2fe4320 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"
@@ -173,8 +174,10 @@ static int selinux_netcache_avc_callback(u32 event)
 
 static int selinux_lsm_notifier_avc_callback(u32 event)
 {
-   if (event == AVC_CALLBACK_RESET)
+   if (event == AVC_CALLBACK_RESET) {
+   sel_pkey_flush();
call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
+   }
 
return 0;
 }
@@ -6094,7 +6097,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 <jmor...@redhat.com> and
+ * Paul Moore <p...@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 
+#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
+

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

2016-11-22 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 2d7a7c1..d87e29d 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,
@@ -6082,7 +6083,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[] = {
@@ -6269,7 +6289,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_ */
-- 
2.7.4

___
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 v5 4/9] IB/core: Enforce security on management datagrams

2016-11-22 Thread Dan Jurgens
From: Daniel Jurgens <dani...@mellanox.com>

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 <dani...@mellanox.com>

---
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 40cbd6b..b6041ec 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_agen

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

2016-11-22 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

v4:
- Seperate avc callback for LSM notifier. Paul Moore

v5:
- Fix link error when CONFIG_SECURITY is not set. Build Robot
---
 drivers/infiniband/core/device.c | 53 
 include/linux/security.h | 23 +
 security/security.c  | 20 +++
 security/selinux/hooks.c | 11 +
 security/selinux/selinuxfs.c |  2 ++
 5 files changed, 109 insertions(+)

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 @@ static int __init ib_core_init(void)
 
 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 342ca4c..0a5de0c 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -69,6 +69,10 @@ struct audit_krule;
 struct user_namespace;
 struct timezone;
 
+enum lsm_event {
+   LSM_POLICY_CHANGE,
+};
+
 /* These functions are in security/commoncap.c */
 extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
   int cap, int audit);
@@ -161,6 +165,10 @@ struct security_mnt_opts {
int num_mnt_opts;
 };
 
+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);
+
 static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
 {
opts->mnt_opts = NULL;
@@ -377,6 +385,21 @@ int security_inode_getsecctx(struct inode *inode, void 
**ctx, u32 

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

2016-11-22 Thread Dan Jurgens
From: Daniel Jurgens <dani...@mellanox.com>

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

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

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

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

An Infiniband port is labeled by device name and port number. There is a single
access vector for IB 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, collectively
known as a Queue Pair (QP). A QP must be initialized by privileged system calls
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 control 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 and move logic to IB security. Dan 
Jurgens
- Changed ib_end_port to ib_port. Paul Moore
- Changed ib_port access vector

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

2016-11-08 Thread Dan Jurgens
From: Daniel Jurgens 

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

issue: 736423
Change-Id: I3bdbecee7aab6d7615a02967c39a5a8792a14d44
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

Signed-off-by: Daniel Jurgens 
---
 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 7578198..f48759d 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,
@@ -6082,7 +6083,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[] = {
@@ -6269,7 +6289,10 @@ static int selinux_key_getsecurity(struct key *key, char 
**_buffer)
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 v4 3/9] selinux lsm IB/core: Implement LSM notification system

2016-11-08 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.

issue: 736423
Change-Id: I9f5a13026c9219105ee5e0cd99edf8eabdafe946
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

v4:
- Seperate avc callback for LSM notifier. Paul Moore

Signed-off-by: Daniel Jurgens 
---
 drivers/infiniband/core/device.c | 53 
 include/linux/security.h |  8 ++
 security/security.c  | 20 +++
 security/selinux/hooks.c | 11 +
 security/selinux/selinuxfs.c |  2 ++
 5 files changed, 94 insertions(+)

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 @@ struct ib_client_data {
 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 @@ static int __init ib_core_init(void)
 
 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 342ca4c..d8c29cd 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -69,6 +69,14 @@
 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 7d3bf2f..40326d4 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 

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

2016-11-08 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.

issue: 736423
Change-Id: I0509141a57a8e08c91a9e0c059800251949b18e6
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

Signed-off-by: Daniel Jurgens 
---
 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 affc8ef..48eaeca 

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

2016-11-08 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.

issue: 736423
Change-Id: Ib3f7df9b5f98da77a6048855d146f9dcaceba336
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

Signed-off-by: Daniel Jurgens 
---
 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 e58e577..402b770 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;
@@ -60,6 +65,7 @@ struct common_audit_data {
 #define LSM_AUDIT_DATA_DENTRY  10
 #define LSM_AUDIT_DATA_IOCTL_OP11
 #define LSM_AUDIT_DATA_FILE12
+#define LSM_AUDIT_DATA_PKEY13
union   {
struct path path;
struct dentry *dentry;
@@ -77,6 +83,7 @@ struct common_audit_data {
char *kmod_name;
struct lsm_ioctlop_audit *op;
struct file *file;
+   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 37f04da..b18d277 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -410,6 +410,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 f48759d..20fb292 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6086,6 +6086,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;
@@ -6290,6 +6312,7 @@ static void selinux_ib_free_security(void *ib_sec)
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 

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

2016-11-08 Thread Dan Jurgens
From: Daniel Jurgens <dani...@mellanox.com>

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.

issue: 736423
Change-Id: I17343224da7e7ee0cc67dadd44c473e453d0
Signed-off-by: Daniel Jurgens <dani...@mellanox.com>

---
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

Signed-off-by: Daniel Jurgens <dani...@mellanox.com>
---
 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 @@ int ib_security_modify_qp(struct ib_qp *qp,
 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 40cbd6b..b6041ec 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-&g

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

2016-11-08 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.

issue: 736423
Change-Id: I906bf7a1e0bd59c3cccdce278e5fe98ba8c404b8
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

v4:
- removed unneeded brackets in ocontext_read. Paul Moore

Signed-off-by: Daniel Jurgens 
---
 security/selinux/include/security.h |   3 +-
 security/selinux/ss/policydb.c  | 129 +++-
 security/selinux/ss/policydb.h  |  27 +---
 3 files changed, 135 insertions(+), 24 deletions(-)

diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index 308a286..6bb9b0a 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -36,10 +36,11 @@
 #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
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_XPERMS_IOCTL
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_INFINIBAND
 
 /* Mask for just the mount related flags */
 #define SE_MNTMASK 0x0f
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index d719db4..24e16da 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 @@ struct policydb_compat_info {
{
.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= 

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

2016-11-08 Thread Dan Jurgens
From: Daniel Jurgens <dani...@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 <jmor...@redhat.com> and Paul Moore
<p...@paul-moore.com> (see security/selinux/netif.c and
security/selinux/netport.c for more information)

issue: 736423
Change-Id: I176c3079d5d84d06839b4f750100ac47a6081e94
Signed-off-by: Daniel Jurgens <dani...@mellanox.com>

---
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

Signed-off-by: Daniel Jurgens <dani...@mellanox.com>
---
 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 ea3f6d0..619d2ea 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"
@@ -174,6 +175,7 @@ static int selinux_netcache_avc_callback(u32 event)
 static int selinux_lsm_notifier_avc_callback(u32 event)
 {
if (event == AVC_CALLBACK_RESET) {
+   sel_pkey_flush();
call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
}
return 0;
@@ -6094,7 +6096,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 <jmor...@redhat.com> and
+ * Paul Moore <p...@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 
+#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

[PATCH v4 8/9] selinux: Add IB Port SMP access vector

2016-11-08 Thread Dan Jurgens
From: Daniel Jurgens 

Add a type for Infiniband ports and an access vector for subnet
management packets. Implement the ib_port_smp hook to check that the
caller has permission to send and receive SMPs on the end port specified
by the device name and port. Add interface to query the SID for a IB
port, which walks the IB_PORT ocontexts to find an entry for the
given name and port.

issue: 736423
Change-Id: If8b365f3cf32e77a2060073f1a53e27ea846804d
Signed-off-by: Daniel Jurgens 

---
v2:
- Shorted ib_end_port. Paul Moore
- Pass void blobs to security hooks. Paul Moore
- Log specific IB port info in audit log. Paul Moore
- Don't create a new intial sid, use unlabeled. Stephen Smalley
- Changed "smp" to "manage_subnet". Paul Moore

v3:
- ib_port -> ib_endport. Paul Moore
- Don't log device name as untrusted string. Paul Moore
- Reorder parameters of LSM hook. Paul Moore

Signed-off-by: Daniel Jurgens 
---
 include/linux/lsm_audit.h   |  8 +++
 security/lsm_audit.c|  5 +
 security/selinux/hooks.c| 25 ++
 security/selinux/include/classmap.h |  2 ++
 security/selinux/include/security.h |  2 ++
 security/selinux/ss/services.c  | 42 +
 6 files changed, 84 insertions(+)

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 402b770..7047b4c 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct lsm_network_audit {
int netif;
@@ -50,6 +51,11 @@ struct lsm_pkey_audit {
u16 pkey;
 };
 
+struct lsm_ib_endport_audit {
+   chardev_name[IB_DEVICE_NAME_MAX];
+   u8  port_num;
+};
+
 /* Auxiliary data to use in generating the audit record. */
 struct common_audit_data {
char type;
@@ -66,6 +72,7 @@ struct common_audit_data {
 #define LSM_AUDIT_DATA_IOCTL_OP11
 #define LSM_AUDIT_DATA_FILE12
 #define LSM_AUDIT_DATA_PKEY13
+#define LSM_AUDIT_DATA_IB_ENDPORT 14
union   {
struct path path;
struct dentry *dentry;
@@ -84,6 +91,7 @@ struct common_audit_data {
struct lsm_ioctlop_audit *op;
struct file *file;
struct lsm_pkey_audit *pkey;
+   struct lsm_ib_endport_audit *ib_endport;
} u;
/* this union contains LSM specific data */
union {
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index b18d277..549fe9d 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -423,6 +423,11 @@ static void dump_common_audit_data(struct audit_buffer *ab,
 a->u.pkey->pkey, _pfx);
break;
}
+   case LSM_AUDIT_DATA_IB_ENDPORT:
+   audit_log_format(ab, " device=%s port_num=%u",
+a->u.ib_endport->dev_name,
+a->u.ib_endport->port_num);
+   break;
} /* switch (a->type) */
 }
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 20fb292..ea3f6d0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6108,6 +6108,29 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 
subnet_prefix, u16 pkey_val)
INFINIBAND_PKEY__ACCESS, );
 }
 
+static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
+   u8 port_num)
+{
+   struct common_audit_data ad;
+   int err;
+   u32 sid = 0;
+   struct ib_security_struct *sec = ib_sec;
+   struct lsm_ib_endport_audit ib_endport;
+
+   err = security_ib_endport_sid(dev_name, port_num, );
+
+   if (err)
+   return err;
+
+   ad.type = LSM_AUDIT_DATA_IB_ENDPORT;
+   strncpy(ib_endport.dev_name, dev_name, sizeof(ib_endport.dev_name));
+   ib_endport.port_num = port_num;
+   ad.u.ib_endport = _endport;
+   return avc_has_perm(sec->sid, sid,
+   SECCLASS_INFINIBAND_ENDPORT,
+   INFINIBAND_ENDPORT__MANAGE_SUBNET, );
+}
+
 static int selinux_ib_alloc_security(void **ib_sec)
 {
struct ib_security_struct *sec;
@@ -6313,6 +6336,8 @@ static void selinux_ib_free_security(void *ib_sec)
LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
 #ifdef CONFIG_SECURITY_INFINIBAND
LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
+   LSM_HOOK_INIT(ib_endport_manage_subnet,
+ selinux_ib_endport_manage_subnet),
LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
 #endif
diff --git a/security/selinux/include/classmap.h 
b/security/selinux/include/classmap.h
index d42dd4d..f93b64b 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h

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

2016-11-08 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.

issue: 736423
Change-Id: Ifdef64b097a8d1d55db65f08ce401d9d2e4b025e
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

Signed-off-by: Daniel Jurgens 
---
 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 1a2984c..affc8ef 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -934,6 +934,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,
@@ -1110,6 +1130,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);
@@ -1168,9 +1190,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;
}
 
@@ -1213,6 +1244,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 5ad43a4..db178fd 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1761,6 +1761,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 v4 0/9] SELinux support for Infiniband RDMA

2016-11-08 Thread Dan Jurgens
From: Daniel Jurgens <dani...@mellanox.com>

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

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

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

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

An Infiniband port is labeled by device name and port number. There is a single
access vector for IB 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, collectively
known as a Queue Pair (QP). A QP must be initialized by privileged system calls
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 control 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 and move logic to IB security. Dan 
Jurgens
- Changed ib_end_port to ib_port. Paul Moore
- Changed ib_port access vector

[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 <dani...@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 <jmor...@redhat.com> and Paul Moore
<p...@paul-moore.com> (see security/selinux/netif.c and
security/selinux/netport.c for more information)

Signed-off-by: Daniel Jurgens <dani...@mellanox.com>

---
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 <jmor...@redhat.com> and
+ * Paul Moore <p...@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 
+#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 a

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

2016-07-29 Thread Dan Jurgens
From: Daniel Jurgens <dani...@mellanox.com>

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 <dani...@mellanox.com>

---
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_agen

[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 <dani...@mellanox.com>

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. Pa

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

2016-07-15 Thread Dan Jurgens
From: Daniel Jurgens <dani...@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 <jmor...@redhat.com> and Paul Moore
<p...@paul-moore.com> (see security/selinux/netif.c and
security/selinux/netport.c for more information)

Signed-off-by: Daniel Jurgens <dani...@mellanox.com>

---
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  |5 +-
 security/selinux/ibpkey.c |  245 +
 security/selinux/include/ibpkey.h |   31 +
 security/selinux/include/objsec.h |6 +
 5 files changed, 287 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 40ad0e8..3423c0c 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,8 @@ static int selinux_cache_avc_callback(u32 event)
sel_netnode_flush();
sel_netport_flush();
synchronize_net();
+
+   sel_pkey_flush();
security_lsm_notify(LSM_POLICY_CHANGE, NULL);
}
return 0;
@@ -6003,7 +6006,7 @@ static int selinux_ib_pkey_access(u64 subnet_prefix, u16 
pkey_val, void *ib_sec)
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 <jmor...@redhat.com> and
+ * Paul Moore <p...@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 
+#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 pke

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

2016-07-15 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
---
 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(+), 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_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 fe3d20d..d9c4bfa 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(u64 subnet_prefix, u16 pkey_val, void 
*ib_sec)
+{
+   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 callsid, char *username,
 
 int 

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

2016-07-15 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 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a363202..fe3d20d 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.7.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 v2 4/9] IB/core: Enforce security on management datagrams

2016-07-15 Thread Dan Jurgens
From: Daniel Jurgens <dani...@mellanox.com>

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 <dani...@mellanox.com>

---
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
---
 drivers/infiniband/core/core_priv.h |   35 +
 drivers/infiniband/core/mad.c   |   52 +---
 drivers/infiniband/core/security.c  |   90 +++
 include/linux/lsm_hooks.h   |7 +++
 include/linux/security.h|6 ++
 include/rdma/ib_mad.h   |4 ++
 security/security.c |8 +++
 7 files changed, 194 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);
+   goto error4;
+   }
+
spin_lock_ir

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

2016-07-15 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 
Reviewed-by: Leon Romanovsky 

---
v2:
- Squashed LSM hook additions. Paul Moore
- Changed security blobs to void*. 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 v2 3/9] selinux lsm IB/core: Implement LSM notification system

2016-07-15 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 is from SELinux when the AVC
cache changes.

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
---
 drivers/infiniband/core/device.c |   46 ++
 include/linux/security.h |   10 ++
 security/security.c  |   58 ++
 security/selinux/hooks.c |5 ++-
 security/selinux/selinuxfs.c |2 +
 5 files changed, 119 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 5b42e83..3219a7a 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -39,6 +39,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -82,6 +83,10 @@ static LIST_HEAD(client_list);
 static DEFINE_MUTEX(device_mutex);
 static DECLARE_RWSEM(lists_rwsem);
 
+static void ib_policy_change_task(struct work_struct *work);
+static DECLARE_WORK(ib_policy_change_work, ib_policy_change_task);
+
+static u32 lsm_callback_id;
 
 static int ib_device_check_mandatory(struct ib_device *device)
 {
@@ -344,6 +349,37 @@ 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 void ib_security_change(enum lsm_event event, void *ctx, void *lsm_data)
+{
+   if (event != LSM_POLICY_CHANGE)
+   return;
+
+   schedule_work(_policy_change_work);
+}
+
 /**
  * ib_register_device - Register an IB device with IB core
  * @device:Device to register
@@ -1075,10 +,19 @@ static int __init ib_core_init(void)
goto err_sa;
}
 
+   ret = security_register_lsm_notifier(_security_change, NULL,
+_callback_id);
+   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 +1143,7 @@ err:
 
 static void __exit ib_core_cleanup(void)
 {
+   security_unregister_lsm_notifier(lsm_callback_id);
ib_cache_cleanup();
ib_remove_ibnl_clients();
ib_sa_cleanup();
diff --git a/include/linux/security.h b/include/linux/security.h
index 33e23c4..bf53911 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -69,6 +69,16 @@ struct audit_krule;
 struct user_namespace;
 struct timezone;
 
+enum lsm_event {
+   LSM_POLICY_CHANGE,
+};
+
+typedef void (*lsm_notifier)(enum lsm_event event, void *ctx, void *data);
+
+void security_lsm_notify(enum lsm_event event, void *data);
+int security_register_lsm_notifier(lsm_notifier func, void *ctx, u32 *id);
+void security_unregister_lsm_notifier(u32 id);
+
 /* 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 234982d..1263c1d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -33,6 +33,18 @@
 /* Maximum number of letters for an LSM name string */
 #define SECURITY_NAME_MAX  10
 
+struct lsm_notifier_entry {
+   u32 callback_id;
+   lsm_notifierfunc;
+   void*ctx;
+   struct list_headlist;
+   struct rcu_head rcu;
+};
+
+static LIST_HEAD(lsm_notifier_list);
+static DEFINE_SPINLOCK(lsm_notifier_lock);
+static u32 

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

2016-07-15 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.7.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 06/12] selinux: Add IB End Port SMP access vector

2016-06-23 Thread Dan Jurgens
From: Daniel Jurgens 

Add a type for Infiniband end ports and an access vector for subnet
management packets. Implement the ib_end_port_smp hook to check that the
caller has permission to send and receive SMPs on the end port specified
by the device name and port.  Add interface to query the SID for a IB
end port, which walks the IB_END_PORT ocontexts to find an entry for the
given name and port.

Signed-off-by: Daniel Jurgens 
Reviewed-by: Eli Cohen 
---
 include/linux/lsm_audit.h| 32 +++---
 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, 95 insertions(+), 12 deletions(-)

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 8ff7eae..acf6de7 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct lsm_network_audit {
int netif;
@@ -50,21 +51,27 @@ struct lsm_pkey_audit {
u16 pkey;
 };
 
+struct lsm_ib_end_port_audit {
+   chardev_name[IB_DEVICE_NAME_MAX];
+   u8  port;
+};
+
 /* Auxiliary data to use in generating the audit record. */
 struct common_audit_data {
char type;
-#define LSM_AUDIT_DATA_PATH1
-#define LSM_AUDIT_DATA_NET 2
-#define LSM_AUDIT_DATA_CAP 3
-#define LSM_AUDIT_DATA_IPC 4
-#define LSM_AUDIT_DATA_TASK5
-#define LSM_AUDIT_DATA_KEY 6
-#define LSM_AUDIT_DATA_NONE7
-#define LSM_AUDIT_DATA_KMOD8
-#define LSM_AUDIT_DATA_INODE   9
-#define LSM_AUDIT_DATA_DENTRY  10
-#define LSM_AUDIT_DATA_IOCTL_OP11
-#define LSM_AUDIT_DATA_PKEY12
+#define LSM_AUDIT_DATA_PATH1
+#define LSM_AUDIT_DATA_NET 2
+#define LSM_AUDIT_DATA_CAP 3
+#define LSM_AUDIT_DATA_IPC 4
+#define LSM_AUDIT_DATA_TASK5
+#define LSM_AUDIT_DATA_KEY 6
+#define LSM_AUDIT_DATA_NONE7
+#define LSM_AUDIT_DATA_KMOD8
+#define LSM_AUDIT_DATA_INODE   9
+#define LSM_AUDIT_DATA_DENTRY  10
+#define LSM_AUDIT_DATA_IOCTL_OP11
+#define LSM_AUDIT_DATA_PKEY12
+#define LSM_AUDIT_DATA_IB_END_PORT 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_ib_end_port_audit *ib_end_port;
} u;
/* this union contains LSM specific data */
union {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5a40b10..fc44542 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6056,6 +6056,32 @@ static int selinux_ib_mad_agent_pkey_access(u64 
subnet_prefix, u16 pkey_val,
mad_agent->m_security);
 }
 
+static int selinux_ib_end_port_smp(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_ib_end_port_audit ib_end_port;
+
+   err = security_ib_end_port_sid(dev_name, port, );
+
+   if (err)
+   goto out;
+
+   ad.type = LSM_AUDIT_DATA_IB_END_PORT;
+   strncpy(ib_end_port.dev_name, dev_name, sizeof(ib_end_port.dev_name));
+   ib_end_port.port = port;
+   ad.u.ib_end_port = _end_port;
+   err = avc_has_perm(sec->sid, sid,
+  SECCLASS_INFINIBAND_END_PORT,
+  INFINIBAND_END_PORT__SMP, );
+
+out:
+   return err;
+}
+
 static int selinux_ib_qp_alloc_security(struct ib_qp_security *qp_sec)
 {
struct ib_security_struct *sec;
@@ -6289,6 +6315,7 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(ib_qp_pkey_access, selinux_ib_qp_pkey_access),
LSM_HOOK_INIT(ib_mad_agent_pkey_access,
  selinux_ib_mad_agent_pkey_access),
+   LSM_HOOK_INIT(ib_end_port_smp, selinux_ib_end_port_smp),
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 d42dd4d..21972c8 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -167,5 +167,7 @@ struct security_class_mapping secclass_map[] = {
  { COMMON_CAP2_PERMS, NULL } },
{ "infiniband_pkey",
  { "access", NULL } },
+  

[PATCH 04/12] selinux: Allocate and free infiniband security hooks

2016-06-23 Thread Dan Jurgens
From: Daniel Jurgens 

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

Signed-off-by: Daniel Jurgens 
Reviewed-by: Eli Cohen 
---
 include/rdma/ib_mad.h |  1 +
 include/rdma/ib_verbs.h   |  1 +
 security/selinux/hooks.c  | 53 +++
 security/selinux/include/objsec.h |  5 
 4 files changed, 60 insertions(+)

diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index c8a773f..a1ed025 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -537,6 +537,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 3f6780b..e522acb 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1454,6 +1454,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 6a8841d..4f13ea4 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,
@@ -83,6 +84,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "avc.h"
 #include "objsec.h"
@@ -6015,6 +6018,47 @@ static void selinux_unregister_ib_flush_callback(void)
mutex_unlock(_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[] = {
@@ -6198,11 +6242,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 
+ *  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

___

[PATCH 10/12] IB/core: Enforce PKey security on management datagrams

2016-06-23 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.

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 
Reviewed-by: Eli Cohen 
Reviewed-by: Leon Romanovsky 
---
 drivers/infiniband/core/core_priv.h | 13 
 drivers/infiniband/core/mad.c   | 63 -
 drivers/infiniband/core/security.c  | 24 ++
 3 files changed, 93 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/core/core_priv.h 
b/drivers/infiniband/core/core_priv.h
index 68e3de0..8ab8d58 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -166,6 +166,11 @@ int ib_get_cached_subnet_prefix(struct ib_device *device,
u64  *sn_pfx);
 
 #ifdef CONFIG_SECURITY_INFINIBAND
+int ib_security_ma_pkey_access(struct ib_device *dev,
+  u8 port_num,
+  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,
@@ -184,6 +189,14 @@ 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);
 #else
+static inline int ib_security_ma_pkey_access(struct ib_device *dev,
+u8 port_num,
+u16 pkey_index,
+struct ib_mad_agent *mad_agent)
+{
+   return 0;
+}
+
 static inline void ib_security_destroy_port_pkey_list(struct ib_device *device)
 {
 }
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 82fb511..975b472 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"
@@ -337,11 +339,17 @@ struct ib_mad_agent *ib_register_mad_agent(struct 
ib_device *device,
goto error1;
}
 
+   ret2 = security_ib_mad_agent_alloc_security(_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;
}
}
 
@@ -384,7 +392,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device 
*device,
if (method) {
if (method_in_use(,
   mad_reg_req))
-   goto error4;
+   goto error5;
}
}
ret2 = add_nonoui_reg_req(mad_reg_req, mad_agent_priv,
@@ -400,14 +408,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;
}
}
 
@@ -417,9 +425,11 @@ struct ib_mad_agent *ib_register_mad_agent(struct 
ib_device *device,
 
return _agent_priv->agent;
 
-error4:
+error5:
spin_unlock_irqrestore(_priv->reg_lock, flags);
kfree(reg_req);
+error4:
+   security_ib_mad_agent_free_security(_agent_priv->agent);
 error3:
kfree(mad_agent_priv);
 error1:
@@ -489,6 +499,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) ||
@@ -513,6 +524,13 @@ struct ib_mad_agent *ib_register_mad_snoop(struct 

[PATCH 08/12] IB/core: IB cache enhancements to support Infiniband security

2016-06-23 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 
---
 drivers/infiniband/core/cache.c | 35 +--
 drivers/infiniband/core/core_priv.h |  3 +++
 include/rdma/ib_verbs.h |  1 +
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index c2e257d..4894e21 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -926,6 +926,25 @@ 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 = port_num - rdma_start_port(device);
+
+   if (port_num < rdma_start_port(device) ||
+   port_num > rdma_end_port(device))
+   return -EINVAL;
+
+   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,
@@ -1102,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(>cache.lock);
 
kfree(gid_cache);
@@ -1160,9 +1181,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;
}
 
@@ -1205,6 +1235,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 e522acb..c00b6b1 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1637,6 +1637,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.


  1   2   >