[PATCH v1 1/1] IB/core: Fix static analysis warning in ib_policy_change_task
From: Daniel Jurgensib_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
From: Daniel Jurgensib_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
From: Daniel JurgensCheck 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
From: Daniel JurgensNew 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
From: Daniel JurgensNew 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
From: Daniel JurgensImplements 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.
From: Daniel JurgensSigned-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
From: Daniel JurgensNew 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
From: Daniel JurgensNew 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
From: Daniel JurgensImplements 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensInfiniband 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
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
From: Daniel JurgensSupport 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensImplement 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
From: Daniel JurgensCache 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensInfiniband 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
From: Daniel JurgensNew 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
From: Daniel JurgensNew 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensUpdate 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
From: Daniel JurgensInfiniband 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
From: Daniel JurgensSupport 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
From: Daniel JurgensAdd 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
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
From: Daniel JurgensAdd 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
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
From: Daniel JurgensCache 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
From: Daniel JurgensSupport 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
From: Daniel JurgensAdd 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
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
From: Daniel JurgensImplement 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
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
From: Daniel JurgensAdd 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
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
From: Daniel JurgensImplement 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
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
From: Daniel JurgensSupport 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
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
From: Daniel JurgensAdd 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
From: Daniel JurgensCache 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
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
From: Daniel JurgensAdd 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
From: Daniel JurgensImplement 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
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
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
From: Daniel JurgensSupport 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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensCache 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
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
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
From: Daniel JurgensAdd 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
From: Daniel JurgensImplement 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
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
From: Daniel JurgensAdd 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
From: Daniel JurgensAdd 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
From: Daniel JurgensCache 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
From: Daniel JurgensAdd 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
From: Daniel JurgensImplement 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
From: Daniel JurgensAllocate 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
From: Daniel JurgensCache 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.