Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
5965453d
cloud-kernel
项目概览
openanolis
/
cloud-kernel
大约 2 年 前同步成功
通知
173
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5965453d
编写于
6月 23, 2017
作者:
J
James Morris
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'stable-4.13' of
git://git.infradead.org/users/pcmoore/selinux
into next
上级
fc26bd50
6a391183
变更
31
隐藏空白更改
内联
并排
Showing
31 changed file
with
2028 addition
and
129 deletion
+2028
-129
drivers/infiniband/core/Makefile
drivers/infiniband/core/Makefile
+2
-1
drivers/infiniband/core/cache.c
drivers/infiniband/core/cache.c
+40
-3
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/core_priv.h
+115
-0
drivers/infiniband/core/device.c
drivers/infiniband/core/device.c
+86
-0
drivers/infiniband/core/mad.c
drivers/infiniband/core/mad.c
+44
-8
drivers/infiniband/core/security.c
drivers/infiniband/core/security.c
+705
-0
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_cmd.c
+11
-4
drivers/infiniband/core/verbs.c
drivers/infiniband/core/verbs.c
+26
-1
fs/nfs/super.c
fs/nfs/super.c
+16
-1
include/linux/lsm_audit.h
include/linux/lsm_audit.h
+15
-0
include/linux/lsm_hooks.h
include/linux/lsm_hooks.h
+38
-1
include/linux/security.h
include/linux/security.h
+56
-2
include/rdma/ib_mad.h
include/rdma/ib_mad.h
+4
-0
include/rdma/ib_verbs.h
include/rdma/ib_verbs.h
+49
-0
security/Kconfig
security/Kconfig
+9
-0
security/lsm_audit.c
security/lsm_audit.c
+16
-0
security/security.c
security/security.c
+53
-2
security/selinux/Makefile
security/selinux/Makefile
+1
-1
security/selinux/hooks.c
security/selinux/hooks.c
+176
-36
security/selinux/ibpkey.c
security/selinux/ibpkey.c
+245
-0
security/selinux/include/classmap.h
security/selinux/include/classmap.h
+5
-1
security/selinux/include/ibpkey.h
security/selinux/include/ibpkey.h
+31
-0
security/selinux/include/objsec.h
security/selinux/include/objsec.h
+11
-0
security/selinux/include/security.h
security/selinux/include/security.h
+8
-1
security/selinux/selinuxfs.c
security/selinux/selinuxfs.c
+4
-11
security/selinux/ss/ebitmap.c
security/selinux/ss/ebitmap.c
+20
-6
security/selinux/ss/ebitmap.h
security/selinux/ss/ebitmap.h
+3
-0
security/selinux/ss/policydb.c
security/selinux/ss/policydb.c
+102
-25
security/selinux/ss/policydb.h
security/selinux/ss/policydb.h
+19
-8
security/selinux/ss/services.c
security/selinux/ss/services.c
+108
-0
security/selinux/ss/sidtab.c
security/selinux/ss/sidtab.c
+10
-17
未找到文件。
drivers/infiniband/core/Makefile
浏览文件 @
5965453d
...
@@ -10,7 +10,8 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \
...
@@ -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
\
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
\
device.o fmr_pool.o cache.o netlink.o
\
roce_gid_mgmt.o mr_pool.o addr.o sa_query.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_USER_MEM)
+=
umem.o
ib_core-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING)
+=
umem_odp.o umem_rbtree.o
ib_core-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING)
+=
umem_odp.o umem_rbtree.o
ib_core-$(CONFIG_CGROUP_RDMA)
+=
cgroup.o
ib_core-$(CONFIG_CGROUP_RDMA)
+=
cgroup.o
...
...
drivers/infiniband/core/cache.c
浏览文件 @
5965453d
...
@@ -53,6 +53,7 @@ struct ib_update_work {
...
@@ -53,6 +53,7 @@ struct ib_update_work {
struct
work_struct
work
;
struct
work_struct
work
;
struct
ib_device
*
device
;
struct
ib_device
*
device
;
u8
port_num
;
u8
port_num
;
bool
enforce_security
;
};
};
union
ib_gid
zgid
;
union
ib_gid
zgid
;
...
@@ -911,6 +912,26 @@ int ib_get_cached_pkey(struct ib_device *device,
...
@@ -911,6 +912,26 @@ int ib_get_cached_pkey(struct ib_device *device,
}
}
EXPORT_SYMBOL
(
ib_get_cached_pkey
);
EXPORT_SYMBOL
(
ib_get_cached_pkey
);
int
ib_get_cached_subnet_prefix
(
struct
ib_device
*
device
,
u8
port_num
,
u64
*
sn_pfx
)
{
unsigned
long
flags
;
int
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
(
&
device
->
cache
.
lock
,
flags
);
*
sn_pfx
=
device
->
cache
.
ports
[
p
].
subnet_prefix
;
read_unlock_irqrestore
(
&
device
->
cache
.
lock
,
flags
);
return
0
;
}
EXPORT_SYMBOL
(
ib_get_cached_subnet_prefix
);
int
ib_find_cached_pkey
(
struct
ib_device
*
device
,
int
ib_find_cached_pkey
(
struct
ib_device
*
device
,
u8
port_num
,
u8
port_num
,
u16
pkey
,
u16
pkey
,
...
@@ -1022,7 +1043,8 @@ int ib_get_cached_port_state(struct ib_device *device,
...
@@ -1022,7 +1043,8 @@ int ib_get_cached_port_state(struct ib_device *device,
EXPORT_SYMBOL
(
ib_get_cached_port_state
);
EXPORT_SYMBOL
(
ib_get_cached_port_state
);
static
void
ib_cache_update
(
struct
ib_device
*
device
,
static
void
ib_cache_update
(
struct
ib_device
*
device
,
u8
port
)
u8
port
,
bool
enforce_security
)
{
{
struct
ib_port_attr
*
tprops
=
NULL
;
struct
ib_port_attr
*
tprops
=
NULL
;
struct
ib_pkey_cache
*
pkey_cache
=
NULL
,
*
old_pkey_cache
;
struct
ib_pkey_cache
*
pkey_cache
=
NULL
,
*
old_pkey_cache
;
...
@@ -1108,8 +1130,15 @@ static void ib_cache_update(struct ib_device *device,
...
@@ -1108,8 +1130,15 @@ static void ib_cache_update(struct ib_device *device,
device
->
cache
.
ports
[
port
-
rdma_start_port
(
device
)].
port_state
=
device
->
cache
.
ports
[
port
-
rdma_start_port
(
device
)].
port_state
=
tprops
->
state
;
tprops
->
state
;
device
->
cache
.
ports
[
port
-
rdma_start_port
(
device
)].
subnet_prefix
=
tprops
->
subnet_prefix
;
write_unlock_irq
(
&
device
->
cache
.
lock
);
write_unlock_irq
(
&
device
->
cache
.
lock
);
if
(
enforce_security
)
ib_security_cache_change
(
device
,
port
,
tprops
->
subnet_prefix
);
kfree
(
gid_cache
);
kfree
(
gid_cache
);
kfree
(
old_pkey_cache
);
kfree
(
old_pkey_cache
);
kfree
(
tprops
);
kfree
(
tprops
);
...
@@ -1126,7 +1155,9 @@ static void ib_cache_task(struct work_struct *_work)
...
@@ -1126,7 +1155,9 @@ static void ib_cache_task(struct work_struct *_work)
struct
ib_update_work
*
work
=
struct
ib_update_work
*
work
=
container_of
(
_work
,
struct
ib_update_work
,
work
);
container_of
(
_work
,
struct
ib_update_work
,
work
);
ib_cache_update
(
work
->
device
,
work
->
port_num
);
ib_cache_update
(
work
->
device
,
work
->
port_num
,
work
->
enforce_security
);
kfree
(
work
);
kfree
(
work
);
}
}
...
@@ -1147,6 +1178,12 @@ static void ib_cache_event(struct ib_event_handler *handler,
...
@@ -1147,6 +1178,12 @@ static void ib_cache_event(struct ib_event_handler *handler,
INIT_WORK
(
&
work
->
work
,
ib_cache_task
);
INIT_WORK
(
&
work
->
work
,
ib_cache_task
);
work
->
device
=
event
->
device
;
work
->
device
=
event
->
device
;
work
->
port_num
=
event
->
element
.
port_num
;
work
->
port_num
=
event
->
element
.
port_num
;
if
(
event
->
event
==
IB_EVENT_PKEY_CHANGE
||
event
->
event
==
IB_EVENT_GID_CHANGE
)
work
->
enforce_security
=
true
;
else
work
->
enforce_security
=
false
;
queue_work
(
ib_wq
,
&
work
->
work
);
queue_work
(
ib_wq
,
&
work
->
work
);
}
}
}
}
...
@@ -1172,7 +1209,7 @@ int ib_cache_setup_one(struct ib_device *device)
...
@@ -1172,7 +1209,7 @@ int ib_cache_setup_one(struct ib_device *device)
goto
out
;
goto
out
;
for
(
p
=
0
;
p
<=
rdma_end_port
(
device
)
-
rdma_start_port
(
device
);
++
p
)
for
(
p
=
0
;
p
<=
rdma_end_port
(
device
)
-
rdma_start_port
(
device
);
++
p
)
ib_cache_update
(
device
,
p
+
rdma_start_port
(
device
));
ib_cache_update
(
device
,
p
+
rdma_start_port
(
device
)
,
true
);
INIT_IB_EVENT_HANDLER
(
&
device
->
cache
.
event_handler
,
INIT_IB_EVENT_HANDLER
(
&
device
->
cache
.
event_handler
,
device
,
ib_cache_event
);
device
,
ib_cache_event
);
...
...
drivers/infiniband/core/core_priv.h
浏览文件 @
5965453d
...
@@ -38,6 +38,16 @@
...
@@ -38,6 +38,16 @@
#include <linux/cgroup_rdma.h>
#include <linux/cgroup_rdma.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_mad.h>
#include "mad_priv.h"
struct
pkey_index_qp_list
{
struct
list_head
pkey_index_list
;
u16
pkey_index
;
/* Lock to hold while iterating the qp_list. */
spinlock_t
qp_list_lock
;
struct
list_head
qp_list
;
};
#if IS_ENABLED(CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS)
#if IS_ENABLED(CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS)
int
cma_configfs_init
(
void
);
int
cma_configfs_init
(
void
);
...
@@ -176,4 +186,109 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb,
...
@@ -176,4 +186,109 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb,
int
ib_nl_handle_ip_res_resp
(
struct
sk_buff
*
skb
,
int
ib_nl_handle_ip_res_resp
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
);
struct
netlink_callback
*
cb
);
int
ib_get_cached_subnet_prefix
(
struct
ib_device
*
device
,
u8
port_num
,
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
,
u8
port_num
,
u64
subnet_prefix
);
int
ib_security_modify_qp
(
struct
ib_qp
*
qp
,
struct
ib_qp_attr
*
qp_attr
,
int
qp_attr_mask
,
struct
ib_udata
*
udata
);
int
ib_create_qp_security
(
struct
ib_qp
*
qp
,
struct
ib_device
*
dev
);
void
ib_destroy_qp_security_begin
(
struct
ib_qp_security
*
sec
);
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
)
{
}
static
inline
void
ib_security_cache_change
(
struct
ib_device
*
device
,
u8
port_num
,
u64
subnet_prefix
)
{
}
static
inline
int
ib_security_modify_qp
(
struct
ib_qp
*
qp
,
struct
ib_qp_attr
*
qp_attr
,
int
qp_attr_mask
,
struct
ib_udata
*
udata
)
{
return
qp
->
device
->
modify_qp
(
qp
->
real_qp
,
qp_attr
,
qp_attr_mask
,
udata
);
}
static
inline
int
ib_create_qp_security
(
struct
ib_qp
*
qp
,
struct
ib_device
*
dev
)
{
return
0
;
}
static
inline
void
ib_destroy_qp_security_begin
(
struct
ib_qp_security
*
sec
)
{
}
static
inline
void
ib_destroy_qp_security_abort
(
struct
ib_qp_security
*
sec
)
{
}
static
inline
void
ib_destroy_qp_security_end
(
struct
ib_qp_security
*
sec
)
{
}
static
inline
int
ib_open_shared_qp_security
(
struct
ib_qp
*
qp
,
struct
ib_device
*
dev
)
{
return
0
;
}
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 */
#endif
/* _CORE_PRIV_H */
drivers/infiniband/core/device.c
浏览文件 @
5965453d
...
@@ -39,6 +39,8 @@
...
@@ -39,6 +39,8 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/security.h>
#include <linux/notifier.h>
#include <rdma/rdma_netlink.h>
#include <rdma/rdma_netlink.h>
#include <rdma/ib_addr.h>
#include <rdma/ib_addr.h>
#include <rdma/ib_cache.h>
#include <rdma/ib_cache.h>
...
@@ -82,6 +84,14 @@ static LIST_HEAD(client_list);
...
@@ -82,6 +84,14 @@ static LIST_HEAD(client_list);
static
DEFINE_MUTEX
(
device_mutex
);
static
DEFINE_MUTEX
(
device_mutex
);
static
DECLARE_RWSEM
(
lists_rwsem
);
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
)
static
int
ib_device_check_mandatory
(
struct
ib_device
*
device
)
{
{
...
@@ -325,6 +335,64 @@ void ib_get_device_fw_str(struct ib_device *dev, char *str, size_t str_len)
...
@@ -325,6 +335,64 @@ void ib_get_device_fw_str(struct ib_device *dev, char *str, size_t str_len)
}
}
EXPORT_SYMBOL
(
ib_get_device_fw_str
);
EXPORT_SYMBOL
(
ib_get_device_fw_str
);
static
int
setup_port_pkey_list
(
struct
ib_device
*
device
)
{
int
i
;
/**
* device->port_pkey_list is indexed directly by the port number,
* Therefore it is declared as a 1 based array with potential empty
* slots at the beginning.
*/
device
->
port_pkey_list
=
kcalloc
(
rdma_end_port
(
device
)
+
1
,
sizeof
(
*
device
->
port_pkey_list
),
GFP_KERNEL
);
if
(
!
device
->
port_pkey_list
)
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
(
rdma_end_port
(
device
)
+
1
);
i
++
)
{
spin_lock_init
(
&
device
->
port_pkey_list
[
i
].
list_lock
);
INIT_LIST_HEAD
(
&
device
->
port_pkey_list
[
i
].
pkey_list
);
}
return
0
;
}
static
void
ib_policy_change_task
(
struct
work_struct
*
work
)
{
struct
ib_device
*
dev
;
down_read
(
&
lists_rwsem
);
list_for_each_entry
(
dev
,
&
device_list
,
core_list
)
{
int
i
;
for
(
i
=
rdma_start_port
(
dev
);
i
<=
rdma_end_port
(
dev
);
i
++
)
{
u64
sp
;
int
ret
=
ib_get_cached_subnet_prefix
(
dev
,
i
,
&
sp
);
WARN_ONCE
(
ret
,
"ib_get_cached_subnet_prefix err: %d, this should never happen here
\n
"
,
ret
);
ib_security_cache_change
(
dev
,
i
,
sp
);
}
}
up_read
(
&
lists_rwsem
);
}
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
(
&
ib_policy_change_work
);
return
NOTIFY_OK
;
}
/**
/**
* ib_register_device - Register an IB device with IB core
* ib_register_device - Register an IB device with IB core
* @device:Device to register
* @device:Device to register
...
@@ -385,6 +453,12 @@ int ib_register_device(struct ib_device *device,
...
@@ -385,6 +453,12 @@ int ib_register_device(struct ib_device *device,
goto
out
;
goto
out
;
}
}
ret
=
setup_port_pkey_list
(
device
);
if
(
ret
)
{
pr_warn
(
"Couldn't create per port_pkey_list
\n
"
);
goto
out
;
}
ret
=
ib_cache_setup_one
(
device
);
ret
=
ib_cache_setup_one
(
device
);
if
(
ret
)
{
if
(
ret
)
{
pr_warn
(
"Couldn't set up InfiniBand P_Key/GID cache
\n
"
);
pr_warn
(
"Couldn't set up InfiniBand P_Key/GID cache
\n
"
);
...
@@ -468,6 +542,9 @@ void ib_unregister_device(struct ib_device *device)
...
@@ -468,6 +542,9 @@ void ib_unregister_device(struct ib_device *device)
ib_device_unregister_sysfs
(
device
);
ib_device_unregister_sysfs
(
device
);
ib_cache_cleanup_one
(
device
);
ib_cache_cleanup_one
(
device
);
ib_security_destroy_port_pkey_list
(
device
);
kfree
(
device
->
port_pkey_list
);
down_write
(
&
lists_rwsem
);
down_write
(
&
lists_rwsem
);
spin_lock_irqsave
(
&
device
->
client_data_lock
,
flags
);
spin_lock_irqsave
(
&
device
->
client_data_lock
,
flags
);
list_for_each_entry_safe
(
context
,
tmp
,
&
device
->
client_data_list
,
list
)
list_for_each_entry_safe
(
context
,
tmp
,
&
device
->
client_data_list
,
list
)
...
@@ -1082,10 +1159,18 @@ static int __init ib_core_init(void)
...
@@ -1082,10 +1159,18 @@ static int __init ib_core_init(void)
goto
err_sa
;
goto
err_sa
;
}
}
ret
=
register_lsm_notifier
(
&
ibdev_lsm_nb
);
if
(
ret
)
{
pr_warn
(
"Couldn't register LSM notifier. ret %d
\n
"
,
ret
);
goto
err_ibnl_clients
;
}
ib_cache_setup
();
ib_cache_setup
();
return
0
;
return
0
;
err_ibnl_clients:
ib_remove_ibnl_clients
();
err_sa:
err_sa:
ib_sa_cleanup
();
ib_sa_cleanup
();
err_mad:
err_mad:
...
@@ -1105,6 +1190,7 @@ static int __init ib_core_init(void)
...
@@ -1105,6 +1190,7 @@ static int __init ib_core_init(void)
static
void
__exit
ib_core_cleanup
(
void
)
static
void
__exit
ib_core_cleanup
(
void
)
{
{
unregister_lsm_notifier
(
&
ibdev_lsm_nb
);
ib_cache_cleanup
();
ib_cache_cleanup
();
ib_remove_ibnl_clients
();
ib_remove_ibnl_clients
();
ib_sa_cleanup
();
ib_sa_cleanup
();
...
...
drivers/infiniband/core/mad.c
浏览文件 @
5965453d
...
@@ -40,9 +40,11 @@
...
@@ -40,9 +40,11 @@
#include <linux/dma-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/security.h>
#include <rdma/ib_cache.h>
#include <rdma/ib_cache.h>
#include "mad_priv.h"
#include "mad_priv.h"
#include "core_priv.h"
#include "mad_rmpp.h"
#include "mad_rmpp.h"
#include "smi.h"
#include "smi.h"
#include "opa_smi.h"
#include "opa_smi.h"
...
@@ -369,6 +371,12 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
...
@@ -369,6 +371,12 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
atomic_set
(
&
mad_agent_priv
->
refcount
,
1
);
atomic_set
(
&
mad_agent_priv
->
refcount
,
1
);
init_completion
(
&
mad_agent_priv
->
comp
);
init_completion
(
&
mad_agent_priv
->
comp
);
ret2
=
ib_mad_agent_security_setup
(
&
mad_agent_priv
->
agent
,
qp_type
);
if
(
ret2
)
{
ret
=
ERR_PTR
(
ret2
);
goto
error4
;
}
spin_lock_irqsave
(
&
port_priv
->
reg_lock
,
flags
);
spin_lock_irqsave
(
&
port_priv
->
reg_lock
,
flags
);
mad_agent_priv
->
agent
.
hi_tid
=
++
ib_mad_client_id
;
mad_agent_priv
->
agent
.
hi_tid
=
++
ib_mad_client_id
;
...
@@ -386,7 +394,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
...
@@ -386,7 +394,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
if
(
method
)
{
if
(
method
)
{
if
(
method_in_use
(
&
method
,
if
(
method_in_use
(
&
method
,
mad_reg_req
))
mad_reg_req
))
goto
error
4
;
goto
error
5
;
}
}
}
}
ret2
=
add_nonoui_reg_req
(
mad_reg_req
,
mad_agent_priv
,
ret2
=
add_nonoui_reg_req
(
mad_reg_req
,
mad_agent_priv
,
...
@@ -402,14 +410,14 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
...
@@ -402,14 +410,14 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
if
(
is_vendor_method_in_use
(
if
(
is_vendor_method_in_use
(
vendor_class
,
vendor_class
,
mad_reg_req
))
mad_reg_req
))
goto
error
4
;
goto
error
5
;
}
}
}
}
ret2
=
add_oui_reg_req
(
mad_reg_req
,
mad_agent_priv
);
ret2
=
add_oui_reg_req
(
mad_reg_req
,
mad_agent_priv
);
}
}
if
(
ret2
)
{
if
(
ret2
)
{
ret
=
ERR_PTR
(
ret2
);
ret
=
ERR_PTR
(
ret2
);
goto
error
4
;
goto
error
5
;
}
}
}
}
...
@@ -418,9 +426,10 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
...
@@ -418,9 +426,10 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
spin_unlock_irqrestore
(
&
port_priv
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
port_priv
->
reg_lock
,
flags
);
return
&
mad_agent_priv
->
agent
;
return
&
mad_agent_priv
->
agent
;
error5:
error4:
spin_unlock_irqrestore
(
&
port_priv
->
reg_lock
,
flags
);
spin_unlock_irqrestore
(
&
port_priv
->
reg_lock
,
flags
);
ib_mad_agent_security_cleanup
(
&
mad_agent_priv
->
agent
);
error4:
kfree
(
reg_req
);
kfree
(
reg_req
);
error3:
error3:
kfree
(
mad_agent_priv
);
kfree
(
mad_agent_priv
);
...
@@ -491,6 +500,7 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
...
@@ -491,6 +500,7 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
struct
ib_mad_agent
*
ret
;
struct
ib_mad_agent
*
ret
;
struct
ib_mad_snoop_private
*
mad_snoop_priv
;
struct
ib_mad_snoop_private
*
mad_snoop_priv
;
int
qpn
;
int
qpn
;
int
err
;
/* Validate parameters */
/* Validate parameters */
if
((
is_snooping_sends
(
mad_snoop_flags
)
&&
!
snoop_handler
)
||
if
((
is_snooping_sends
(
mad_snoop_flags
)
&&
!
snoop_handler
)
||
...
@@ -525,17 +535,25 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
...
@@ -525,17 +535,25 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
mad_snoop_priv
->
agent
.
port_num
=
port_num
;
mad_snoop_priv
->
agent
.
port_num
=
port_num
;
mad_snoop_priv
->
mad_snoop_flags
=
mad_snoop_flags
;
mad_snoop_priv
->
mad_snoop_flags
=
mad_snoop_flags
;
init_completion
(
&
mad_snoop_priv
->
comp
);
init_completion
(
&
mad_snoop_priv
->
comp
);
err
=
ib_mad_agent_security_setup
(
&
mad_snoop_priv
->
agent
,
qp_type
);
if
(
err
)
{
ret
=
ERR_PTR
(
err
);
goto
error2
;
}
mad_snoop_priv
->
snoop_index
=
register_snoop_agent
(
mad_snoop_priv
->
snoop_index
=
register_snoop_agent
(
&
port_priv
->
qp_info
[
qpn
],
&
port_priv
->
qp_info
[
qpn
],
mad_snoop_priv
);
mad_snoop_priv
);
if
(
mad_snoop_priv
->
snoop_index
<
0
)
{
if
(
mad_snoop_priv
->
snoop_index
<
0
)
{
ret
=
ERR_PTR
(
mad_snoop_priv
->
snoop_index
);
ret
=
ERR_PTR
(
mad_snoop_priv
->
snoop_index
);
goto
error
2
;
goto
error
3
;
}
}
atomic_set
(
&
mad_snoop_priv
->
refcount
,
1
);
atomic_set
(
&
mad_snoop_priv
->
refcount
,
1
);
return
&
mad_snoop_priv
->
agent
;
return
&
mad_snoop_priv
->
agent
;
error3:
ib_mad_agent_security_cleanup
(
&
mad_snoop_priv
->
agent
);
error2:
error2:
kfree
(
mad_snoop_priv
);
kfree
(
mad_snoop_priv
);
error1:
error1:
...
@@ -581,6 +599,8 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
...
@@ -581,6 +599,8 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
deref_mad_agent
(
mad_agent_priv
);
deref_mad_agent
(
mad_agent_priv
);
wait_for_completion
(
&
mad_agent_priv
->
comp
);
wait_for_completion
(
&
mad_agent_priv
->
comp
);
ib_mad_agent_security_cleanup
(
&
mad_agent_priv
->
agent
);
kfree
(
mad_agent_priv
->
reg_req
);
kfree
(
mad_agent_priv
->
reg_req
);
kfree
(
mad_agent_priv
);
kfree
(
mad_agent_priv
);
}
}
...
@@ -599,6 +619,8 @@ static void unregister_mad_snoop(struct ib_mad_snoop_private *mad_snoop_priv)
...
@@ -599,6 +619,8 @@ static void unregister_mad_snoop(struct ib_mad_snoop_private *mad_snoop_priv)
deref_snoop_agent
(
mad_snoop_priv
);
deref_snoop_agent
(
mad_snoop_priv
);
wait_for_completion
(
&
mad_snoop_priv
->
comp
);
wait_for_completion
(
&
mad_snoop_priv
->
comp
);
ib_mad_agent_security_cleanup
(
&
mad_snoop_priv
->
agent
);
kfree
(
mad_snoop_priv
);
kfree
(
mad_snoop_priv
);
}
}
...
@@ -1215,12 +1237,16 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
...
@@ -1215,12 +1237,16 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
/* Walk list of send WRs and post each on send list */
/* Walk list of send WRs and post each on send list */
for
(;
send_buf
;
send_buf
=
next_send_buf
)
{
for
(;
send_buf
;
send_buf
=
next_send_buf
)
{
mad_send_wr
=
container_of
(
send_buf
,
mad_send_wr
=
container_of
(
send_buf
,
struct
ib_mad_send_wr_private
,
struct
ib_mad_send_wr_private
,
send_buf
);
send_buf
);
mad_agent_priv
=
mad_send_wr
->
mad_agent_priv
;
mad_agent_priv
=
mad_send_wr
->
mad_agent_priv
;
ret
=
ib_mad_enforce_security
(
mad_agent_priv
,
mad_send_wr
->
send_wr
.
pkey_index
);
if
(
ret
)
goto
error
;
if
(
!
send_buf
->
mad_agent
->
send_handler
||
if
(
!
send_buf
->
mad_agent
->
send_handler
||
(
send_buf
->
timeout_ms
&&
(
send_buf
->
timeout_ms
&&
!
send_buf
->
mad_agent
->
recv_handler
))
{
!
send_buf
->
mad_agent
->
recv_handler
))
{
...
@@ -1946,6 +1972,14 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
...
@@ -1946,6 +1972,14 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
struct
ib_mad_send_wr_private
*
mad_send_wr
;
struct
ib_mad_send_wr_private
*
mad_send_wr
;
struct
ib_mad_send_wc
mad_send_wc
;
struct
ib_mad_send_wc
mad_send_wc
;
unsigned
long
flags
;
unsigned
long
flags
;
int
ret
;
ret
=
ib_mad_enforce_security
(
mad_agent_priv
,
mad_recv_wc
->
wc
->
pkey_index
);
if
(
ret
)
{
ib_free_recv_mad
(
mad_recv_wc
);
deref_mad_agent
(
mad_agent_priv
);
}
INIT_LIST_HEAD
(
&
mad_recv_wc
->
rmpp_list
);
INIT_LIST_HEAD
(
&
mad_recv_wc
->
rmpp_list
);
list_add
(
&
mad_recv_wc
->
recv_buf
.
list
,
&
mad_recv_wc
->
rmpp_list
);
list_add
(
&
mad_recv_wc
->
recv_buf
.
list
,
&
mad_recv_wc
->
rmpp_list
);
...
@@ -2003,6 +2037,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
...
@@ -2003,6 +2037,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
mad_recv_wc
);
mad_recv_wc
);
deref_mad_agent
(
mad_agent_priv
);
deref_mad_agent
(
mad_agent_priv
);
}
}
return
;
}
}
static
enum
smi_action
handle_ib_smi
(
const
struct
ib_mad_port_private
*
port_priv
,
static
enum
smi_action
handle_ib_smi
(
const
struct
ib_mad_port_private
*
port_priv
,
...
...
drivers/infiniband/core/security.c
0 → 100644
浏览文件 @
5965453d
/*
* Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifdef CONFIG_SECURITY_INFINIBAND
#include <linux/security.h>
#include <linux/completion.h>
#include <linux/list.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
#include "core_priv.h"
#include "mad_priv.h"
static
struct
pkey_index_qp_list
*
get_pkey_idx_qp_list
(
struct
ib_port_pkey
*
pp
)
{
struct
pkey_index_qp_list
*
pkey
=
NULL
;
struct
pkey_index_qp_list
*
tmp_pkey
;
struct
ib_device
*
dev
=
pp
->
sec
->
dev
;
spin_lock
(
&
dev
->
port_pkey_list
[
pp
->
port_num
].
list_lock
);
list_for_each_entry
(
tmp_pkey
,
&
dev
->
port_pkey_list
[
pp
->
port_num
].
pkey_list
,
pkey_index_list
)
{
if
(
tmp_pkey
->
pkey_index
==
pp
->
pkey_index
)
{
pkey
=
tmp_pkey
;
break
;
}
}
spin_unlock
(
&
dev
->
port_pkey_list
[
pp
->
port_num
].
list_lock
);
return
pkey
;
}
static
int
get_pkey_and_subnet_prefix
(
struct
ib_port_pkey
*
pp
,
u16
*
pkey
,
u64
*
subnet_prefix
)
{
struct
ib_device
*
dev
=
pp
->
sec
->
dev
;
int
ret
;
ret
=
ib_get_cached_pkey
(
dev
,
pp
->
port_num
,
pp
->
pkey_index
,
pkey
);
if
(
ret
)
return
ret
;
ret
=
ib_get_cached_subnet_prefix
(
dev
,
pp
->
port_num
,
subnet_prefix
);
return
ret
;
}
static
int
enforce_qp_pkey_security
(
u16
pkey
,
u64
subnet_prefix
,
struct
ib_qp_security
*
qp_sec
)
{
struct
ib_qp_security
*
shared_qp_sec
;
int
ret
;
ret
=
security_ib_pkey_access
(
qp_sec
->
security
,
subnet_prefix
,
pkey
);
if
(
ret
)
return
ret
;
if
(
qp_sec
->
qp
==
qp_sec
->
qp
->
real_qp
)
{
list_for_each_entry
(
shared_qp_sec
,
&
qp_sec
->
shared_qp_list
,
shared_qp_list
)
{
ret
=
security_ib_pkey_access
(
shared_qp_sec
->
security
,
subnet_prefix
,
pkey
);
if
(
ret
)
return
ret
;
}
}
return
0
;
}
/* The caller of this function must hold the QP security
* mutex of the QP of the security structure in *pps.
*
* It takes separate ports_pkeys and security structure
* because in some cases the pps will be for a new settings
* or the pps will be for the real QP and security structure
* will be for a shared QP.
*/
static
int
check_qp_port_pkey_settings
(
struct
ib_ports_pkeys
*
pps
,
struct
ib_qp_security
*
sec
)
{
u64
subnet_prefix
;
u16
pkey
;
int
ret
=
0
;
if
(
!
pps
)
return
0
;
if
(
pps
->
main
.
state
!=
IB_PORT_PKEY_NOT_VALID
)
{
get_pkey_and_subnet_prefix
(
&
pps
->
main
,
&
pkey
,
&
subnet_prefix
);
ret
=
enforce_qp_pkey_security
(
pkey
,
subnet_prefix
,
sec
);
}
if
(
ret
)
return
ret
;
if
(
pps
->
alt
.
state
!=
IB_PORT_PKEY_NOT_VALID
)
{
get_pkey_and_subnet_prefix
(
&
pps
->
alt
,
&
pkey
,
&
subnet_prefix
);
ret
=
enforce_qp_pkey_security
(
pkey
,
subnet_prefix
,
sec
);
}
return
ret
;
}
/* The caller of this function must hold the QP security
* mutex.
*/
static
void
qp_to_error
(
struct
ib_qp_security
*
sec
)
{
struct
ib_qp_security
*
shared_qp_sec
;
struct
ib_qp_attr
attr
=
{
.
qp_state
=
IB_QPS_ERR
};
struct
ib_event
event
=
{
.
event
=
IB_EVENT_QP_FATAL
};
/* If the QP is in the process of being destroyed
* the qp pointer in the security structure is
* undefined. It cannot be modified now.
*/
if
(
sec
->
destroying
)
return
;
ib_modify_qp
(
sec
->
qp
,
&
attr
,
IB_QP_STATE
);
if
(
sec
->
qp
->
event_handler
&&
sec
->
qp
->
qp_context
)
{
event
.
element
.
qp
=
sec
->
qp
;
sec
->
qp
->
event_handler
(
&
event
,
sec
->
qp
->
qp_context
);
}
list_for_each_entry
(
shared_qp_sec
,
&
sec
->
shared_qp_list
,
shared_qp_list
)
{
struct
ib_qp
*
qp
=
shared_qp_sec
->
qp
;
if
(
qp
->
event_handler
&&
qp
->
qp_context
)
{
event
.
element
.
qp
=
qp
;
event
.
device
=
qp
->
device
;
qp
->
event_handler
(
&
event
,
qp
->
qp_context
);
}
}
}
static
inline
void
check_pkey_qps
(
struct
pkey_index_qp_list
*
pkey
,
struct
ib_device
*
device
,
u8
port_num
,
u64
subnet_prefix
)
{
struct
ib_port_pkey
*
pp
,
*
tmp_pp
;
bool
comp
;
LIST_HEAD
(
to_error_list
);
u16
pkey_val
;
if
(
!
ib_get_cached_pkey
(
device
,
port_num
,
pkey
->
pkey_index
,
&
pkey_val
))
{
spin_lock
(
&
pkey
->
qp_list_lock
);
list_for_each_entry
(
pp
,
&
pkey
->
qp_list
,
qp_list
)
{
if
(
atomic_read
(
&
pp
->
sec
->
error_list_count
))
continue
;
if
(
enforce_qp_pkey_security
(
pkey_val
,
subnet_prefix
,
pp
->
sec
))
{
atomic_inc
(
&
pp
->
sec
->
error_list_count
);
list_add
(
&
pp
->
to_error_list
,
&
to_error_list
);
}
}
spin_unlock
(
&
pkey
->
qp_list_lock
);
}
list_for_each_entry_safe
(
pp
,
tmp_pp
,
&
to_error_list
,
to_error_list
)
{
mutex_lock
(
&
pp
->
sec
->
mutex
);
qp_to_error
(
pp
->
sec
);
list_del
(
&
pp
->
to_error_list
);
atomic_dec
(
&
pp
->
sec
->
error_list_count
);
comp
=
pp
->
sec
->
destroying
;
mutex_unlock
(
&
pp
->
sec
->
mutex
);
if
(
comp
)
complete
(
&
pp
->
sec
->
error_complete
);
}
}
/* The caller of this function must hold the QP security
* mutex.
*/
static
int
port_pkey_list_insert
(
struct
ib_port_pkey
*
pp
)
{
struct
pkey_index_qp_list
*
tmp_pkey
;
struct
pkey_index_qp_list
*
pkey
;
struct
ib_device
*
dev
;
u8
port_num
=
pp
->
port_num
;
int
ret
=
0
;
if
(
pp
->
state
!=
IB_PORT_PKEY_VALID
)
return
0
;
dev
=
pp
->
sec
->
dev
;
pkey
=
get_pkey_idx_qp_list
(
pp
);
if
(
!
pkey
)
{
bool
found
=
false
;
pkey
=
kzalloc
(
sizeof
(
*
pkey
),
GFP_KERNEL
);
if
(
!
pkey
)
return
-
ENOMEM
;
spin_lock
(
&
dev
->
port_pkey_list
[
port_num
].
list_lock
);
/* Check for the PKey again. A racing process may
* have created it.
*/
list_for_each_entry
(
tmp_pkey
,
&
dev
->
port_pkey_list
[
port_num
].
pkey_list
,
pkey_index_list
)
{
if
(
tmp_pkey
->
pkey_index
==
pp
->
pkey_index
)
{
kfree
(
pkey
);
pkey
=
tmp_pkey
;
found
=
true
;
break
;
}
}
if
(
!
found
)
{
pkey
->
pkey_index
=
pp
->
pkey_index
;
spin_lock_init
(
&
pkey
->
qp_list_lock
);
INIT_LIST_HEAD
(
&
pkey
->
qp_list
);
list_add
(
&
pkey
->
pkey_index_list
,
&
dev
->
port_pkey_list
[
port_num
].
pkey_list
);
}
spin_unlock
(
&
dev
->
port_pkey_list
[
port_num
].
list_lock
);
}
spin_lock
(
&
pkey
->
qp_list_lock
);
list_add
(
&
pp
->
qp_list
,
&
pkey
->
qp_list
);
spin_unlock
(
&
pkey
->
qp_list_lock
);
pp
->
state
=
IB_PORT_PKEY_LISTED
;
return
ret
;
}
/* The caller of this function must hold the QP security
* mutex.
*/
static
void
port_pkey_list_remove
(
struct
ib_port_pkey
*
pp
)
{
struct
pkey_index_qp_list
*
pkey
;
if
(
pp
->
state
!=
IB_PORT_PKEY_LISTED
)
return
;
pkey
=
get_pkey_idx_qp_list
(
pp
);
spin_lock
(
&
pkey
->
qp_list_lock
);
list_del
(
&
pp
->
qp_list
);
spin_unlock
(
&
pkey
->
qp_list_lock
);
/* The setting may still be valid, i.e. after
* a destroy has failed for example.
*/
pp
->
state
=
IB_PORT_PKEY_VALID
;
}
static
void
destroy_qp_security
(
struct
ib_qp_security
*
sec
)
{
security_ib_free_security
(
sec
->
security
);
kfree
(
sec
->
ports_pkeys
);
kfree
(
sec
);
}
/* The caller of this function must hold the QP security
* mutex.
*/
static
struct
ib_ports_pkeys
*
get_new_pps
(
const
struct
ib_qp
*
qp
,
const
struct
ib_qp_attr
*
qp_attr
,
int
qp_attr_mask
)
{
struct
ib_ports_pkeys
*
new_pps
;
struct
ib_ports_pkeys
*
qp_pps
=
qp
->
qp_sec
->
ports_pkeys
;
new_pps
=
kzalloc
(
sizeof
(
*
new_pps
),
GFP_KERNEL
);
if
(
!
new_pps
)
return
NULL
;
if
(
qp_attr_mask
&
(
IB_QP_PKEY_INDEX
|
IB_QP_PORT
))
{
if
(
!
qp_pps
)
{
new_pps
->
main
.
port_num
=
qp_attr
->
port_num
;
new_pps
->
main
.
pkey_index
=
qp_attr
->
pkey_index
;
}
else
{
new_pps
->
main
.
port_num
=
(
qp_attr_mask
&
IB_QP_PORT
)
?
qp_attr
->
port_num
:
qp_pps
->
main
.
port_num
;
new_pps
->
main
.
pkey_index
=
(
qp_attr_mask
&
IB_QP_PKEY_INDEX
)
?
qp_attr
->
pkey_index
:
qp_pps
->
main
.
pkey_index
;
}
new_pps
->
main
.
state
=
IB_PORT_PKEY_VALID
;
}
else
if
(
qp_pps
)
{
new_pps
->
main
.
port_num
=
qp_pps
->
main
.
port_num
;
new_pps
->
main
.
pkey_index
=
qp_pps
->
main
.
pkey_index
;
if
(
qp_pps
->
main
.
state
!=
IB_PORT_PKEY_NOT_VALID
)
new_pps
->
main
.
state
=
IB_PORT_PKEY_VALID
;
}
if
(
qp_attr_mask
&
IB_QP_ALT_PATH
)
{
new_pps
->
alt
.
port_num
=
qp_attr
->
alt_port_num
;
new_pps
->
alt
.
pkey_index
=
qp_attr
->
alt_pkey_index
;
new_pps
->
alt
.
state
=
IB_PORT_PKEY_VALID
;
}
else
if
(
qp_pps
)
{
new_pps
->
alt
.
port_num
=
qp_pps
->
alt
.
port_num
;
new_pps
->
alt
.
pkey_index
=
qp_pps
->
alt
.
pkey_index
;
if
(
qp_pps
->
alt
.
state
!=
IB_PORT_PKEY_NOT_VALID
)
new_pps
->
alt
.
state
=
IB_PORT_PKEY_VALID
;
}
new_pps
->
main
.
sec
=
qp
->
qp_sec
;
new_pps
->
alt
.
sec
=
qp
->
qp_sec
;
return
new_pps
;
}
int
ib_open_shared_qp_security
(
struct
ib_qp
*
qp
,
struct
ib_device
*
dev
)
{
struct
ib_qp
*
real_qp
=
qp
->
real_qp
;
int
ret
;
ret
=
ib_create_qp_security
(
qp
,
dev
);
if
(
ret
)
return
ret
;
mutex_lock
(
&
real_qp
->
qp_sec
->
mutex
);
ret
=
check_qp_port_pkey_settings
(
real_qp
->
qp_sec
->
ports_pkeys
,
qp
->
qp_sec
);
if
(
ret
)
goto
ret
;
if
(
qp
!=
real_qp
)
list_add
(
&
qp
->
qp_sec
->
shared_qp_list
,
&
real_qp
->
qp_sec
->
shared_qp_list
);
ret:
mutex_unlock
(
&
real_qp
->
qp_sec
->
mutex
);
if
(
ret
)
destroy_qp_security
(
qp
->
qp_sec
);
return
ret
;
}
void
ib_close_shared_qp_security
(
struct
ib_qp_security
*
sec
)
{
struct
ib_qp
*
real_qp
=
sec
->
qp
->
real_qp
;
mutex_lock
(
&
real_qp
->
qp_sec
->
mutex
);
list_del
(
&
sec
->
shared_qp_list
);
mutex_unlock
(
&
real_qp
->
qp_sec
->
mutex
);
destroy_qp_security
(
sec
);
}
int
ib_create_qp_security
(
struct
ib_qp
*
qp
,
struct
ib_device
*
dev
)
{
int
ret
;
qp
->
qp_sec
=
kzalloc
(
sizeof
(
*
qp
->
qp_sec
),
GFP_KERNEL
);
if
(
!
qp
->
qp_sec
)
return
-
ENOMEM
;
qp
->
qp_sec
->
qp
=
qp
;
qp
->
qp_sec
->
dev
=
dev
;
mutex_init
(
&
qp
->
qp_sec
->
mutex
);
INIT_LIST_HEAD
(
&
qp
->
qp_sec
->
shared_qp_list
);
atomic_set
(
&
qp
->
qp_sec
->
error_list_count
,
0
);
init_completion
(
&
qp
->
qp_sec
->
error_complete
);
ret
=
security_ib_alloc_security
(
&
qp
->
qp_sec
->
security
);
if
(
ret
)
kfree
(
qp
->
qp_sec
);
return
ret
;
}
EXPORT_SYMBOL
(
ib_create_qp_security
);
void
ib_destroy_qp_security_begin
(
struct
ib_qp_security
*
sec
)
{
mutex_lock
(
&
sec
->
mutex
);
/* Remove the QP from the lists so it won't get added to
* a to_error_list during the destroy process.
*/
if
(
sec
->
ports_pkeys
)
{
port_pkey_list_remove
(
&
sec
->
ports_pkeys
->
main
);
port_pkey_list_remove
(
&
sec
->
ports_pkeys
->
alt
);
}
/* If the QP is already in one or more of those lists
* the destroying flag will ensure the to error flow
* doesn't operate on an undefined QP.
*/
sec
->
destroying
=
true
;
/* Record the error list count to know how many completions
* to wait for.
*/
sec
->
error_comps_pending
=
atomic_read
(
&
sec
->
error_list_count
);
mutex_unlock
(
&
sec
->
mutex
);
}
void
ib_destroy_qp_security_abort
(
struct
ib_qp_security
*
sec
)
{
int
ret
;
int
i
;
/* If a concurrent cache update is in progress this
* QP security could be marked for an error state
* transition. Wait for this to complete.
*/
for
(
i
=
0
;
i
<
sec
->
error_comps_pending
;
i
++
)
wait_for_completion
(
&
sec
->
error_complete
);
mutex_lock
(
&
sec
->
mutex
);
sec
->
destroying
=
false
;
/* Restore the position in the lists and verify
* access is still allowed in case a cache update
* occurred while attempting to destroy.
*
* Because these setting were listed already
* and removed during ib_destroy_qp_security_begin
* we know the pkey_index_qp_list for the PKey
* already exists so port_pkey_list_insert won't fail.
*/
if
(
sec
->
ports_pkeys
)
{
port_pkey_list_insert
(
&
sec
->
ports_pkeys
->
main
);
port_pkey_list_insert
(
&
sec
->
ports_pkeys
->
alt
);
}
ret
=
check_qp_port_pkey_settings
(
sec
->
ports_pkeys
,
sec
);
if
(
ret
)
qp_to_error
(
sec
);
mutex_unlock
(
&
sec
->
mutex
);
}
void
ib_destroy_qp_security_end
(
struct
ib_qp_security
*
sec
)
{
int
i
;
/* If a concurrent cache update is occurring we must
* wait until this QP security structure is processed
* in the QP to error flow before destroying it because
* the to_error_list is in use.
*/
for
(
i
=
0
;
i
<
sec
->
error_comps_pending
;
i
++
)
wait_for_completion
(
&
sec
->
error_complete
);
destroy_qp_security
(
sec
);
}
void
ib_security_cache_change
(
struct
ib_device
*
device
,
u8
port_num
,
u64
subnet_prefix
)
{
struct
pkey_index_qp_list
*
pkey
;
list_for_each_entry
(
pkey
,
&
device
->
port_pkey_list
[
port_num
].
pkey_list
,
pkey_index_list
)
{
check_pkey_qps
(
pkey
,
device
,
port_num
,
subnet_prefix
);
}
}
void
ib_security_destroy_port_pkey_list
(
struct
ib_device
*
device
)
{
struct
pkey_index_qp_list
*
pkey
,
*
tmp_pkey
;
int
i
;
for
(
i
=
rdma_start_port
(
device
);
i
<=
rdma_end_port
(
device
);
i
++
)
{
spin_lock
(
&
device
->
port_pkey_list
[
i
].
list_lock
);
list_for_each_entry_safe
(
pkey
,
tmp_pkey
,
&
device
->
port_pkey_list
[
i
].
pkey_list
,
pkey_index_list
)
{
list_del
(
&
pkey
->
pkey_index_list
);
kfree
(
pkey
);
}
spin_unlock
(
&
device
->
port_pkey_list
[
i
].
list_lock
);
}
}
int
ib_security_modify_qp
(
struct
ib_qp
*
qp
,
struct
ib_qp_attr
*
qp_attr
,
int
qp_attr_mask
,
struct
ib_udata
*
udata
)
{
int
ret
=
0
;
struct
ib_ports_pkeys
*
tmp_pps
;
struct
ib_ports_pkeys
*
new_pps
;
bool
special_qp
=
(
qp
->
qp_type
==
IB_QPT_SMI
||
qp
->
qp_type
==
IB_QPT_GSI
||
qp
->
qp_type
>=
IB_QPT_RESERVED1
);
bool
pps_change
=
((
qp_attr_mask
&
(
IB_QP_PKEY_INDEX
|
IB_QP_PORT
))
||
(
qp_attr_mask
&
IB_QP_ALT_PATH
));
if
(
pps_change
&&
!
special_qp
)
{
mutex_lock
(
&
qp
->
qp_sec
->
mutex
);
new_pps
=
get_new_pps
(
qp
,
qp_attr
,
qp_attr_mask
);
/* Add this QP to the lists for the new port
* and pkey settings before checking for permission
* in case there is a concurrent cache update
* occurring. Walking the list for a cache change
* doesn't acquire the security mutex unless it's
* sending the QP to error.
*/
ret
=
port_pkey_list_insert
(
&
new_pps
->
main
);
if
(
!
ret
)
ret
=
port_pkey_list_insert
(
&
new_pps
->
alt
);
if
(
!
ret
)
ret
=
check_qp_port_pkey_settings
(
new_pps
,
qp
->
qp_sec
);
}
if
(
!
ret
)
ret
=
qp
->
device
->
modify_qp
(
qp
->
real_qp
,
qp_attr
,
qp_attr_mask
,
udata
);
if
(
pps_change
&&
!
special_qp
)
{
/* Clean up the lists and free the appropriate
* ports_pkeys structure.
*/
if
(
ret
)
{
tmp_pps
=
new_pps
;
}
else
{
tmp_pps
=
qp
->
qp_sec
->
ports_pkeys
;
qp
->
qp_sec
->
ports_pkeys
=
new_pps
;
}
if
(
tmp_pps
)
{
port_pkey_list_remove
(
&
tmp_pps
->
main
);
port_pkey_list_remove
(
&
tmp_pps
->
alt
);
}
kfree
(
tmp_pps
);
mutex_unlock
(
&
qp
->
qp_sec
->
mutex
);
}
return
ret
;
}
EXPORT_SYMBOL
(
ib_security_modify_qp
);
int
ib_security_pkey_access
(
struct
ib_device
*
dev
,
u8
port_num
,
u16
pkey_index
,
void
*
sec
)
{
u64
subnet_prefix
;
u16
pkey
;
int
ret
;
ret
=
ib_get_cached_pkey
(
dev
,
port_num
,
pkey_index
,
&
pkey
);
if
(
ret
)
return
ret
;
ret
=
ib_get_cached_subnet_prefix
(
dev
,
port_num
,
&
subnet_prefix
);
if
(
ret
)
return
ret
;
return
security_ib_pkey_access
(
sec
,
subnet_prefix
,
pkey
);
}
EXPORT_SYMBOL
(
ib_security_pkey_access
);
static
int
ib_mad_agent_security_change
(
struct
notifier_block
*
nb
,
unsigned
long
event
,
void
*
data
)
{
struct
ib_mad_agent
*
ag
=
container_of
(
nb
,
struct
ib_mad_agent
,
lsm_nb
);
if
(
event
!=
LSM_POLICY_CHANGE
)
return
NOTIFY_DONE
;
ag
->
smp_allowed
=
!
security_ib_endport_manage_subnet
(
ag
->
security
,
ag
->
device
->
name
,
ag
->
port_num
);
return
NOTIFY_OK
;
}
int
ib_mad_agent_security_setup
(
struct
ib_mad_agent
*
agent
,
enum
ib_qp_type
qp_type
)
{
int
ret
;
ret
=
security_ib_alloc_security
(
&
agent
->
security
);
if
(
ret
)
return
ret
;
if
(
qp_type
!=
IB_QPT_SMI
)
return
0
;
ret
=
security_ib_endport_manage_subnet
(
agent
->
security
,
agent
->
device
->
name
,
agent
->
port_num
);
if
(
ret
)
return
ret
;
agent
->
lsm_nb
.
notifier_call
=
ib_mad_agent_security_change
;
ret
=
register_lsm_notifier
(
&
agent
->
lsm_nb
);
if
(
ret
)
return
ret
;
agent
->
smp_allowed
=
true
;
agent
->
lsm_nb_reg
=
true
;
return
0
;
}
void
ib_mad_agent_security_cleanup
(
struct
ib_mad_agent
*
agent
)
{
security_ib_free_security
(
agent
->
security
);
if
(
agent
->
lsm_nb_reg
)
unregister_lsm_notifier
(
&
agent
->
lsm_nb
);
}
int
ib_mad_enforce_security
(
struct
ib_mad_agent_private
*
map
,
u16
pkey_index
)
{
int
ret
;
if
(
map
->
agent
.
qp
->
qp_type
==
IB_QPT_SMI
&&
!
map
->
agent
.
smp_allowed
)
return
-
EACCES
;
ret
=
ib_security_pkey_access
(
map
->
agent
.
device
,
map
->
agent
.
port_num
,
pkey_index
,
map
->
agent
.
security
);
if
(
ret
)
return
ret
;
return
0
;
}
#endif
/* CONFIG_SECURITY_INFINIBAND */
drivers/infiniband/core/uverbs_cmd.c
浏览文件 @
5965453d
...
@@ -1508,6 +1508,10 @@ static int create_qp(struct ib_uverbs_file *file,
...
@@ -1508,6 +1508,10 @@ static int create_qp(struct ib_uverbs_file *file,
}
}
if
(
cmd
->
qp_type
!=
IB_QPT_XRC_TGT
)
{
if
(
cmd
->
qp_type
!=
IB_QPT_XRC_TGT
)
{
ret
=
ib_create_qp_security
(
qp
,
device
);
if
(
ret
)
goto
err_cb
;
qp
->
real_qp
=
qp
;
qp
->
real_qp
=
qp
;
qp
->
device
=
device
;
qp
->
device
=
device
;
qp
->
pd
=
pd
;
qp
->
pd
=
pd
;
...
@@ -2002,14 +2006,17 @@ static int modify_qp(struct ib_uverbs_file *file,
...
@@ -2002,14 +2006,17 @@ static int modify_qp(struct ib_uverbs_file *file,
if
(
ret
)
if
(
ret
)
goto
release_qp
;
goto
release_qp
;
}
}
ret
=
qp
->
device
->
modify_qp
(
qp
,
attr
,
ret
=
ib_security_modify_qp
(
qp
,
attr
,
modify_qp_mask
(
qp
->
qp_type
,
modify_qp_mask
(
qp
->
qp_type
,
cmd
->
base
.
attr_mask
),
cmd
->
base
.
attr_mask
),
udata
);
udata
);
}
else
{
}
else
{
ret
=
ib_modify_qp
(
qp
,
attr
,
ret
=
ib_security_modify_qp
(
qp
,
modify_qp_mask
(
qp
->
qp_type
,
attr
,
cmd
->
base
.
attr_mask
));
modify_qp_mask
(
qp
->
qp_type
,
cmd
->
base
.
attr_mask
),
NULL
);
}
}
release_qp:
release_qp:
...
...
drivers/infiniband/core/verbs.c
浏览文件 @
5965453d
...
@@ -44,6 +44,7 @@
...
@@ -44,6 +44,7 @@
#include <linux/in.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/in6.h>
#include <net/addrconf.h>
#include <net/addrconf.h>
#include <linux/security.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
#include <rdma/ib_cache.h>
...
@@ -713,11 +714,19 @@ static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
...
@@ -713,11 +714,19 @@ static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
{
{
struct
ib_qp
*
qp
;
struct
ib_qp
*
qp
;
unsigned
long
flags
;
unsigned
long
flags
;
int
err
;
qp
=
kzalloc
(
sizeof
*
qp
,
GFP_KERNEL
);
qp
=
kzalloc
(
sizeof
*
qp
,
GFP_KERNEL
);
if
(
!
qp
)
if
(
!
qp
)
return
ERR_PTR
(
-
ENOMEM
);
return
ERR_PTR
(
-
ENOMEM
);
qp
->
real_qp
=
real_qp
;
err
=
ib_open_shared_qp_security
(
qp
,
real_qp
->
device
);
if
(
err
)
{
kfree
(
qp
);
return
ERR_PTR
(
err
);
}
qp
->
real_qp
=
real_qp
;
qp
->
real_qp
=
real_qp
;
atomic_inc
(
&
real_qp
->
usecnt
);
atomic_inc
(
&
real_qp
->
usecnt
);
qp
->
device
=
real_qp
->
device
;
qp
->
device
=
real_qp
->
device
;
...
@@ -804,6 +813,12 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
...
@@ -804,6 +813,12 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
if
(
IS_ERR
(
qp
))
if
(
IS_ERR
(
qp
))
return
qp
;
return
qp
;
ret
=
ib_create_qp_security
(
qp
,
device
);
if
(
ret
)
{
ib_destroy_qp
(
qp
);
return
ERR_PTR
(
ret
);
}
qp
->
device
=
device
;
qp
->
device
=
device
;
qp
->
real_qp
=
qp
;
qp
->
real_qp
=
qp
;
qp
->
uobject
=
NULL
;
qp
->
uobject
=
NULL
;
...
@@ -1266,7 +1281,7 @@ int ib_modify_qp(struct ib_qp *qp,
...
@@ -1266,7 +1281,7 @@ int ib_modify_qp(struct ib_qp *qp,
return
ret
;
return
ret
;
}
}
return
qp
->
device
->
modify_qp
(
qp
->
real_qp
,
qp_attr
,
qp_attr_mask
,
NULL
);
return
ib_security_
modify_qp
(
qp
->
real_qp
,
qp_attr
,
qp_attr_mask
,
NULL
);
}
}
EXPORT_SYMBOL
(
ib_modify_qp
);
EXPORT_SYMBOL
(
ib_modify_qp
);
...
@@ -1295,6 +1310,7 @@ int ib_close_qp(struct ib_qp *qp)
...
@@ -1295,6 +1310,7 @@ int ib_close_qp(struct ib_qp *qp)
spin_unlock_irqrestore
(
&
real_qp
->
device
->
event_handler_lock
,
flags
);
spin_unlock_irqrestore
(
&
real_qp
->
device
->
event_handler_lock
,
flags
);
atomic_dec
(
&
real_qp
->
usecnt
);
atomic_dec
(
&
real_qp
->
usecnt
);
ib_close_shared_qp_security
(
qp
->
qp_sec
);
kfree
(
qp
);
kfree
(
qp
);
return
0
;
return
0
;
...
@@ -1335,6 +1351,7 @@ int ib_destroy_qp(struct ib_qp *qp)
...
@@ -1335,6 +1351,7 @@ int ib_destroy_qp(struct ib_qp *qp)
struct
ib_cq
*
scq
,
*
rcq
;
struct
ib_cq
*
scq
,
*
rcq
;
struct
ib_srq
*
srq
;
struct
ib_srq
*
srq
;
struct
ib_rwq_ind_table
*
ind_tbl
;
struct
ib_rwq_ind_table
*
ind_tbl
;
struct
ib_qp_security
*
sec
;
int
ret
;
int
ret
;
WARN_ON_ONCE
(
qp
->
mrs_used
>
0
);
WARN_ON_ONCE
(
qp
->
mrs_used
>
0
);
...
@@ -1350,6 +1367,9 @@ int ib_destroy_qp(struct ib_qp *qp)
...
@@ -1350,6 +1367,9 @@ int ib_destroy_qp(struct ib_qp *qp)
rcq
=
qp
->
recv_cq
;
rcq
=
qp
->
recv_cq
;
srq
=
qp
->
srq
;
srq
=
qp
->
srq
;
ind_tbl
=
qp
->
rwq_ind_tbl
;
ind_tbl
=
qp
->
rwq_ind_tbl
;
sec
=
qp
->
qp_sec
;
if
(
sec
)
ib_destroy_qp_security_begin
(
sec
);
if
(
!
qp
->
uobject
)
if
(
!
qp
->
uobject
)
rdma_rw_cleanup_mrs
(
qp
);
rdma_rw_cleanup_mrs
(
qp
);
...
@@ -1366,6 +1386,11 @@ int ib_destroy_qp(struct ib_qp *qp)
...
@@ -1366,6 +1386,11 @@ int ib_destroy_qp(struct ib_qp *qp)
atomic_dec
(
&
srq
->
usecnt
);
atomic_dec
(
&
srq
->
usecnt
);
if
(
ind_tbl
)
if
(
ind_tbl
)
atomic_dec
(
&
ind_tbl
->
usecnt
);
atomic_dec
(
&
ind_tbl
->
usecnt
);
if
(
sec
)
ib_destroy_qp_security_end
(
sec
);
}
else
{
if
(
sec
)
ib_destroy_qp_security_abort
(
sec
);
}
}
return
ret
;
return
ret
;
...
...
fs/nfs/super.c
浏览文件 @
5965453d
...
@@ -2544,10 +2544,25 @@ EXPORT_SYMBOL_GPL(nfs_set_sb_security);
...
@@ -2544,10 +2544,25 @@ EXPORT_SYMBOL_GPL(nfs_set_sb_security);
int
nfs_clone_sb_security
(
struct
super_block
*
s
,
struct
dentry
*
mntroot
,
int
nfs_clone_sb_security
(
struct
super_block
*
s
,
struct
dentry
*
mntroot
,
struct
nfs_mount_info
*
mount_info
)
struct
nfs_mount_info
*
mount_info
)
{
{
int
error
;
unsigned
long
kflags
=
0
,
kflags_out
=
0
;
/* clone any lsm security options from the parent to the new sb */
/* clone any lsm security options from the parent to the new sb */
if
(
d_inode
(
mntroot
)
->
i_op
!=
NFS_SB
(
s
)
->
nfs_client
->
rpc_ops
->
dir_inode_ops
)
if
(
d_inode
(
mntroot
)
->
i_op
!=
NFS_SB
(
s
)
->
nfs_client
->
rpc_ops
->
dir_inode_ops
)
return
-
ESTALE
;
return
-
ESTALE
;
return
security_sb_clone_mnt_opts
(
mount_info
->
cloned
->
sb
,
s
);
if
(
NFS_SB
(
s
)
->
caps
&
NFS_CAP_SECURITY_LABEL
)
kflags
|=
SECURITY_LSM_NATIVE_LABELS
;
error
=
security_sb_clone_mnt_opts
(
mount_info
->
cloned
->
sb
,
s
,
kflags
,
&
kflags_out
);
if
(
error
)
return
error
;
if
(
NFS_SB
(
s
)
->
caps
&
NFS_CAP_SECURITY_LABEL
&&
!
(
kflags_out
&
SECURITY_LSM_NATIVE_LABELS
))
NFS_SB
(
s
)
->
caps
&=
~
NFS_CAP_SECURITY_LABEL
;
return
0
;
}
}
EXPORT_SYMBOL_GPL
(
nfs_clone_sb_security
);
EXPORT_SYMBOL_GPL
(
nfs_clone_sb_security
);
...
...
include/linux/lsm_audit.h
浏览文件 @
5965453d
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#include <linux/path.h>
#include <linux/path.h>
#include <linux/key.h>
#include <linux/key.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <rdma/ib_verbs.h>
struct
lsm_network_audit
{
struct
lsm_network_audit
{
int
netif
;
int
netif
;
...
@@ -45,6 +46,16 @@ struct lsm_ioctlop_audit {
...
@@ -45,6 +46,16 @@ struct lsm_ioctlop_audit {
u16
cmd
;
u16
cmd
;
};
};
struct
lsm_ibpkey_audit
{
u64
subnet_prefix
;
u16
pkey
;
};
struct
lsm_ibendport_audit
{
char
dev_name
[
IB_DEVICE_NAME_MAX
];
u8
port
;
};
/* Auxiliary data to use in generating the audit record. */
/* Auxiliary data to use in generating the audit record. */
struct
common_audit_data
{
struct
common_audit_data
{
char
type
;
char
type
;
...
@@ -60,6 +71,8 @@ struct common_audit_data {
...
@@ -60,6 +71,8 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_DENTRY 10
#define LSM_AUDIT_DATA_DENTRY 10
#define LSM_AUDIT_DATA_IOCTL_OP 11
#define LSM_AUDIT_DATA_IOCTL_OP 11
#define LSM_AUDIT_DATA_FILE 12
#define LSM_AUDIT_DATA_FILE 12
#define LSM_AUDIT_DATA_IBPKEY 13
#define LSM_AUDIT_DATA_IBENDPORT 14
union
{
union
{
struct
path
path
;
struct
path
path
;
struct
dentry
*
dentry
;
struct
dentry
*
dentry
;
...
@@ -77,6 +90,8 @@ struct common_audit_data {
...
@@ -77,6 +90,8 @@ struct common_audit_data {
char
*
kmod_name
;
char
*
kmod_name
;
struct
lsm_ioctlop_audit
*
op
;
struct
lsm_ioctlop_audit
*
op
;
struct
file
*
file
;
struct
file
*
file
;
struct
lsm_ibpkey_audit
*
ibpkey
;
struct
lsm_ibendport_audit
*
ibendport
;
}
u
;
}
u
;
/* this union contains LSM specific data */
/* this union contains LSM specific data */
union
{
union
{
...
...
include/linux/lsm_hooks.h
浏览文件 @
5965453d
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
* Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
* Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
* Copyright (C) 2015 Intel Corporation.
* Copyright (C) 2015 Intel Corporation.
* Copyright (C) 2015 Casey Schaufler <casey@schaufler-ca.com>
* Copyright (C) 2015 Casey Schaufler <casey@schaufler-ca.com>
* Copyright (C) 2016 Mellanox Techonologies
*
*
* This program is free software; you can redistribute it and/or modify
* 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
* it under the terms of the GNU General Public License as published by
...
@@ -911,6 +912,26 @@
...
@@ -911,6 +912,26 @@
* associated with the TUN device's security structure.
* associated with the TUN device's security structure.
* @security pointer to the TUN devices's security structure.
* @security pointer to the TUN devices's security structure.
*
*
* Security hooks for Infiniband
*
* @ib_pkey_access:
* Check permission to access a pkey when modifing a QP.
* @subnet_prefix the subnet prefix of the port being used.
* @pkey the pkey to be accessed.
* @sec pointer to a security structure.
* @ib_endport_manage_subnet:
* Check permissions to send and receive SMPs on a end port.
* @dev_name the IB device name (i.e. mlx4_0).
* @port_num the port number.
* @sec pointer to a security structure.
* @ib_alloc_security:
* Allocate a security structure for Infiniband objects.
* @sec pointer to a security structure pointer.
* Returns 0 on success, non-zero on failure
* @ib_free_security:
* Deallocate an Infiniband security structure.
* @sec contains the security structure to be freed.
*
* Security hooks for XFRM operations.
* Security hooks for XFRM operations.
*
*
* @xfrm_policy_alloc_security:
* @xfrm_policy_alloc_security:
...
@@ -1388,7 +1409,9 @@ union security_list_options {
...
@@ -1388,7 +1409,9 @@ union security_list_options {
unsigned
long
kern_flags
,
unsigned
long
kern_flags
,
unsigned
long
*
set_kern_flags
);
unsigned
long
*
set_kern_flags
);
int
(
*
sb_clone_mnt_opts
)(
const
struct
super_block
*
oldsb
,
int
(
*
sb_clone_mnt_opts
)(
const
struct
super_block
*
oldsb
,
struct
super_block
*
newsb
);
struct
super_block
*
newsb
,
unsigned
long
kern_flags
,
unsigned
long
*
set_kern_flags
);
int
(
*
sb_parse_opts_str
)(
char
*
options
,
struct
security_mnt_opts
*
opts
);
int
(
*
sb_parse_opts_str
)(
char
*
options
,
struct
security_mnt_opts
*
opts
);
int
(
*
dentry_init_security
)(
struct
dentry
*
dentry
,
int
mode
,
int
(
*
dentry_init_security
)(
struct
dentry
*
dentry
,
int
mode
,
const
struct
qstr
*
name
,
void
**
ctx
,
const
struct
qstr
*
name
,
void
**
ctx
,
...
@@ -1620,6 +1643,14 @@ union security_list_options {
...
@@ -1620,6 +1643,14 @@ union security_list_options {
int
(
*
tun_dev_open
)(
void
*
security
);
int
(
*
tun_dev_open
)(
void
*
security
);
#endif
/* CONFIG_SECURITY_NETWORK */
#endif
/* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
int
(
*
ib_pkey_access
)(
void
*
sec
,
u64
subnet_prefix
,
u16
pkey
);
int
(
*
ib_endport_manage_subnet
)(
void
*
sec
,
const
char
*
dev_name
,
u8
port_num
);
int
(
*
ib_alloc_security
)(
void
**
sec
);
void
(
*
ib_free_security
)(
void
*
sec
);
#endif
/* CONFIG_SECURITY_INFINIBAND */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM
int
(
*
xfrm_policy_alloc_security
)(
struct
xfrm_sec_ctx
**
ctxp
,
int
(
*
xfrm_policy_alloc_security
)(
struct
xfrm_sec_ctx
**
ctxp
,
struct
xfrm_user_sec_ctx
*
sec_ctx
,
struct
xfrm_user_sec_ctx
*
sec_ctx
,
...
@@ -1851,6 +1882,12 @@ struct security_hook_heads {
...
@@ -1851,6 +1882,12 @@ struct security_hook_heads {
struct
list_head
tun_dev_attach
;
struct
list_head
tun_dev_attach
;
struct
list_head
tun_dev_open
;
struct
list_head
tun_dev_open
;
#endif
/* CONFIG_SECURITY_NETWORK */
#endif
/* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
struct
list_head
ib_pkey_access
;
struct
list_head
ib_endport_manage_subnet
;
struct
list_head
ib_alloc_security
;
struct
list_head
ib_free_security
;
#endif
/* CONFIG_SECURITY_INFINIBAND */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM
struct
list_head
xfrm_policy_alloc_security
;
struct
list_head
xfrm_policy_alloc_security
;
struct
list_head
xfrm_policy_clone_security
;
struct
list_head
xfrm_policy_clone_security
;
...
...
include/linux/security.h
浏览文件 @
5965453d
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
* Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
* Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
* Copyright (C) 2001 James Morris <jmorris@intercode.com.au>
* Copyright (C) 2001 James Morris <jmorris@intercode.com.au>
* Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
* Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
* Copyright (C) 2016 Mellanox Techonologies
*
*
* This program is free software; you can redistribute it and/or modify
* 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
* it under the terms of the GNU General Public License as published by
...
@@ -68,6 +69,10 @@ struct audit_krule;
...
@@ -68,6 +69,10 @@ struct audit_krule;
struct
user_namespace
;
struct
user_namespace
;
struct
timezone
;
struct
timezone
;
enum
lsm_event
{
LSM_POLICY_CHANGE
,
};
/* These functions are in security/commoncap.c */
/* These functions are in security/commoncap.c */
extern
int
cap_capable
(
const
struct
cred
*
cred
,
struct
user_namespace
*
ns
,
extern
int
cap_capable
(
const
struct
cred
*
cred
,
struct
user_namespace
*
ns
,
int
cap
,
int
audit
);
int
cap
,
int
audit
);
...
@@ -163,6 +168,10 @@ struct security_mnt_opts {
...
@@ -163,6 +168,10 @@ struct security_mnt_opts {
int
num_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
)
static
inline
void
security_init_mnt_opts
(
struct
security_mnt_opts
*
opts
)
{
{
opts
->
mnt_opts
=
NULL
;
opts
->
mnt_opts
=
NULL
;
...
@@ -240,7 +249,9 @@ int security_sb_set_mnt_opts(struct super_block *sb,
...
@@ -240,7 +249,9 @@ int security_sb_set_mnt_opts(struct super_block *sb,
unsigned
long
kern_flags
,
unsigned
long
kern_flags
,
unsigned
long
*
set_kern_flags
);
unsigned
long
*
set_kern_flags
);
int
security_sb_clone_mnt_opts
(
const
struct
super_block
*
oldsb
,
int
security_sb_clone_mnt_opts
(
const
struct
super_block
*
oldsb
,
struct
super_block
*
newsb
);
struct
super_block
*
newsb
,
unsigned
long
kern_flags
,
unsigned
long
*
set_kern_flags
);
int
security_sb_parse_opts_str
(
char
*
options
,
struct
security_mnt_opts
*
opts
);
int
security_sb_parse_opts_str
(
char
*
options
,
struct
security_mnt_opts
*
opts
);
int
security_dentry_init_security
(
struct
dentry
*
dentry
,
int
mode
,
int
security_dentry_init_security
(
struct
dentry
*
dentry
,
int
mode
,
const
struct
qstr
*
name
,
void
**
ctx
,
const
struct
qstr
*
name
,
void
**
ctx
,
...
@@ -381,6 +392,21 @@ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
...
@@ -381,6 +392,21 @@ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
struct
security_mnt_opts
{
struct
security_mnt_opts
{
};
};
static
inline
int
call_lsm_notifier
(
enum
lsm_event
event
,
void
*
data
)
{
return
0
;
}
static
inline
int
register_lsm_notifier
(
struct
notifier_block
*
nb
)
{
return
0
;
}
static
inline
int
unregister_lsm_notifier
(
struct
notifier_block
*
nb
)
{
return
0
;
}
static
inline
void
security_init_mnt_opts
(
struct
security_mnt_opts
*
opts
)
static
inline
void
security_init_mnt_opts
(
struct
security_mnt_opts
*
opts
)
{
{
}
}
...
@@ -581,7 +607,9 @@ static inline int security_sb_set_mnt_opts(struct super_block *sb,
...
@@ -581,7 +607,9 @@ static inline int security_sb_set_mnt_opts(struct super_block *sb,
}
}
static
inline
int
security_sb_clone_mnt_opts
(
const
struct
super_block
*
oldsb
,
static
inline
int
security_sb_clone_mnt_opts
(
const
struct
super_block
*
oldsb
,
struct
super_block
*
newsb
)
struct
super_block
*
newsb
,
unsigned
long
kern_flags
,
unsigned
long
*
set_kern_flags
)
{
{
return
0
;
return
0
;
}
}
...
@@ -1406,6 +1434,32 @@ static inline int security_tun_dev_open(void *security)
...
@@ -1406,6 +1434,32 @@ static inline int security_tun_dev_open(void *security)
}
}
#endif
/* CONFIG_SECURITY_NETWORK */
#endif
/* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
int
security_ib_pkey_access
(
void
*
sec
,
u64
subnet_prefix
,
u16
pkey
);
int
security_ib_endport_manage_subnet
(
void
*
sec
,
const
char
*
name
,
u8
port_num
);
int
security_ib_alloc_security
(
void
**
sec
);
void
security_ib_free_security
(
void
*
sec
);
#else
/* CONFIG_SECURITY_INFINIBAND */
static
inline
int
security_ib_pkey_access
(
void
*
sec
,
u64
subnet_prefix
,
u16
pkey
)
{
return
0
;
}
static
inline
int
security_ib_endport_manage_subnet
(
void
*
sec
,
const
char
*
dev_name
,
u8
port_num
)
{
return
0
;
}
static
inline
int
security_ib_alloc_security
(
void
**
sec
)
{
return
0
;
}
static
inline
void
security_ib_free_security
(
void
*
sec
)
{
}
#endif
/* CONFIG_SECURITY_INFINIBAND */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM
int
security_xfrm_policy_alloc
(
struct
xfrm_sec_ctx
**
ctxp
,
int
security_xfrm_policy_alloc
(
struct
xfrm_sec_ctx
**
ctxp
,
...
...
include/rdma/ib_mad.h
浏览文件 @
5965453d
...
@@ -575,6 +575,10 @@ struct ib_mad_agent {
...
@@ -575,6 +575,10 @@ struct ib_mad_agent {
u32
flags
;
u32
flags
;
u8
port_num
;
u8
port_num
;
u8
rmpp_version
;
u8
rmpp_version
;
void
*
security
;
bool
smp_allowed
;
bool
lsm_nb_reg
;
struct
notifier_block
lsm_nb
;
};
};
/**
/**
...
...
include/rdma/ib_verbs.h
浏览文件 @
5965453d
...
@@ -1614,6 +1614,45 @@ struct ib_rwq_ind_table_init_attr {
...
@@ -1614,6 +1614,45 @@ struct ib_rwq_ind_table_init_attr {
struct
ib_wq
**
ind_tbl
;
struct
ib_wq
**
ind_tbl
;
};
};
enum
port_pkey_state
{
IB_PORT_PKEY_NOT_VALID
=
0
,
IB_PORT_PKEY_VALID
=
1
,
IB_PORT_PKEY_LISTED
=
2
,
};
struct
ib_qp_security
;
struct
ib_port_pkey
{
enum
port_pkey_state
state
;
u16
pkey_index
;
u8
port_num
;
struct
list_head
qp_list
;
struct
list_head
to_error_list
;
struct
ib_qp_security
*
sec
;
};
struct
ib_ports_pkeys
{
struct
ib_port_pkey
main
;
struct
ib_port_pkey
alt
;
};
struct
ib_qp_security
{
struct
ib_qp
*
qp
;
struct
ib_device
*
dev
;
/* Hold this mutex when changing port and pkey settings. */
struct
mutex
mutex
;
struct
ib_ports_pkeys
*
ports_pkeys
;
/* A list of all open shared QP handles. Required to enforce security
* properly for all users of a shared QP.
*/
struct
list_head
shared_qp_list
;
void
*
security
;
bool
destroying
;
atomic_t
error_list_count
;
struct
completion
error_complete
;
int
error_comps_pending
;
};
/*
/*
* @max_write_sge: Maximum SGE elements per RDMA WRITE request.
* @max_write_sge: Maximum SGE elements per RDMA WRITE request.
* @max_read_sge: Maximum SGE elements per RDMA READ request.
* @max_read_sge: Maximum SGE elements per RDMA READ request.
...
@@ -1643,6 +1682,7 @@ struct ib_qp {
...
@@ -1643,6 +1682,7 @@ struct ib_qp {
u32
max_read_sge
;
u32
max_read_sge
;
enum
ib_qp_type
qp_type
;
enum
ib_qp_type
qp_type
;
struct
ib_rwq_ind_table
*
rwq_ind_tbl
;
struct
ib_rwq_ind_table
*
rwq_ind_tbl
;
struct
ib_qp_security
*
qp_sec
;
};
};
struct
ib_mr
{
struct
ib_mr
{
...
@@ -1891,6 +1931,7 @@ enum ib_mad_result {
...
@@ -1891,6 +1931,7 @@ enum ib_mad_result {
};
};
struct
ib_port_cache
{
struct
ib_port_cache
{
u64
subnet_prefix
;
struct
ib_pkey_cache
*
pkey
;
struct
ib_pkey_cache
*
pkey
;
struct
ib_gid_table
*
gid
;
struct
ib_gid_table
*
gid
;
u8
lmc
;
u8
lmc
;
...
@@ -1940,6 +1981,12 @@ struct rdma_netdev {
...
@@ -1940,6 +1981,12 @@ struct rdma_netdev {
union
ib_gid
*
gid
,
u16
mlid
);
union
ib_gid
*
gid
,
u16
mlid
);
};
};
struct
ib_port_pkey_list
{
/* Lock to hold while modifying the list. */
spinlock_t
list_lock
;
struct
list_head
pkey_list
;
};
struct
ib_device
{
struct
ib_device
{
/* Do not access @dma_device directly from ULP nor from HW drivers. */
/* Do not access @dma_device directly from ULP nor from HW drivers. */
struct
device
*
dma_device
;
struct
device
*
dma_device
;
...
@@ -1963,6 +2010,8 @@ struct ib_device {
...
@@ -1963,6 +2010,8 @@ struct ib_device {
int
num_comp_vectors
;
int
num_comp_vectors
;
struct
ib_port_pkey_list
*
port_pkey_list
;
struct
iw_cm_verbs
*
iwcm
;
struct
iw_cm_verbs
*
iwcm
;
/**
/**
...
...
security/Kconfig
浏览文件 @
5965453d
...
@@ -54,6 +54,15 @@ config SECURITY_NETWORK
...
@@ -54,6 +54,15 @@ config SECURITY_NETWORK
implement
socket
and
networking
access
controls
.
implement
socket
and
networking
access
controls
.
If
you
are
unsure
how
to
answer
this
question
,
answer
N
.
If
you
are
unsure
how
to
answer
this
question
,
answer
N
.
config
SECURITY_INFINIBAND
bool
"Infiniband Security Hooks"
depends
on
SECURITY
&&
INFINIBAND
help
This
enables
the
Infiniband
security
hooks
.
If
enabled
,
a
security
module
can
use
these
hooks
to
implement
Infiniband
access
controls
.
If
you
are
unsure
how
to
answer
this
question
,
answer
N
.
config
SECURITY_NETWORK_XFRM
config
SECURITY_NETWORK_XFRM
bool
"XFRM (IPSec) Networking Security Hooks"
bool
"XFRM (IPSec) Networking Security Hooks"
depends
on
XFRM
&&
SECURITY_NETWORK
depends
on
XFRM
&&
SECURITY_NETWORK
...
...
security/lsm_audit.c
浏览文件 @
5965453d
...
@@ -410,6 +410,22 @@ static void dump_common_audit_data(struct audit_buffer *ab,
...
@@ -410,6 +410,22 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_format
(
ab
,
" kmod="
);
audit_log_format
(
ab
,
" kmod="
);
audit_log_untrustedstring
(
ab
,
a
->
u
.
kmod_name
);
audit_log_untrustedstring
(
ab
,
a
->
u
.
kmod_name
);
break
;
break
;
case
LSM_AUDIT_DATA_IBPKEY
:
{
struct
in6_addr
sbn_pfx
;
memset
(
&
sbn_pfx
.
s6_addr
,
0
,
sizeof
(
sbn_pfx
.
s6_addr
));
memcpy
(
&
sbn_pfx
.
s6_addr
,
&
a
->
u
.
ibpkey
->
subnet_prefix
,
sizeof
(
a
->
u
.
ibpkey
->
subnet_prefix
));
audit_log_format
(
ab
,
" pkey=0x%x subnet_prefix=%pI6c"
,
a
->
u
.
ibpkey
->
pkey
,
&
sbn_pfx
);
break
;
}
case
LSM_AUDIT_DATA_IBENDPORT
:
audit_log_format
(
ab
,
" device=%s port_num=%u"
,
a
->
u
.
ibendport
->
dev_name
,
a
->
u
.
ibendport
->
port
);
break
;
}
/* switch (a->type) */
}
/* switch (a->type) */
}
}
...
...
security/security.c
浏览文件 @
5965453d
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
* Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
* Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
* Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
* Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
* Copyright (C) 2016 Mellanox Technologies
*
*
* This program is free software; you can redistribute it and/or modify
* 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
* it under the terms of the GNU General Public License as published by
...
@@ -34,6 +35,8 @@
...
@@ -34,6 +35,8 @@
#define SECURITY_NAME_MAX 10
#define SECURITY_NAME_MAX 10
struct
security_hook_heads
security_hook_heads
__lsm_ro_after_init
;
struct
security_hook_heads
security_hook_heads
__lsm_ro_after_init
;
static
ATOMIC_NOTIFIER_HEAD
(
lsm_notifier_chain
);
char
*
lsm_names
;
char
*
lsm_names
;
/* Boot-time LSM user choice */
/* Boot-time LSM user choice */
static
__initdata
char
chosen_lsm
[
SECURITY_NAME_MAX
+
1
]
=
static
__initdata
char
chosen_lsm
[
SECURITY_NAME_MAX
+
1
]
=
...
@@ -165,6 +168,24 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
...
@@ -165,6 +168,24 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
panic
(
"%s - Cannot get early memory.
\n
"
,
__func__
);
panic
(
"%s - Cannot get early memory.
\n
"
,
__func__
);
}
}
int
call_lsm_notifier
(
enum
lsm_event
event
,
void
*
data
)
{
return
atomic_notifier_call_chain
(
&
lsm_notifier_chain
,
event
,
data
);
}
EXPORT_SYMBOL
(
call_lsm_notifier
);
int
register_lsm_notifier
(
struct
notifier_block
*
nb
)
{
return
atomic_notifier_chain_register
(
&
lsm_notifier_chain
,
nb
);
}
EXPORT_SYMBOL
(
register_lsm_notifier
);
int
unregister_lsm_notifier
(
struct
notifier_block
*
nb
)
{
return
atomic_notifier_chain_unregister
(
&
lsm_notifier_chain
,
nb
);
}
EXPORT_SYMBOL
(
unregister_lsm_notifier
);
/*
/*
* Hook list operation macros.
* Hook list operation macros.
*
*
...
@@ -399,9 +420,12 @@ int security_sb_set_mnt_opts(struct super_block *sb,
...
@@ -399,9 +420,12 @@ int security_sb_set_mnt_opts(struct super_block *sb,
EXPORT_SYMBOL
(
security_sb_set_mnt_opts
);
EXPORT_SYMBOL
(
security_sb_set_mnt_opts
);
int
security_sb_clone_mnt_opts
(
const
struct
super_block
*
oldsb
,
int
security_sb_clone_mnt_opts
(
const
struct
super_block
*
oldsb
,
struct
super_block
*
newsb
)
struct
super_block
*
newsb
,
unsigned
long
kern_flags
,
unsigned
long
*
set_kern_flags
)
{
{
return
call_int_hook
(
sb_clone_mnt_opts
,
0
,
oldsb
,
newsb
);
return
call_int_hook
(
sb_clone_mnt_opts
,
0
,
oldsb
,
newsb
,
kern_flags
,
set_kern_flags
);
}
}
EXPORT_SYMBOL
(
security_sb_clone_mnt_opts
);
EXPORT_SYMBOL
(
security_sb_clone_mnt_opts
);
...
@@ -1515,6 +1539,33 @@ EXPORT_SYMBOL(security_tun_dev_open);
...
@@ -1515,6 +1539,33 @@ EXPORT_SYMBOL(security_tun_dev_open);
#endif
/* CONFIG_SECURITY_NETWORK */
#endif
/* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
int
security_ib_pkey_access
(
void
*
sec
,
u64
subnet_prefix
,
u16
pkey
)
{
return
call_int_hook
(
ib_pkey_access
,
0
,
sec
,
subnet_prefix
,
pkey
);
}
EXPORT_SYMBOL
(
security_ib_pkey_access
);
int
security_ib_endport_manage_subnet
(
void
*
sec
,
const
char
*
dev_name
,
u8
port_num
)
{
return
call_int_hook
(
ib_endport_manage_subnet
,
0
,
sec
,
dev_name
,
port_num
);
}
EXPORT_SYMBOL
(
security_ib_endport_manage_subnet
);
int
security_ib_alloc_security
(
void
**
sec
)
{
return
call_int_hook
(
ib_alloc_security
,
0
,
sec
);
}
EXPORT_SYMBOL
(
security_ib_alloc_security
);
void
security_ib_free_security
(
void
*
sec
)
{
call_void_hook
(
ib_free_security
,
sec
);
}
EXPORT_SYMBOL
(
security_ib_free_security
);
#endif
/* CONFIG_SECURITY_INFINIBAND */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM
int
security_xfrm_policy_alloc
(
struct
xfrm_sec_ctx
**
ctxp
,
int
security_xfrm_policy_alloc
(
struct
xfrm_sec_ctx
**
ctxp
,
...
...
security/selinux/Makefile
浏览文件 @
5965453d
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
obj-$(CONFIG_SECURITY_SELINUX)
:=
selinux.o
obj-$(CONFIG_SECURITY_SELINUX)
:=
selinux.o
selinux-y
:=
avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.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/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
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o
...
...
security/selinux/hooks.c
浏览文件 @
5965453d
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
* Paul Moore <paul@paul-moore.com>
* Paul Moore <paul@paul-moore.com>
* Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
* Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
* Yuichi Nakamura <ynakam@hitachisoft.jp>
* Yuichi Nakamura <ynakam@hitachisoft.jp>
* Copyright (C) 2016 Mellanox Technologies
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* it under the terms of the GNU General Public License version 2,
...
@@ -90,6 +91,7 @@
...
@@ -90,6 +91,7 @@
#include "netif.h"
#include "netif.h"
#include "netnode.h"
#include "netnode.h"
#include "netport.h"
#include "netport.h"
#include "ibpkey.h"
#include "xfrm.h"
#include "xfrm.h"
#include "netlabel.h"
#include "netlabel.h"
#include "audit.h"
#include "audit.h"
...
@@ -171,6 +173,16 @@ static int selinux_netcache_avc_callback(u32 event)
...
@@ -171,6 +173,16 @@ static int selinux_netcache_avc_callback(u32 event)
return
0
;
return
0
;
}
}
static
int
selinux_lsm_notifier_avc_callback
(
u32
event
)
{
if
(
event
==
AVC_CALLBACK_RESET
)
{
sel_ib_pkey_flush
();
call_lsm_notifier
(
LSM_POLICY_CHANGE
,
NULL
);
}
return
0
;
}
/*
/*
* initialise the security for the init task
* initialise the security for the init task
*/
*/
...
@@ -398,18 +410,6 @@ static void superblock_free_security(struct super_block *sb)
...
@@ -398,18 +410,6 @@ static void superblock_free_security(struct super_block *sb)
kfree
(
sbsec
);
kfree
(
sbsec
);
}
}
/* The file system's label must be initialized prior to use. */
static
const
char
*
labeling_behaviors
[
7
]
=
{
"uses xattr"
,
"uses transition SIDs"
,
"uses task SIDs"
,
"uses genfs_contexts"
,
"not configured for labeling"
,
"uses mountpoint labeling"
,
"uses native labeling"
,
};
static
inline
int
inode_doinit
(
struct
inode
*
inode
)
static
inline
int
inode_doinit
(
struct
inode
*
inode
)
{
{
return
inode_doinit_with_dentry
(
inode
,
NULL
);
return
inode_doinit_with_dentry
(
inode
,
NULL
);
...
@@ -524,13 +524,17 @@ static int sb_finish_set_opts(struct super_block *sb)
...
@@ -524,13 +524,17 @@ static int sb_finish_set_opts(struct super_block *sb)
}
}
}
}
if
(
sbsec
->
behavior
>
ARRAY_SIZE
(
labeling_behaviors
))
printk
(
KERN_ERR
"SELinux: initialized (dev %s, type %s), unknown behavior
\n
"
,
sb
->
s_id
,
sb
->
s_type
->
name
);
sbsec
->
flags
|=
SE_SBINITIALIZED
;
sbsec
->
flags
|=
SE_SBINITIALIZED
;
/*
* Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
* leave the flag untouched because sb_clone_mnt_opts might be handing
* us a superblock that needs the flag to be cleared.
*/
if
(
selinux_is_sblabel_mnt
(
sb
))
if
(
selinux_is_sblabel_mnt
(
sb
))
sbsec
->
flags
|=
SBLABEL_MNT
;
sbsec
->
flags
|=
SBLABEL_MNT
;
else
sbsec
->
flags
&=
~
SBLABEL_MNT
;
/* Initialize the root inode. */
/* Initialize the root inode. */
rc
=
inode_doinit_with_dentry
(
root_inode
,
root
);
rc
=
inode_doinit_with_dentry
(
root_inode
,
root
);
...
@@ -809,6 +813,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
...
@@ -809,6 +813,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
sbsec
->
flags
|=
SE_SBPROC
|
SE_SBGENFS
;
sbsec
->
flags
|=
SE_SBPROC
|
SE_SBGENFS
;
if
(
!
strcmp
(
sb
->
s_type
->
name
,
"debugfs"
)
||
if
(
!
strcmp
(
sb
->
s_type
->
name
,
"debugfs"
)
||
!
strcmp
(
sb
->
s_type
->
name
,
"tracefs"
)
||
!
strcmp
(
sb
->
s_type
->
name
,
"sysfs"
)
||
!
strcmp
(
sb
->
s_type
->
name
,
"sysfs"
)
||
!
strcmp
(
sb
->
s_type
->
name
,
"pstore"
))
!
strcmp
(
sb
->
s_type
->
name
,
"pstore"
))
sbsec
->
flags
|=
SE_SBGENFS
;
sbsec
->
flags
|=
SE_SBGENFS
;
...
@@ -963,8 +968,11 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb,
...
@@ -963,8 +968,11 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb,
}
}
static
int
selinux_sb_clone_mnt_opts
(
const
struct
super_block
*
oldsb
,
static
int
selinux_sb_clone_mnt_opts
(
const
struct
super_block
*
oldsb
,
struct
super_block
*
newsb
)
struct
super_block
*
newsb
,
unsigned
long
kern_flags
,
unsigned
long
*
set_kern_flags
)
{
{
int
rc
=
0
;
const
struct
superblock_security_struct
*
oldsbsec
=
oldsb
->
s_security
;
const
struct
superblock_security_struct
*
oldsbsec
=
oldsb
->
s_security
;
struct
superblock_security_struct
*
newsbsec
=
newsb
->
s_security
;
struct
superblock_security_struct
*
newsbsec
=
newsb
->
s_security
;
...
@@ -979,6 +987,13 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
...
@@ -979,6 +987,13 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
if
(
!
ss_initialized
)
if
(
!
ss_initialized
)
return
0
;
return
0
;
/*
* Specifying internal flags without providing a place to
* place the results is not allowed.
*/
if
(
kern_flags
&&
!
set_kern_flags
)
return
-
EINVAL
;
/* how can we clone if the old one wasn't set up?? */
/* how can we clone if the old one wasn't set up?? */
BUG_ON
(
!
(
oldsbsec
->
flags
&
SE_SBINITIALIZED
));
BUG_ON
(
!
(
oldsbsec
->
flags
&
SE_SBINITIALIZED
));
...
@@ -994,6 +1009,18 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
...
@@ -994,6 +1009,18 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
newsbsec
->
def_sid
=
oldsbsec
->
def_sid
;
newsbsec
->
def_sid
=
oldsbsec
->
def_sid
;
newsbsec
->
behavior
=
oldsbsec
->
behavior
;
newsbsec
->
behavior
=
oldsbsec
->
behavior
;
if
(
newsbsec
->
behavior
==
SECURITY_FS_USE_NATIVE
&&
!
(
kern_flags
&
SECURITY_LSM_NATIVE_LABELS
)
&&
!
set_context
)
{
rc
=
security_fs_use
(
newsb
);
if
(
rc
)
goto
out
;
}
if
(
kern_flags
&
SECURITY_LSM_NATIVE_LABELS
&&
!
set_context
)
{
newsbsec
->
behavior
=
SECURITY_FS_USE_NATIVE
;
*
set_kern_flags
|=
SECURITY_LSM_NATIVE_LABELS
;
}
if
(
set_context
)
{
if
(
set_context
)
{
u32
sid
=
oldsbsec
->
mntpoint_sid
;
u32
sid
=
oldsbsec
->
mntpoint_sid
;
...
@@ -1013,8 +1040,9 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
...
@@ -1013,8 +1040,9 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
}
}
sb_finish_set_opts
(
newsb
);
sb_finish_set_opts
(
newsb
);
out:
mutex_unlock
(
&
newsbsec
->
lock
);
mutex_unlock
(
&
newsbsec
->
lock
);
return
0
;
return
rc
;
}
}
static
int
selinux_parse_opts_str
(
char
*
options
,
static
int
selinux_parse_opts_str
(
char
*
options
,
...
@@ -2063,8 +2091,9 @@ static inline u32 file_to_av(struct file *file)
...
@@ -2063,8 +2091,9 @@ static inline u32 file_to_av(struct file *file)
static
inline
u32
open_file_to_av
(
struct
file
*
file
)
static
inline
u32
open_file_to_av
(
struct
file
*
file
)
{
{
u32
av
=
file_to_av
(
file
);
u32
av
=
file_to_av
(
file
);
struct
inode
*
inode
=
file_inode
(
file
);
if
(
selinux_policycap_openperm
)
if
(
selinux_policycap_openperm
&&
inode
->
i_sb
->
s_magic
!=
SOCKFS_MAGIC
)
av
|=
FILE__OPEN
;
av
|=
FILE__OPEN
;
return
av
;
return
av
;
...
@@ -3059,6 +3088,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
...
@@ -3059,6 +3088,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
static
int
selinux_inode_setattr
(
struct
dentry
*
dentry
,
struct
iattr
*
iattr
)
static
int
selinux_inode_setattr
(
struct
dentry
*
dentry
,
struct
iattr
*
iattr
)
{
{
const
struct
cred
*
cred
=
current_cred
();
const
struct
cred
*
cred
=
current_cred
();
struct
inode
*
inode
=
d_backing_inode
(
dentry
);
unsigned
int
ia_valid
=
iattr
->
ia_valid
;
unsigned
int
ia_valid
=
iattr
->
ia_valid
;
__u32
av
=
FILE__WRITE
;
__u32
av
=
FILE__WRITE
;
...
@@ -3074,8 +3104,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
...
@@ -3074,8 +3104,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
ATTR_ATIME_SET
|
ATTR_MTIME_SET
|
ATTR_TIMES_SET
))
ATTR_ATIME_SET
|
ATTR_MTIME_SET
|
ATTR_TIMES_SET
))
return
dentry_has_perm
(
cred
,
dentry
,
FILE__SETATTR
);
return
dentry_has_perm
(
cred
,
dentry
,
FILE__SETATTR
);
if
(
selinux_policycap_openperm
&&
(
ia_valid
&
ATTR_SIZE
)
if
(
selinux_policycap_openperm
&&
&&
!
(
ia_valid
&
ATTR_FILE
))
inode
->
i_sb
->
s_magic
!=
SOCKFS_MAGIC
&&
(
ia_valid
&
ATTR_SIZE
)
&&
!
(
ia_valid
&
ATTR_FILE
))
av
|=
FILE__OPEN
;
av
|=
FILE__OPEN
;
return
dentry_has_perm
(
cred
,
dentry
,
av
);
return
dentry_has_perm
(
cred
,
dentry
,
av
);
...
@@ -3107,6 +3139,18 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
...
@@ -3107,6 +3139,18 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
return
dentry_has_perm
(
cred
,
dentry
,
FILE__SETATTR
);
return
dentry_has_perm
(
cred
,
dentry
,
FILE__SETATTR
);
}
}
static
bool
has_cap_mac_admin
(
bool
audit
)
{
const
struct
cred
*
cred
=
current_cred
();
int
cap_audit
=
audit
?
SECURITY_CAP_AUDIT
:
SECURITY_CAP_NOAUDIT
;
if
(
cap_capable
(
cred
,
&
init_user_ns
,
CAP_MAC_ADMIN
,
cap_audit
))
return
false
;
if
(
cred_has_capability
(
cred
,
CAP_MAC_ADMIN
,
cap_audit
,
true
))
return
false
;
return
true
;
}
static
int
selinux_inode_setxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
static
int
selinux_inode_setxattr
(
struct
dentry
*
dentry
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
const
void
*
value
,
size_t
size
,
int
flags
)
{
{
...
@@ -3138,7 +3182,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
...
@@ -3138,7 +3182,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
rc
=
security_context_to_sid
(
value
,
size
,
&
newsid
,
GFP_KERNEL
);
rc
=
security_context_to_sid
(
value
,
size
,
&
newsid
,
GFP_KERNEL
);
if
(
rc
==
-
EINVAL
)
{
if
(
rc
==
-
EINVAL
)
{
if
(
!
capable
(
CAP_MAC_ADMIN
))
{
if
(
!
has_cap_mac_admin
(
true
))
{
struct
audit_buffer
*
ab
;
struct
audit_buffer
*
ab
;
size_t
audit_size
;
size_t
audit_size
;
const
char
*
str
;
const
char
*
str
;
...
@@ -3264,13 +3308,8 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
...
@@ -3264,13 +3308,8 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
* and lack of permission just means that we fall back to the
* and lack of permission just means that we fall back to the
* in-core context value, not a denial.
* in-core context value, not a denial.
*/
*/
error
=
cap_capable
(
current_cred
(),
&
init_user_ns
,
CAP_MAC_ADMIN
,
SECURITY_CAP_NOAUDIT
);
if
(
!
error
)
error
=
cred_has_capability
(
current_cred
(),
CAP_MAC_ADMIN
,
SECURITY_CAP_NOAUDIT
,
true
);
isec
=
inode_security
(
inode
);
isec
=
inode_security
(
inode
);
if
(
!
error
)
if
(
has_cap_mac_admin
(
false
)
)
error
=
security_sid_to_context_force
(
isec
->
sid
,
&
context
,
error
=
security_sid_to_context_force
(
isec
->
sid
,
&
context
,
&
size
);
&
size
);
else
else
...
@@ -3550,6 +3589,18 @@ static int selinux_mmap_addr(unsigned long addr)
...
@@ -3550,6 +3589,18 @@ static int selinux_mmap_addr(unsigned long addr)
static
int
selinux_mmap_file
(
struct
file
*
file
,
unsigned
long
reqprot
,
static
int
selinux_mmap_file
(
struct
file
*
file
,
unsigned
long
reqprot
,
unsigned
long
prot
,
unsigned
long
flags
)
unsigned
long
prot
,
unsigned
long
flags
)
{
{
struct
common_audit_data
ad
;
int
rc
;
if
(
file
)
{
ad
.
type
=
LSM_AUDIT_DATA_FILE
;
ad
.
u
.
file
=
file
;
rc
=
inode_has_perm
(
current_cred
(),
file_inode
(
file
),
FILE__MAP
,
&
ad
);
if
(
rc
)
return
rc
;
}
if
(
selinux_checkreqprot
)
if
(
selinux_checkreqprot
)
prot
=
reqprot
;
prot
=
reqprot
;
...
@@ -3710,7 +3761,8 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
...
@@ -3710,7 +3761,8 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
/* task security operations */
/* task security operations */
static
int
selinux_task_create
(
unsigned
long
clone_flags
)
static
int
selinux_task_alloc
(
struct
task_struct
*
task
,
unsigned
long
clone_flags
)
{
{
u32
sid
=
current_sid
();
u32
sid
=
current_sid
();
...
@@ -5918,7 +5970,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
...
@@ -5918,7 +5970,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
}
}
error
=
security_context_to_sid
(
value
,
size
,
&
sid
,
GFP_KERNEL
);
error
=
security_context_to_sid
(
value
,
size
,
&
sid
,
GFP_KERNEL
);
if
(
error
==
-
EINVAL
&&
!
strcmp
(
name
,
"fscreate"
))
{
if
(
error
==
-
EINVAL
&&
!
strcmp
(
name
,
"fscreate"
))
{
if
(
!
capable
(
CAP_MAC_ADMIN
))
{
if
(
!
has_cap_mac_admin
(
true
))
{
struct
audit_buffer
*
ab
;
struct
audit_buffer
*
ab
;
size_t
audit_size
;
size_t
audit_size
;
...
@@ -6128,7 +6180,70 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
...
@@ -6128,7 +6180,70 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
*
_buffer
=
context
;
*
_buffer
=
context
;
return
rc
;
return
rc
;
}
}
#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
=
sel_ib_pkey_sid
(
subnet_prefix
,
pkey_val
,
&
sid
);
if
(
err
)
return
err
;
ad
.
type
=
LSM_AUDIT_DATA_IBPKEY
;
ibpkey
.
subnet_prefix
=
subnet_prefix
;
ibpkey
.
pkey
=
pkey_val
;
ad
.
u
.
ibpkey
=
&
ibpkey
;
return
avc_has_perm
(
sec
->
sid
,
sid
,
SECCLASS_INFINIBAND_PKEY
,
INFINIBAND_PKEY__ACCESS
,
&
ad
);
}
static
int
selinux_ib_endport_manage_subnet
(
void
*
ib_sec
,
const
char
*
dev_name
,
u8
port_num
)
{
struct
common_audit_data
ad
;
int
err
;
u32
sid
=
0
;
struct
ib_security_struct
*
sec
=
ib_sec
;
struct
lsm_ibendport_audit
ibendport
;
err
=
security_ib_endport_sid
(
dev_name
,
port_num
,
&
sid
);
if
(
err
)
return
err
;
ad
.
type
=
LSM_AUDIT_DATA_IBENDPORT
;
strncpy
(
ibendport
.
dev_name
,
dev_name
,
sizeof
(
ibendport
.
dev_name
));
ibendport
.
port
=
port_num
;
ad
.
u
.
ibendport
=
&
ibendport
;
return
avc_has_perm
(
sec
->
sid
,
sid
,
SECCLASS_INFINIBAND_ENDPORT
,
INFINIBAND_ENDPORT__MANAGE_SUBNET
,
&
ad
);
}
static
int
selinux_ib_alloc_security
(
void
**
ib_sec
)
{
struct
ib_security_struct
*
sec
;
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
#endif
static
struct
security_hook_list
selinux_hooks
[]
__lsm_ro_after_init
=
{
static
struct
security_hook_list
selinux_hooks
[]
__lsm_ro_after_init
=
{
...
@@ -6213,7 +6328,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
...
@@ -6213,7 +6328,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT
(
file_open
,
selinux_file_open
),
LSM_HOOK_INIT
(
file_open
,
selinux_file_open
),
LSM_HOOK_INIT
(
task_
create
,
selinux_task_create
),
LSM_HOOK_INIT
(
task_
alloc
,
selinux_task_alloc
),
LSM_HOOK_INIT
(
cred_alloc_blank
,
selinux_cred_alloc_blank
),
LSM_HOOK_INIT
(
cred_alloc_blank
,
selinux_cred_alloc_blank
),
LSM_HOOK_INIT
(
cred_free
,
selinux_cred_free
),
LSM_HOOK_INIT
(
cred_free
,
selinux_cred_free
),
LSM_HOOK_INIT
(
cred_prepare
,
selinux_cred_prepare
),
LSM_HOOK_INIT
(
cred_prepare
,
selinux_cred_prepare
),
...
@@ -6315,7 +6430,13 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
...
@@ -6315,7 +6430,13 @@ 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_queue
,
selinux_tun_dev_attach_queue
),
LSM_HOOK_INIT
(
tun_dev_attach
,
selinux_tun_dev_attach
),
LSM_HOOK_INIT
(
tun_dev_attach
,
selinux_tun_dev_attach
),
LSM_HOOK_INIT
(
tun_dev_open
,
selinux_tun_dev_open
),
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
#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM
LSM_HOOK_INIT
(
xfrm_policy_alloc_security
,
selinux_xfrm_policy_alloc
),
LSM_HOOK_INIT
(
xfrm_policy_alloc_security
,
selinux_xfrm_policy_alloc
),
LSM_HOOK_INIT
(
xfrm_policy_clone_security
,
selinux_xfrm_policy_clone
),
LSM_HOOK_INIT
(
xfrm_policy_clone_security
,
selinux_xfrm_policy_clone
),
...
@@ -6379,6 +6500,9 @@ static __init int selinux_init(void)
...
@@ -6379,6 +6500,9 @@ static __init int selinux_init(void)
if
(
avc_add_callback
(
selinux_netcache_avc_callback
,
AVC_CALLBACK_RESET
))
if
(
avc_add_callback
(
selinux_netcache_avc_callback
,
AVC_CALLBACK_RESET
))
panic
(
"SELinux: Unable to register AVC netcache callback
\n
"
);
panic
(
"SELinux: Unable to register AVC netcache callback
\n
"
);
if
(
avc_add_callback
(
selinux_lsm_notifier_avc_callback
,
AVC_CALLBACK_RESET
))
panic
(
"SELinux: Unable to register AVC LSM notifier callback
\n
"
);
if
(
selinux_enforcing
)
if
(
selinux_enforcing
)
printk
(
KERN_DEBUG
"SELinux: Starting in enforcing mode
\n
"
);
printk
(
KERN_DEBUG
"SELinux: Starting in enforcing mode
\n
"
);
else
else
...
@@ -6448,6 +6572,23 @@ static struct nf_hook_ops selinux_nf_ops[] = {
...
@@ -6448,6 +6572,23 @@ static struct nf_hook_ops selinux_nf_ops[] = {
#endif
/* IPV6 */
#endif
/* IPV6 */
};
};
static
int
__net_init
selinux_nf_register
(
struct
net
*
net
)
{
return
nf_register_net_hooks
(
net
,
selinux_nf_ops
,
ARRAY_SIZE
(
selinux_nf_ops
));
}
static
void
__net_exit
selinux_nf_unregister
(
struct
net
*
net
)
{
nf_unregister_net_hooks
(
net
,
selinux_nf_ops
,
ARRAY_SIZE
(
selinux_nf_ops
));
}
static
struct
pernet_operations
selinux_net_ops
=
{
.
init
=
selinux_nf_register
,
.
exit
=
selinux_nf_unregister
,
};
static
int
__init
selinux_nf_ip_init
(
void
)
static
int
__init
selinux_nf_ip_init
(
void
)
{
{
int
err
;
int
err
;
...
@@ -6457,13 +6598,12 @@ static int __init selinux_nf_ip_init(void)
...
@@ -6457,13 +6598,12 @@ static int __init selinux_nf_ip_init(void)
printk
(
KERN_DEBUG
"SELinux: Registering netfilter hooks
\n
"
);
printk
(
KERN_DEBUG
"SELinux: Registering netfilter hooks
\n
"
);
err
=
nf_register_hooks
(
selinux_nf_ops
,
ARRAY_SIZE
(
selinux_nf_ops
)
);
err
=
register_pernet_subsys
(
&
selinux_net_ops
);
if
(
err
)
if
(
err
)
panic
(
"SELinux:
nf_register_hook
s: error %d
\n
"
,
err
);
panic
(
"SELinux:
register_pernet_subsy
s: error %d
\n
"
,
err
);
return
0
;
return
0
;
}
}
__initcall
(
selinux_nf_ip_init
);
__initcall
(
selinux_nf_ip_init
);
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
...
@@ -6471,7 +6611,7 @@ static void selinux_nf_ip_exit(void)
...
@@ -6471,7 +6611,7 @@ static void selinux_nf_ip_exit(void)
{
{
printk
(
KERN_DEBUG
"SELinux: Unregistering netfilter hooks
\n
"
);
printk
(
KERN_DEBUG
"SELinux: Unregistering netfilter hooks
\n
"
);
nf_unregister_hooks
(
selinux_nf_ops
,
ARRAY_SIZE
(
selinux_nf_ops
)
);
unregister_pernet_subsys
(
&
selinux_net_ops
);
}
}
#endif
#endif
...
...
security/selinux/ibpkey.c
0 → 100644
浏览文件 @
5965453d
/*
* Pkey table
*
* SELinux must keep a mapping of Infinband PKEYs to labels/SIDs. This
* mapping is maintained as part of the normal policy but a fast cache is
* needed to reduce the lookup overhead.
*
* This code is heavily based on the "netif" and "netport" concept originally
* developed by
* James Morris <jmorris@redhat.com> and
* Paul Moore <paul@paul-moore.com>
* (see security/selinux/netif.c and security/selinux/netport.c for more
* information)
*
*/
/*
* (c) Mellanox Technologies, 2016
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include "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
(
pkey
&
(
SEL_PKEY_HASH_SIZE
-
1
));
}
/**
* sel_ib_pkey_find - Search for a pkey record
* @subnet_prefix: subnet_prefix
* @pkey_num: pkey_num
*
* Description:
* Search the pkey table and return the matching record. If an entry
* can not be found in the table return NULL.
*
*/
static
struct
sel_ib_pkey
*
sel_ib_pkey_find
(
u64
subnet_prefix
,
u16
pkey_num
)
{
unsigned
int
idx
;
struct
sel_ib_pkey
*
pkey
;
idx
=
sel_ib_pkey_hashfn
(
pkey_num
);
list_for_each_entry_rcu
(
pkey
,
&
sel_ib_pkey_hash
[
idx
].
list
,
list
)
{
if
(
pkey
->
psec
.
pkey
==
pkey_num
&&
pkey
->
psec
.
subnet_prefix
==
subnet_prefix
)
return
pkey
;
}
return
NULL
;
}
/**
* sel_ib_pkey_insert - Insert a new pkey into the table
* @pkey: the new pkey record
*
* Description:
* Add a new pkey record to the hash table.
*
*/
static
void
sel_ib_pkey_insert
(
struct
sel_ib_pkey
*
pkey
)
{
unsigned
int
idx
;
/* we need to impose a limit on the growth of the hash table so check
* this bucket to make sure it is within the specified bounds
*/
idx
=
sel_ib_pkey_hashfn
(
pkey
->
psec
.
pkey
);
list_add_rcu
(
&
pkey
->
list
,
&
sel_ib_pkey_hash
[
idx
].
list
);
if
(
sel_ib_pkey_hash
[
idx
].
size
==
SEL_PKEY_HASH_BKT_LIMIT
)
{
struct
sel_ib_pkey
*
tail
;
tail
=
list_entry
(
rcu_dereference_protected
(
sel_ib_pkey_hash
[
idx
].
list
.
prev
,
lockdep_is_held
(
&
sel_ib_pkey_lock
)),
struct
sel_ib_pkey
,
list
);
list_del_rcu
(
&
tail
->
list
);
kfree_rcu
(
tail
,
rcu
);
}
else
{
sel_ib_pkey_hash
[
idx
].
size
++
;
}
}
/**
* sel_ib_pkey_sid_slow - Lookup the SID of a pkey using the policy
* @subnet_prefix: subnet prefix
* @pkey_num: pkey number
* @sid: pkey SID
*
* Description:
* This function determines the SID of a pkey by querying the security
* policy. The result is added to the pkey table to speedup future
* queries. Returns zero on success, negative values on failure.
*
*/
static
int
sel_ib_pkey_sid_slow
(
u64
subnet_prefix
,
u16
pkey_num
,
u32
*
sid
)
{
int
ret
;
struct
sel_ib_pkey
*
pkey
;
struct
sel_ib_pkey
*
new
=
NULL
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
sel_ib_pkey_lock
,
flags
);
pkey
=
sel_ib_pkey_find
(
subnet_prefix
,
pkey_num
);
if
(
pkey
)
{
*
sid
=
pkey
->
psec
.
sid
;
spin_unlock_irqrestore
(
&
sel_ib_pkey_lock
,
flags
);
return
0
;
}
ret
=
security_ib_pkey_sid
(
subnet_prefix
,
pkey_num
,
sid
);
if
(
ret
)
goto
out
;
/* If this memory allocation fails still return 0. The SID
* is valid, it just won't be added to the cache.
*/
new
=
kzalloc
(
sizeof
(
*
new
),
GFP_ATOMIC
);
if
(
!
new
)
goto
out
;
new
->
psec
.
subnet_prefix
=
subnet_prefix
;
new
->
psec
.
pkey
=
pkey_num
;
new
->
psec
.
sid
=
*
sid
;
sel_ib_pkey_insert
(
new
);
out:
spin_unlock_irqrestore
(
&
sel_ib_pkey_lock
,
flags
);
return
ret
;
}
/**
* sel_ib_pkey_sid - Lookup the SID of a PKEY
* @subnet_prefix: subnet_prefix
* @pkey_num: pkey number
* @sid: pkey SID
*
* Description:
* This function determines the SID of a PKEY using the fastest method
* possible. First the pkey table is queried, but if an entry can't be found
* then the policy is queried and the result is added to the table to speedup
* future queries. Returns zero on success, negative values on failure.
*
*/
int
sel_ib_pkey_sid
(
u64
subnet_prefix
,
u16
pkey_num
,
u32
*
sid
)
{
struct
sel_ib_pkey
*
pkey
;
rcu_read_lock
();
pkey
=
sel_ib_pkey_find
(
subnet_prefix
,
pkey_num
);
if
(
pkey
)
{
*
sid
=
pkey
->
psec
.
sid
;
rcu_read_unlock
();
return
0
;
}
rcu_read_unlock
();
return
sel_ib_pkey_sid_slow
(
subnet_prefix
,
pkey_num
,
sid
);
}
/**
* sel_ib_pkey_flush - Flush the entire pkey table
*
* Description:
* Remove all entries from the pkey table
*
*/
void
sel_ib_pkey_flush
(
void
)
{
unsigned
int
idx
;
struct
sel_ib_pkey
*
pkey
,
*
pkey_tmp
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
sel_ib_pkey_lock
,
flags
);
for
(
idx
=
0
;
idx
<
SEL_PKEY_HASH_SIZE
;
idx
++
)
{
list_for_each_entry_safe
(
pkey
,
pkey_tmp
,
&
sel_ib_pkey_hash
[
idx
].
list
,
list
)
{
list_del_rcu
(
&
pkey
->
list
);
kfree_rcu
(
pkey
,
rcu
);
}
sel_ib_pkey_hash
[
idx
].
size
=
0
;
}
spin_unlock_irqrestore
(
&
sel_ib_pkey_lock
,
flags
);
}
static
__init
int
sel_ib_pkey_init
(
void
)
{
int
iter
;
if
(
!
selinux_enabled
)
return
0
;
for
(
iter
=
0
;
iter
<
SEL_PKEY_HASH_SIZE
;
iter
++
)
{
INIT_LIST_HEAD
(
&
sel_ib_pkey_hash
[
iter
].
list
);
sel_ib_pkey_hash
[
iter
].
size
=
0
;
}
return
0
;
}
subsys_initcall
(
sel_ib_pkey_init
);
security/selinux/include/classmap.h
浏览文件 @
5965453d
#include <linux/capability.h>
#include <linux/capability.h>
#define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \
#define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \
"getattr", "setattr", "lock", "relabelfrom", "relabelto", "append"
"getattr", "setattr", "lock", "relabelfrom", "relabelto", "append"
, "map"
#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
"rename", "execute", "quotaon", "mounton", "audit_access", \
"rename", "execute", "quotaon", "mounton", "audit_access", \
...
@@ -231,6 +231,10 @@ struct security_class_mapping secclass_map[] = {
...
@@ -231,6 +231,10 @@ struct security_class_mapping secclass_map[] = {
{
COMMON_SOCK_PERMS
,
NULL
}
},
{
COMMON_SOCK_PERMS
,
NULL
}
},
{
"smc_socket"
,
{
"smc_socket"
,
{
COMMON_SOCK_PERMS
,
NULL
}
},
{
COMMON_SOCK_PERMS
,
NULL
}
},
{
"infiniband_pkey"
,
{
"access"
,
NULL
}
},
{
"infiniband_endport"
,
{
"manage_subnet"
,
NULL
}
},
{
NULL
}
{
NULL
}
};
};
...
...
security/selinux/include/ibpkey.h
0 → 100644
浏览文件 @
5965453d
/*
* pkey table
*
* SELinux must keep a mapping of pkeys to labels/SIDs. This
* mapping is maintained as part of the normal policy but a fast cache is
* needed to reduce the lookup overhead.
*
*/
/*
* (c) Mellanox Technologies, 2016
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _SELINUX_IB_PKEY_H
#define _SELINUX_IB_PKEY_H
void
sel_ib_pkey_flush
(
void
);
int
sel_ib_pkey_sid
(
u64
subnet_prefix
,
u16
pkey
,
u32
*
sid
);
#endif
security/selinux/include/objsec.h
浏览文件 @
5965453d
...
@@ -10,6 +10,7 @@
...
@@ -10,6 +10,7 @@
*
*
* Copyright (C) 2001,2002 Networks Associates Technology, Inc.
* Copyright (C) 2001,2002 Networks Associates Technology, Inc.
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* Copyright (C) 2016 Mellanox Technologies
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* it under the terms of the GNU General Public License version 2,
...
@@ -139,6 +140,16 @@ struct key_security_struct {
...
@@ -139,6 +140,16 @@ struct key_security_struct {
u32
sid
;
/* SID of key */
u32
sid
;
/* SID of key */
};
};
struct
ib_security_struct
{
u32
sid
;
/* SID of the queue pair or MAD agent */
};
struct
pkey_security_struct
{
u64
subnet_prefix
;
/* Port subnet prefix */
u16
pkey
;
/* PKey number */
u32
sid
;
/* SID of pkey */
};
extern
unsigned
int
selinux_checkreqprot
;
extern
unsigned
int
selinux_checkreqprot
;
#endif
/* _SELINUX_OBJSEC_H_ */
#endif
/* _SELINUX_OBJSEC_H_ */
security/selinux/include/security.h
浏览文件 @
5965453d
...
@@ -36,10 +36,11 @@
...
@@ -36,10 +36,11 @@
#define POLICYDB_VERSION_DEFAULT_TYPE 28
#define POLICYDB_VERSION_DEFAULT_TYPE 28
#define POLICYDB_VERSION_CONSTRAINT_NAMES 29
#define POLICYDB_VERSION_CONSTRAINT_NAMES 29
#define POLICYDB_VERSION_XPERMS_IOCTL 30
#define POLICYDB_VERSION_XPERMS_IOCTL 30
#define POLICYDB_VERSION_INFINIBAND 31
/* Range of policy versions we understand*/
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#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 */
/* Mask for just the mount related flags */
#define SE_MNTMASK 0x0f
#define SE_MNTMASK 0x0f
...
@@ -76,6 +77,8 @@ enum {
...
@@ -76,6 +77,8 @@ enum {
};
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
extern
char
*
selinux_policycap_names
[
__POLICYDB_CAPABILITY_MAX
];
extern
int
selinux_policycap_netpeer
;
extern
int
selinux_policycap_netpeer
;
extern
int
selinux_policycap_openperm
;
extern
int
selinux_policycap_openperm
;
extern
int
selinux_policycap_extsockclass
;
extern
int
selinux_policycap_extsockclass
;
...
@@ -178,6 +181,10 @@ int security_get_user_sids(u32 callsid, char *username,
...
@@ -178,6 +181,10 @@ int security_get_user_sids(u32 callsid, char *username,
int
security_port_sid
(
u8
protocol
,
u16
port
,
u32
*
out_sid
);
int
security_port_sid
(
u8
protocol
,
u16
port
,
u32
*
out_sid
);
int
security_ib_pkey_sid
(
u64
subnet_prefix
,
u16
pkey_num
,
u32
*
out_sid
);
int
security_ib_endport_sid
(
const
char
*
dev_name
,
u8
port_num
,
u32
*
out_sid
);
int
security_netif_sid
(
char
*
name
,
u32
*
if_sid
);
int
security_netif_sid
(
char
*
name
,
u32
*
if_sid
);
int
security_node_sid
(
u16
domain
,
void
*
addr
,
u32
addrlen
,
int
security_node_sid
(
u16
domain
,
void
*
addr
,
u32
addrlen
,
...
...
security/selinux/selinuxfs.c
浏览文件 @
5965453d
...
@@ -41,15 +41,6 @@
...
@@ -41,15 +41,6 @@
#include "objsec.h"
#include "objsec.h"
#include "conditional.h"
#include "conditional.h"
/* Policy capability filenames */
static
char
*
policycap_names
[]
=
{
"network_peer_controls"
,
"open_perms"
,
"extended_socket_class"
,
"always_check_network"
,
"cgroup_seclabel"
};
unsigned
int
selinux_checkreqprot
=
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE
;
unsigned
int
selinux_checkreqprot
=
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE
;
static
int
__init
checkreqprot_setup
(
char
*
str
)
static
int
__init
checkreqprot_setup
(
char
*
str
)
...
@@ -163,6 +154,8 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
...
@@ -163,6 +154,8 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
avc_ss_reset
(
0
);
avc_ss_reset
(
0
);
selnl_notify_setenforce
(
selinux_enforcing
);
selnl_notify_setenforce
(
selinux_enforcing
);
selinux_status_update_setenforce
(
selinux_enforcing
);
selinux_status_update_setenforce
(
selinux_enforcing
);
if
(
!
selinux_enforcing
)
call_lsm_notifier
(
LSM_POLICY_CHANGE
,
NULL
);
}
}
length
=
count
;
length
=
count
;
out:
out:
...
@@ -1750,9 +1743,9 @@ static int sel_make_policycap(void)
...
@@ -1750,9 +1743,9 @@ static int sel_make_policycap(void)
sel_remove_entries
(
policycap_dir
);
sel_remove_entries
(
policycap_dir
);
for
(
iter
=
0
;
iter
<=
POLICYDB_CAPABILITY_MAX
;
iter
++
)
{
for
(
iter
=
0
;
iter
<=
POLICYDB_CAPABILITY_MAX
;
iter
++
)
{
if
(
iter
<
ARRAY_SIZE
(
policycap_names
))
if
(
iter
<
ARRAY_SIZE
(
selinux_
policycap_names
))
dentry
=
d_alloc_name
(
policycap_dir
,
dentry
=
d_alloc_name
(
policycap_dir
,
policycap_names
[
iter
]);
selinux_
policycap_names
[
iter
]);
else
else
dentry
=
d_alloc_name
(
policycap_dir
,
"unknown"
);
dentry
=
d_alloc_name
(
policycap_dir
,
"unknown"
);
...
...
security/selinux/ss/ebitmap.c
浏览文件 @
5965453d
...
@@ -24,6 +24,8 @@
...
@@ -24,6 +24,8 @@
#define BITS_PER_U64 (sizeof(u64) * 8)
#define BITS_PER_U64 (sizeof(u64) * 8)
static
struct
kmem_cache
*
ebitmap_node_cachep
;
int
ebitmap_cmp
(
struct
ebitmap
*
e1
,
struct
ebitmap
*
e2
)
int
ebitmap_cmp
(
struct
ebitmap
*
e1
,
struct
ebitmap
*
e2
)
{
{
struct
ebitmap_node
*
n1
,
*
n2
;
struct
ebitmap_node
*
n1
,
*
n2
;
...
@@ -54,7 +56,7 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
...
@@ -54,7 +56,7 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
n
=
src
->
node
;
n
=
src
->
node
;
prev
=
NULL
;
prev
=
NULL
;
while
(
n
)
{
while
(
n
)
{
new
=
k
zalloc
(
sizeof
(
*
new
)
,
GFP_ATOMIC
);
new
=
k
mem_cache_zalloc
(
ebitmap_node_cachep
,
GFP_ATOMIC
);
if
(
!
new
)
{
if
(
!
new
)
{
ebitmap_destroy
(
dst
);
ebitmap_destroy
(
dst
);
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -162,7 +164,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
...
@@ -162,7 +164,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
if
(
e_iter
==
NULL
||
if
(
e_iter
==
NULL
||
offset
>=
e_iter
->
startbit
+
EBITMAP_SIZE
)
{
offset
>=
e_iter
->
startbit
+
EBITMAP_SIZE
)
{
e_prev
=
e_iter
;
e_prev
=
e_iter
;
e_iter
=
k
zalloc
(
sizeof
(
*
e_iter
)
,
GFP_ATOMIC
);
e_iter
=
k
mem_cache_zalloc
(
ebitmap_node_cachep
,
GFP_ATOMIC
);
if
(
e_iter
==
NULL
)
if
(
e_iter
==
NULL
)
goto
netlbl_import_failure
;
goto
netlbl_import_failure
;
e_iter
->
startbit
=
offset
-
(
offset
%
EBITMAP_SIZE
);
e_iter
->
startbit
=
offset
-
(
offset
%
EBITMAP_SIZE
);
...
@@ -288,7 +290,7 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
...
@@ -288,7 +290,7 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
prev
->
next
=
n
->
next
;
prev
->
next
=
n
->
next
;
else
else
e
->
node
=
n
->
next
;
e
->
node
=
n
->
next
;
k
free
(
n
);
k
mem_cache_free
(
ebitmap_node_cachep
,
n
);
}
}
return
0
;
return
0
;
}
}
...
@@ -299,7 +301,7 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
...
@@ -299,7 +301,7 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
if
(
!
value
)
if
(
!
value
)
return
0
;
return
0
;
new
=
k
zalloc
(
sizeof
(
*
new
)
,
GFP_ATOMIC
);
new
=
k
mem_cache_zalloc
(
ebitmap_node_cachep
,
GFP_ATOMIC
);
if
(
!
new
)
if
(
!
new
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -332,7 +334,7 @@ void ebitmap_destroy(struct ebitmap *e)
...
@@ -332,7 +334,7 @@ void ebitmap_destroy(struct ebitmap *e)
while
(
n
)
{
while
(
n
)
{
temp
=
n
;
temp
=
n
;
n
=
n
->
next
;
n
=
n
->
next
;
k
free
(
temp
);
k
mem_cache_free
(
ebitmap_node_cachep
,
temp
);
}
}
e
->
highbit
=
0
;
e
->
highbit
=
0
;
...
@@ -400,7 +402,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
...
@@ -400,7 +402,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
if
(
!
n
||
startbit
>=
n
->
startbit
+
EBITMAP_SIZE
)
{
if
(
!
n
||
startbit
>=
n
->
startbit
+
EBITMAP_SIZE
)
{
struct
ebitmap_node
*
tmp
;
struct
ebitmap_node
*
tmp
;
tmp
=
k
zalloc
(
sizeof
(
*
tmp
)
,
GFP_KERNEL
);
tmp
=
k
mem_cache_zalloc
(
ebitmap_node_cachep
,
GFP_KERNEL
);
if
(
!
tmp
)
{
if
(
!
tmp
)
{
printk
(
KERN_ERR
printk
(
KERN_ERR
"SELinux: ebitmap: out of memory
\n
"
);
"SELinux: ebitmap: out of memory
\n
"
);
...
@@ -519,3 +521,15 @@ int ebitmap_write(struct ebitmap *e, void *fp)
...
@@ -519,3 +521,15 @@ int ebitmap_write(struct ebitmap *e, void *fp)
}
}
return
0
;
return
0
;
}
}
void
ebitmap_cache_init
(
void
)
{
ebitmap_node_cachep
=
kmem_cache_create
(
"ebitmap_node"
,
sizeof
(
struct
ebitmap_node
),
0
,
SLAB_PANIC
,
NULL
);
}
void
ebitmap_cache_destroy
(
void
)
{
kmem_cache_destroy
(
ebitmap_node_cachep
);
}
security/selinux/ss/ebitmap.h
浏览文件 @
5965453d
...
@@ -130,6 +130,9 @@ void ebitmap_destroy(struct ebitmap *e);
...
@@ -130,6 +130,9 @@ void ebitmap_destroy(struct ebitmap *e);
int
ebitmap_read
(
struct
ebitmap
*
e
,
void
*
fp
);
int
ebitmap_read
(
struct
ebitmap
*
e
,
void
*
fp
);
int
ebitmap_write
(
struct
ebitmap
*
e
,
void
*
fp
);
int
ebitmap_write
(
struct
ebitmap
*
e
,
void
*
fp
);
void
ebitmap_cache_init
(
void
);
void
ebitmap_cache_destroy
(
void
);
#ifdef CONFIG_NETLABEL
#ifdef CONFIG_NETLABEL
int
ebitmap_netlbl_export
(
struct
ebitmap
*
ebmap
,
int
ebitmap_netlbl_export
(
struct
ebitmap
*
ebmap
,
struct
netlbl_lsm_catmap
**
catmap
);
struct
netlbl_lsm_catmap
**
catmap
);
...
...
security/selinux/ss/policydb.c
浏览文件 @
5965453d
...
@@ -17,6 +17,11 @@
...
@@ -17,6 +17,11 @@
*
*
* Added support for the policy capability bitmap
* 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) 2007 Hewlett-Packard Development Company, L.P.
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
...
@@ -76,81 +81,86 @@ static struct policydb_compat_info policydb_compat[] = {
...
@@ -76,81 +81,86 @@ static struct policydb_compat_info policydb_compat[] = {
{
{
.
version
=
POLICYDB_VERSION_BASE
,
.
version
=
POLICYDB_VERSION_BASE
,
.
sym_num
=
SYM_NUM
-
3
,
.
sym_num
=
SYM_NUM
-
3
,
.
ocon_num
=
OCON_NUM
-
1
,
.
ocon_num
=
OCON_NUM
-
3
,
},
},
{
{
.
version
=
POLICYDB_VERSION_BOOL
,
.
version
=
POLICYDB_VERSION_BOOL
,
.
sym_num
=
SYM_NUM
-
2
,
.
sym_num
=
SYM_NUM
-
2
,
.
ocon_num
=
OCON_NUM
-
1
,
.
ocon_num
=
OCON_NUM
-
3
,
},
},
{
{
.
version
=
POLICYDB_VERSION_IPV6
,
.
version
=
POLICYDB_VERSION_IPV6
,
.
sym_num
=
SYM_NUM
-
2
,
.
sym_num
=
SYM_NUM
-
2
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_NLCLASS
,
.
version
=
POLICYDB_VERSION_NLCLASS
,
.
sym_num
=
SYM_NUM
-
2
,
.
sym_num
=
SYM_NUM
-
2
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_MLS
,
.
version
=
POLICYDB_VERSION_MLS
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_AVTAB
,
.
version
=
POLICYDB_VERSION_AVTAB
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_RANGETRANS
,
.
version
=
POLICYDB_VERSION_RANGETRANS
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_POLCAP
,
.
version
=
POLICYDB_VERSION_POLCAP
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_PERMISSIVE
,
.
version
=
POLICYDB_VERSION_PERMISSIVE
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_BOUNDARY
,
.
version
=
POLICYDB_VERSION_BOUNDARY
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_FILENAME_TRANS
,
.
version
=
POLICYDB_VERSION_FILENAME_TRANS
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_ROLETRANS
,
.
version
=
POLICYDB_VERSION_ROLETRANS
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
,
.
version
=
POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_DEFAULT_TYPE
,
.
version
=
POLICYDB_VERSION_DEFAULT_TYPE
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_CONSTRAINT_NAMES
,
.
version
=
POLICYDB_VERSION_CONSTRAINT_NAMES
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
},
{
{
.
version
=
POLICYDB_VERSION_XPERMS_IOCTL
,
.
version
=
POLICYDB_VERSION_XPERMS_IOCTL
,
.
sym_num
=
SYM_NUM
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
-
2
,
},
{
.
version
=
POLICYDB_VERSION_INFINIBAND
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
.
ocon_num
=
OCON_NUM
,
},
},
};
};
...
@@ -538,34 +548,30 @@ static int policydb_index(struct policydb *p)
...
@@ -538,34 +548,30 @@ static int policydb_index(struct policydb *p)
symtab_hash_eval
(
p
->
symtab
);
symtab_hash_eval
(
p
->
symtab
);
#endif
#endif
rc
=
-
ENOMEM
;
p
->
class_val_to_struct
=
kcalloc
(
p
->
p_classes
.
nprim
,
p
->
class_val_to_struct
=
kcalloc
(
p
->
p_classes
.
nprim
,
sizeof
(
*
p
->
class_val_to_struct
),
sizeof
(
*
p
->
class_val_to_struct
),
GFP_KERNEL
);
GFP_KERNEL
);
if
(
!
p
->
class_val_to_struct
)
if
(
!
p
->
class_val_to_struct
)
goto
out
;
return
-
ENOMEM
;
rc
=
-
ENOMEM
;
p
->
role_val_to_struct
=
kcalloc
(
p
->
p_roles
.
nprim
,
p
->
role_val_to_struct
=
kcalloc
(
p
->
p_roles
.
nprim
,
sizeof
(
*
p
->
role_val_to_struct
),
sizeof
(
*
p
->
role_val_to_struct
),
GFP_KERNEL
);
GFP_KERNEL
);
if
(
!
p
->
role_val_to_struct
)
if
(
!
p
->
role_val_to_struct
)
goto
out
;
return
-
ENOMEM
;
rc
=
-
ENOMEM
;
p
->
user_val_to_struct
=
kcalloc
(
p
->
p_users
.
nprim
,
p
->
user_val_to_struct
=
kcalloc
(
p
->
p_users
.
nprim
,
sizeof
(
*
p
->
user_val_to_struct
),
sizeof
(
*
p
->
user_val_to_struct
),
GFP_KERNEL
);
GFP_KERNEL
);
if
(
!
p
->
user_val_to_struct
)
if
(
!
p
->
user_val_to_struct
)
goto
out
;
return
-
ENOMEM
;
/* Yes, I want the sizeof the pointer, not the structure */
/* Yes, I want the sizeof the pointer, not the structure */
rc
=
-
ENOMEM
;
p
->
type_val_to_struct_array
=
flex_array_alloc
(
sizeof
(
struct
type_datum
*
),
p
->
type_val_to_struct_array
=
flex_array_alloc
(
sizeof
(
struct
type_datum
*
),
p
->
p_types
.
nprim
,
p
->
p_types
.
nprim
,
GFP_KERNEL
|
__GFP_ZERO
);
GFP_KERNEL
|
__GFP_ZERO
);
if
(
!
p
->
type_val_to_struct_array
)
if
(
!
p
->
type_val_to_struct_array
)
goto
out
;
return
-
ENOMEM
;
rc
=
flex_array_prealloc
(
p
->
type_val_to_struct_array
,
0
,
rc
=
flex_array_prealloc
(
p
->
type_val_to_struct_array
,
0
,
p
->
p_types
.
nprim
,
GFP_KERNEL
|
__GFP_ZERO
);
p
->
p_types
.
nprim
,
GFP_KERNEL
|
__GFP_ZERO
);
...
@@ -577,12 +583,11 @@ static int policydb_index(struct policydb *p)
...
@@ -577,12 +583,11 @@ static int policydb_index(struct policydb *p)
goto
out
;
goto
out
;
for
(
i
=
0
;
i
<
SYM_NUM
;
i
++
)
{
for
(
i
=
0
;
i
<
SYM_NUM
;
i
++
)
{
rc
=
-
ENOMEM
;
p
->
sym_val_to_name
[
i
]
=
flex_array_alloc
(
sizeof
(
char
*
),
p
->
sym_val_to_name
[
i
]
=
flex_array_alloc
(
sizeof
(
char
*
),
p
->
symtab
[
i
].
nprim
,
p
->
symtab
[
i
].
nprim
,
GFP_KERNEL
|
__GFP_ZERO
);
GFP_KERNEL
|
__GFP_ZERO
);
if
(
!
p
->
sym_val_to_name
[
i
])
if
(
!
p
->
sym_val_to_name
[
i
])
goto
out
;
return
-
ENOMEM
;
rc
=
flex_array_prealloc
(
p
->
sym_val_to_name
[
i
],
rc
=
flex_array_prealloc
(
p
->
sym_val_to_name
[
i
],
0
,
p
->
symtab
[
i
].
nprim
,
0
,
p
->
symtab
[
i
].
nprim
,
...
@@ -2211,6 +2216,51 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
...
@@ -2211,6 +2216,51 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
goto
out
;
goto
out
;
break
;
break
;
}
}
case
OCON_IBPKEY
:
rc
=
next_entry
(
nodebuf
,
fp
,
sizeof
(
u32
)
*
4
);
if
(
rc
)
goto
out
;
c
->
u
.
ibpkey
.
subnet_prefix
=
be64_to_cpu
(
*
((
__be64
*
)
nodebuf
));
if
(
nodebuf
[
2
]
>
0xffff
||
nodebuf
[
3
]
>
0xffff
)
{
rc
=
-
EINVAL
;
goto
out
;
}
c
->
u
.
ibpkey
.
low_pkey
=
le32_to_cpu
(
nodebuf
[
2
]);
c
->
u
.
ibpkey
.
high_pkey
=
le32_to_cpu
(
nodebuf
[
3
]);
rc
=
context_read_and_validate
(
&
c
->
context
[
0
],
p
,
fp
);
if
(
rc
)
goto
out
;
break
;
case
OCON_IBENDPORT
:
rc
=
next_entry
(
buf
,
fp
,
sizeof
(
u32
)
*
2
);
if
(
rc
)
goto
out
;
len
=
le32_to_cpu
(
buf
[
0
]);
rc
=
str_read
(
&
c
->
u
.
ibendport
.
dev_name
,
GFP_KERNEL
,
fp
,
len
);
if
(
rc
)
goto
out
;
if
(
buf
[
1
]
>
0xff
||
buf
[
1
]
==
0
)
{
rc
=
-
EINVAL
;
goto
out
;
}
c
->
u
.
ibendport
.
port
=
le32_to_cpu
(
buf
[
1
]);
rc
=
context_read_and_validate
(
&
c
->
context
[
0
],
p
,
fp
);
if
(
rc
)
goto
out
;
break
;
}
}
}
}
}
}
...
@@ -3140,6 +3190,33 @@ static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
...
@@ -3140,6 +3190,33 @@ static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
break
;
break
;
case
OCON_IBPKEY
:
*
((
__be64
*
)
nodebuf
)
=
cpu_to_be64
(
c
->
u
.
ibpkey
.
subnet_prefix
);
nodebuf
[
2
]
=
cpu_to_le32
(
c
->
u
.
ibpkey
.
low_pkey
);
nodebuf
[
3
]
=
cpu_to_le32
(
c
->
u
.
ibpkey
.
high_pkey
);
rc
=
put_entry
(
nodebuf
,
sizeof
(
u32
),
4
,
fp
);
if
(
rc
)
return
rc
;
rc
=
context_write
(
p
,
&
c
->
context
[
0
],
fp
);
if
(
rc
)
return
rc
;
break
;
case
OCON_IBENDPORT
:
len
=
strlen
(
c
->
u
.
ibendport
.
dev_name
);
buf
[
0
]
=
cpu_to_le32
(
len
);
buf
[
1
]
=
cpu_to_le32
(
c
->
u
.
ibendport
.
port
);
rc
=
put_entry
(
buf
,
sizeof
(
u32
),
2
,
fp
);
if
(
rc
)
return
rc
;
rc
=
put_entry
(
c
->
u
.
ibendport
.
dev_name
,
1
,
len
,
fp
);
if
(
rc
)
return
rc
;
rc
=
context_write
(
p
,
&
c
->
context
[
0
],
fp
);
if
(
rc
)
return
rc
;
break
;
}
}
}
}
}
}
...
...
security/selinux/ss/policydb.h
浏览文件 @
5965453d
...
@@ -187,6 +187,15 @@ struct ocontext {
...
@@ -187,6 +187,15 @@ struct ocontext {
u32
addr
[
4
];
u32
addr
[
4
];
u32
mask
[
4
];
u32
mask
[
4
];
}
node6
;
/* IPv6 node information */
}
node6
;
/* IPv6 node information */
struct
{
u64
subnet_prefix
;
u16
low_pkey
;
u16
high_pkey
;
}
ibpkey
;
struct
{
char
*
dev_name
;
u8
port
;
}
ibendport
;
}
u
;
}
u
;
union
{
union
{
u32
sclass
;
/* security class for genfs */
u32
sclass
;
/* security class for genfs */
...
@@ -215,14 +224,16 @@ struct genfs {
...
@@ -215,14 +224,16 @@ struct genfs {
#define SYM_NUM 8
#define SYM_NUM 8
/* object context array indices */
/* object context array indices */
#define OCON_ISID 0
/* initial SIDs */
#define OCON_ISID 0
/* initial SIDs */
#define OCON_FS 1
/* unlabeled file systems */
#define OCON_FS 1
/* unlabeled file systems */
#define OCON_PORT 2
/* TCP and UDP port numbers */
#define OCON_PORT 2
/* TCP and UDP port numbers */
#define OCON_NETIF 3
/* network interfaces */
#define OCON_NETIF 3
/* network interfaces */
#define OCON_NODE 4
/* nodes */
#define OCON_NODE 4
/* nodes */
#define OCON_FSUSE 5
/* fs_use */
#define OCON_FSUSE 5
/* fs_use */
#define OCON_NODE6 6
/* IPv6 nodes */
#define OCON_NODE6 6
/* IPv6 nodes */
#define OCON_NUM 7
#define OCON_IBPKEY 7
/* Infiniband PKeys */
#define OCON_IBENDPORT 8
/* Infiniband end ports */
#define OCON_NUM 9
/* The policy database */
/* The policy database */
struct
policydb
{
struct
policydb
{
...
...
security/selinux/ss/services.c
浏览文件 @
5965453d
...
@@ -70,6 +70,15 @@
...
@@ -70,6 +70,15 @@
#include "ebitmap.h"
#include "ebitmap.h"
#include "audit.h"
#include "audit.h"
/* Policy capability names */
char
*
selinux_policycap_names
[
__POLICYDB_CAPABILITY_MAX
]
=
{
"network_peer_controls"
,
"open_perms"
,
"extended_socket_class"
,
"always_check_network"
,
"cgroup_seclabel"
};
int
selinux_policycap_netpeer
;
int
selinux_policycap_netpeer
;
int
selinux_policycap_openperm
;
int
selinux_policycap_openperm
;
int
selinux_policycap_extsockclass
;
int
selinux_policycap_extsockclass
;
...
@@ -1986,6 +1995,9 @@ static int convert_context(u32 key,
...
@@ -1986,6 +1995,9 @@ static int convert_context(u32 key,
static
void
security_load_policycaps
(
void
)
static
void
security_load_policycaps
(
void
)
{
{
unsigned
int
i
;
struct
ebitmap_node
*
node
;
selinux_policycap_netpeer
=
ebitmap_get_bit
(
&
policydb
.
policycaps
,
selinux_policycap_netpeer
=
ebitmap_get_bit
(
&
policydb
.
policycaps
,
POLICYDB_CAPABILITY_NETPEER
);
POLICYDB_CAPABILITY_NETPEER
);
selinux_policycap_openperm
=
ebitmap_get_bit
(
&
policydb
.
policycaps
,
selinux_policycap_openperm
=
ebitmap_get_bit
(
&
policydb
.
policycaps
,
...
@@ -1997,6 +2009,17 @@ static void security_load_policycaps(void)
...
@@ -1997,6 +2009,17 @@ static void security_load_policycaps(void)
selinux_policycap_cgroupseclabel
=
selinux_policycap_cgroupseclabel
=
ebitmap_get_bit
(
&
policydb
.
policycaps
,
ebitmap_get_bit
(
&
policydb
.
policycaps
,
POLICYDB_CAPABILITY_CGROUPSECLABEL
);
POLICYDB_CAPABILITY_CGROUPSECLABEL
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
selinux_policycap_names
);
i
++
)
pr_info
(
"SELinux: policy capability %s=%d
\n
"
,
selinux_policycap_names
[
i
],
ebitmap_get_bit
(
&
policydb
.
policycaps
,
i
));
ebitmap_for_each_positive_bit
(
&
policydb
.
policycaps
,
node
,
i
)
{
if
(
i
>=
ARRAY_SIZE
(
selinux_policycap_names
))
pr_info
(
"SELinux: unknown policy capability %u
\n
"
,
i
);
}
}
}
static
int
security_preserve_bools
(
struct
policydb
*
p
);
static
int
security_preserve_bools
(
struct
policydb
*
p
);
...
@@ -2031,9 +2054,11 @@ int security_load_policy(void *data, size_t len)
...
@@ -2031,9 +2054,11 @@ int security_load_policy(void *data, size_t len)
if
(
!
ss_initialized
)
{
if
(
!
ss_initialized
)
{
avtab_cache_init
();
avtab_cache_init
();
ebitmap_cache_init
();
rc
=
policydb_read
(
&
policydb
,
fp
);
rc
=
policydb_read
(
&
policydb
,
fp
);
if
(
rc
)
{
if
(
rc
)
{
avtab_cache_destroy
();
avtab_cache_destroy
();
ebitmap_cache_destroy
();
goto
out
;
goto
out
;
}
}
...
@@ -2044,6 +2069,7 @@ int security_load_policy(void *data, size_t len)
...
@@ -2044,6 +2069,7 @@ int security_load_policy(void *data, size_t len)
if
(
rc
)
{
if
(
rc
)
{
policydb_destroy
(
&
policydb
);
policydb_destroy
(
&
policydb
);
avtab_cache_destroy
();
avtab_cache_destroy
();
ebitmap_cache_destroy
();
goto
out
;
goto
out
;
}
}
...
@@ -2051,6 +2077,7 @@ int security_load_policy(void *data, size_t len)
...
@@ -2051,6 +2077,7 @@ int security_load_policy(void *data, size_t len)
if
(
rc
)
{
if
(
rc
)
{
policydb_destroy
(
&
policydb
);
policydb_destroy
(
&
policydb
);
avtab_cache_destroy
();
avtab_cache_destroy
();
ebitmap_cache_destroy
();
goto
out
;
goto
out
;
}
}
...
@@ -2209,6 +2236,87 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
...
@@ -2209,6 +2236,87 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
return
rc
;
return
rc
;
}
}
/**
* security_pkey_sid - Obtain the SID for a pkey.
* @subnet_prefix: Subnet Prefix
* @pkey_num: pkey number
* @out_sid: security identifier
*/
int
security_ib_pkey_sid
(
u64
subnet_prefix
,
u16
pkey_num
,
u32
*
out_sid
)
{
struct
ocontext
*
c
;
int
rc
=
0
;
read_lock
(
&
policy_rwlock
);
c
=
policydb
.
ocontexts
[
OCON_IBPKEY
];
while
(
c
)
{
if
(
c
->
u
.
ibpkey
.
low_pkey
<=
pkey_num
&&
c
->
u
.
ibpkey
.
high_pkey
>=
pkey_num
&&
c
->
u
.
ibpkey
.
subnet_prefix
==
subnet_prefix
)
break
;
c
=
c
->
next
;
}
if
(
c
)
{
if
(
!
c
->
sid
[
0
])
{
rc
=
sidtab_context_to_sid
(
&
sidtab
,
&
c
->
context
[
0
],
&
c
->
sid
[
0
]);
if
(
rc
)
goto
out
;
}
*
out_sid
=
c
->
sid
[
0
];
}
else
*
out_sid
=
SECINITSID_UNLABELED
;
out:
read_unlock
(
&
policy_rwlock
);
return
rc
;
}
/**
* security_ib_endport_sid - Obtain the SID for a subnet management interface.
* @dev_name: device name
* @port: port number
* @out_sid: security identifier
*/
int
security_ib_endport_sid
(
const
char
*
dev_name
,
u8
port_num
,
u32
*
out_sid
)
{
struct
ocontext
*
c
;
int
rc
=
0
;
read_lock
(
&
policy_rwlock
);
c
=
policydb
.
ocontexts
[
OCON_IBENDPORT
];
while
(
c
)
{
if
(
c
->
u
.
ibendport
.
port
==
port_num
&&
!
strncmp
(
c
->
u
.
ibendport
.
dev_name
,
dev_name
,
IB_DEVICE_NAME_MAX
))
break
;
c
=
c
->
next
;
}
if
(
c
)
{
if
(
!
c
->
sid
[
0
])
{
rc
=
sidtab_context_to_sid
(
&
sidtab
,
&
c
->
context
[
0
],
&
c
->
sid
[
0
]);
if
(
rc
)
goto
out
;
}
*
out_sid
=
c
->
sid
[
0
];
}
else
*
out_sid
=
SECINITSID_UNLABELED
;
out:
read_unlock
(
&
policy_rwlock
);
return
rc
;
}
/**
/**
* security_netif_sid - Obtain the SID for a network interface.
* security_netif_sid - Obtain the SID for a network interface.
* @name: interface name
* @name: interface name
...
...
security/selinux/ss/sidtab.c
浏览文件 @
5965453d
...
@@ -32,13 +32,11 @@ int sidtab_init(struct sidtab *s)
...
@@ -32,13 +32,11 @@ int sidtab_init(struct sidtab *s)
int
sidtab_insert
(
struct
sidtab
*
s
,
u32
sid
,
struct
context
*
context
)
int
sidtab_insert
(
struct
sidtab
*
s
,
u32
sid
,
struct
context
*
context
)
{
{
int
hvalue
,
rc
=
0
;
int
hvalue
;
struct
sidtab_node
*
prev
,
*
cur
,
*
newnode
;
struct
sidtab_node
*
prev
,
*
cur
,
*
newnode
;
if
(
!
s
)
{
if
(
!
s
)
rc
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
out
;
}
hvalue
=
SIDTAB_HASH
(
sid
);
hvalue
=
SIDTAB_HASH
(
sid
);
prev
=
NULL
;
prev
=
NULL
;
...
@@ -48,21 +46,17 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
...
@@ -48,21 +46,17 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
cur
=
cur
->
next
;
cur
=
cur
->
next
;
}
}
if
(
cur
&&
sid
==
cur
->
sid
)
{
if
(
cur
&&
sid
==
cur
->
sid
)
rc
=
-
EEXIST
;
return
-
EEXIST
;
goto
out
;
}
newnode
=
kmalloc
(
sizeof
(
*
newnode
),
GFP_ATOMIC
);
newnode
=
kmalloc
(
sizeof
(
*
newnode
),
GFP_ATOMIC
);
if
(
!
newnode
)
{
if
(
!
newnode
)
rc
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
out
;
}
newnode
->
sid
=
sid
;
newnode
->
sid
=
sid
;
if
(
context_cpy
(
&
newnode
->
context
,
context
))
{
if
(
context_cpy
(
&
newnode
->
context
,
context
))
{
kfree
(
newnode
);
kfree
(
newnode
);
rc
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
out
;
}
}
if
(
prev
)
{
if
(
prev
)
{
...
@@ -78,8 +72,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
...
@@ -78,8 +72,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
s
->
nel
++
;
s
->
nel
++
;
if
(
sid
>=
s
->
next_sid
)
if
(
sid
>=
s
->
next_sid
)
s
->
next_sid
=
sid
+
1
;
s
->
next_sid
=
sid
+
1
;
out:
return
0
;
return
rc
;
}
}
static
struct
context
*
sidtab_search_core
(
struct
sidtab
*
s
,
u32
sid
,
int
force
)
static
struct
context
*
sidtab_search_core
(
struct
sidtab
*
s
,
u32
sid
,
int
force
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录