Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
d93aca60
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
d93aca60
编写于
12月 13, 2013
作者:
J
James Morris
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.infradead.org/users/pcmoore/selinux_fixes
into for-linus
上级
54fb723c
c0828e50
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
165 addition
and
42 deletion
+165
-42
security/selinux/hooks.c
security/selinux/hooks.c
+112
-25
security/selinux/include/xfrm.h
security/selinux/include/xfrm.h
+5
-3
security/selinux/xfrm.c
security/selinux/xfrm.c
+48
-14
未找到文件。
security/selinux/hooks.c
浏览文件 @
d93aca60
...
...
@@ -53,6 +53,7 @@
#include <net/ip.h>
/* for local_port_range[] */
#include <net/sock.h>
#include <net/tcp.h>
/* struct or_callable used in sock_rcv_skb */
#include <net/inet_connection_sock.h>
#include <net/net_namespace.h>
#include <net/netlabel.h>
#include <linux/uaccess.h>
...
...
@@ -3828,7 +3829,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
u32
nlbl_sid
;
u32
nlbl_type
;
err
=
selinux_
skb_xfrm
_sid
(
skb
,
&
xfrm_sid
);
err
=
selinux_
xfrm_skb
_sid
(
skb
,
&
xfrm_sid
);
if
(
unlikely
(
err
))
return
-
EACCES
;
err
=
selinux_netlbl_skbuff_getsid
(
skb
,
family
,
&
nlbl_type
,
&
nlbl_sid
);
...
...
@@ -3846,6 +3847,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
return
0
;
}
/**
* selinux_conn_sid - Determine the child socket label for a connection
* @sk_sid: the parent socket's SID
* @skb_sid: the packet's SID
* @conn_sid: the resulting connection SID
*
* If @skb_sid is valid then the user:role:type information from @sk_sid is
* combined with the MLS information from @skb_sid in order to create
* @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
* of @sk_sid. Returns zero on success, negative values on failure.
*
*/
static
int
selinux_conn_sid
(
u32
sk_sid
,
u32
skb_sid
,
u32
*
conn_sid
)
{
int
err
=
0
;
if
(
skb_sid
!=
SECSID_NULL
)
err
=
security_sid_mls_copy
(
sk_sid
,
skb_sid
,
conn_sid
);
else
*
conn_sid
=
sk_sid
;
return
err
;
}
/* socket security operations */
static
int
socket_sockcreate_sid
(
const
struct
task_security_struct
*
tsec
,
...
...
@@ -4452,7 +4477,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
int
err
;
u16
family
=
sk
->
sk_family
;
u32
new
sid
;
u32
conn
sid
;
u32
peersid
;
/* handle mapped IPv4 packets arriving via IPv6 sockets */
...
...
@@ -4462,16 +4487,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
err
=
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peersid
);
if
(
err
)
return
err
;
if
(
peersid
==
SECSID_NULL
)
{
req
->
secid
=
sksec
->
sid
;
req
->
peer_secid
=
SECSID_NULL
;
}
else
{
err
=
security_sid_mls_copy
(
sksec
->
sid
,
peersid
,
&
newsid
);
if
(
err
)
return
err
;
req
->
secid
=
newsid
;
req
->
peer_secid
=
peersid
;
}
err
=
selinux_conn_sid
(
sksec
->
sid
,
peersid
,
&
connsid
);
if
(
err
)
return
err
;
req
->
secid
=
connsid
;
req
->
peer_secid
=
peersid
;
return
selinux_netlbl_inet_conn_request
(
req
,
family
);
}
...
...
@@ -4731,6 +4751,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
static
unsigned
int
selinux_ip_output
(
struct
sk_buff
*
skb
,
u16
family
)
{
struct
sock
*
sk
;
u32
sid
;
if
(
!
netlbl_enabled
())
...
...
@@ -4739,8 +4760,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
/* we do this in the LOCAL_OUT path and not the POST_ROUTING path
* because we want to make sure we apply the necessary labeling
* before IPsec is applied so we can leverage AH protection */
if
(
skb
->
sk
)
{
struct
sk_security_struct
*
sksec
=
skb
->
sk
->
sk_security
;
sk
=
skb
->
sk
;
if
(
sk
)
{
struct
sk_security_struct
*
sksec
;
if
(
sk
->
sk_state
==
TCP_LISTEN
)
/* if the socket is the listening state then this
* packet is a SYN-ACK packet which means it needs to
* be labeled based on the connection/request_sock and
* not the parent socket. unfortunately, we can't
* lookup the request_sock yet as it isn't queued on
* the parent socket until after the SYN-ACK is sent.
* the "solution" is to simply pass the packet as-is
* as any IP option based labeling should be copied
* from the initial connection request (in the IP
* layer). it is far from ideal, but until we get a
* security label in the packet itself this is the
* best we can do. */
return
NF_ACCEPT
;
/* standard practice, label using the parent socket */
sksec
=
sk
->
sk_security
;
sid
=
sksec
->
sid
;
}
else
sid
=
SECINITSID_KERNEL
;
...
...
@@ -4810,27 +4850,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
* as fast and as clean as possible. */
if
(
!
selinux_policycap_netpeer
)
return
selinux_ip_postroute_compat
(
skb
,
ifindex
,
family
);
secmark_active
=
selinux_secmark_enabled
();
peerlbl_active
=
selinux_peerlbl_enabled
();
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
NF_ACCEPT
;
sk
=
skb
->
sk
;
#ifdef CONFIG_XFRM
/* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
* packet transformation so allow the packet to pass without any checks
* since we'll have another chance to perform access control checks
* when the packet is on it's final way out.
* NOTE: there appear to be some IPv6 multicast cases where skb->dst
* is NULL, in this case go ahead and apply access control. */
if
(
skb_dst
(
skb
)
!=
NULL
&&
skb_dst
(
skb
)
->
xfrm
!=
NULL
)
* is NULL, in this case go ahead and apply access control.
* NOTE: if this is a local socket (skb->sk != NULL) that is in the
* TCP listening state we cannot wait until the XFRM processing
* is done as we will miss out on the SA label if we do;
* unfortunately, this means more work, but it is only once per
* connection. */
if
(
skb_dst
(
skb
)
!=
NULL
&&
skb_dst
(
skb
)
->
xfrm
!=
NULL
&&
!
(
sk
!=
NULL
&&
sk
->
sk_state
==
TCP_LISTEN
))
return
NF_ACCEPT
;
#endif
secmark_active
=
selinux_secmark_enabled
();
peerlbl_active
=
selinux_peerlbl_enabled
();
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
NF_ACCEPT
;
/* if the packet is being forwarded then get the peer label from the
* packet itself; otherwise check to see if it is from a local
* application or the kernel, if from an application get the peer label
* from the sending socket, otherwise use the kernel's sid */
sk
=
skb
->
sk
;
if
(
sk
==
NULL
)
{
/* Without an associated socket the packet is either coming
* from the kernel or it is being forwarded; check the packet
* to determine which and if the packet is being forwarded
* query the packet directly to determine the security label. */
if
(
skb
->
skb_iif
)
{
secmark_perm
=
PACKET__FORWARD_OUT
;
if
(
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
))
...
...
@@ -4839,7 +4888,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
secmark_perm
=
PACKET__SEND
;
peer_sid
=
SECINITSID_KERNEL
;
}
}
else
if
(
sk
->
sk_state
==
TCP_LISTEN
)
{
/* Locally generated packet but the associated socket is in the
* listening state which means this is a SYN-ACK packet. In
* this particular case the correct security label is assigned
* to the connection/request_sock but unfortunately we can't
* query the request_sock as it isn't queued on the parent
* socket until after the SYN-ACK packet is sent; the only
* viable choice is to regenerate the label like we do in
* selinux_inet_conn_request(). See also selinux_ip_output()
* for similar problems. */
u32
skb_sid
;
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
if
(
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
skb_sid
))
return
NF_DROP
;
/* At this point, if the returned skb peerlbl is SECSID_NULL
* and the packet has been through at least one XFRM
* transformation then we must be dealing with the "final"
* form of labeled IPsec packet; since we've already applied
* all of our access controls on this packet we can safely
* pass the packet. */
if
(
skb_sid
==
SECSID_NULL
)
{
switch
(
family
)
{
case
PF_INET
:
if
(
IPCB
(
skb
)
->
flags
&
IPSKB_XFRM_TRANSFORMED
)
return
NF_ACCEPT
;
break
;
case
PF_INET6
:
if
(
IP6CB
(
skb
)
->
flags
&
IP6SKB_XFRM_TRANSFORMED
)
return
NF_ACCEPT
;
default:
return
NF_DROP_ERR
(
-
ECONNREFUSED
);
}
}
if
(
selinux_conn_sid
(
sksec
->
sid
,
skb_sid
,
&
peer_sid
))
return
NF_DROP
;
secmark_perm
=
PACKET__SEND
;
}
else
{
/* Locally generated packet, fetch the security label from the
* associated socket. */
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
peer_sid
=
sksec
->
sid
;
secmark_perm
=
PACKET__SEND
;
...
...
security/selinux/include/xfrm.h
浏览文件 @
d93aca60
...
...
@@ -39,6 +39,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
int
selinux_xfrm_postroute_last
(
u32
sk_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
,
u8
proto
);
int
selinux_xfrm_decode_session
(
struct
sk_buff
*
skb
,
u32
*
sid
,
int
ckall
);
int
selinux_xfrm_skb_sid
(
struct
sk_buff
*
skb
,
u32
*
sid
);
static
inline
void
selinux_xfrm_notify_policyload
(
void
)
{
...
...
@@ -79,11 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
static
inline
void
selinux_xfrm_notify_policyload
(
void
)
{
}
#endif
static
inline
int
selinux_
skb_xfrm
_sid
(
struct
sk_buff
*
skb
,
u32
*
sid
)
static
inline
int
selinux_
xfrm_skb
_sid
(
struct
sk_buff
*
skb
,
u32
*
sid
)
{
return
selinux_xfrm_decode_session
(
skb
,
sid
,
0
);
*
sid
=
SECSID_NULL
;
return
0
;
}
#endif
#endif
/* _SELINUX_XFRM_H_ */
security/selinux/xfrm.c
浏览文件 @
d93aca60
...
...
@@ -209,19 +209,26 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
NULL
)
?
0
:
1
);
}
/*
* LSM hook implementation that checks and/or returns the xfrm sid for the
* incoming packet.
*/
int
selinux_xfrm_decode_session
(
struct
sk_buff
*
skb
,
u32
*
sid
,
int
ckall
)
static
u32
selinux_xfrm_skb_sid_egress
(
struct
sk_buff
*
skb
)
{
u32
sid_session
=
SECSID_NULL
;
struct
sec_path
*
sp
;
struct
dst_entry
*
dst
=
skb_dst
(
skb
)
;
struct
xfrm_state
*
x
;
if
(
skb
==
NULL
)
goto
out
;
if
(
dst
==
NULL
)
return
SECSID_NULL
;
x
=
dst
->
xfrm
;
if
(
x
==
NULL
||
!
selinux_authorizable_xfrm
(
x
))
return
SECSID_NULL
;
return
x
->
security
->
ctx_sid
;
}
static
int
selinux_xfrm_skb_sid_ingress
(
struct
sk_buff
*
skb
,
u32
*
sid
,
int
ckall
)
{
u32
sid_session
=
SECSID_NULL
;
struct
sec_path
*
sp
=
skb
->
sp
;
sp
=
skb
->
sp
;
if
(
sp
)
{
int
i
;
...
...
@@ -247,6 +254,30 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
return
0
;
}
/*
* LSM hook implementation that checks and/or returns the xfrm sid for the
* incoming packet.
*/
int
selinux_xfrm_decode_session
(
struct
sk_buff
*
skb
,
u32
*
sid
,
int
ckall
)
{
if
(
skb
==
NULL
)
{
*
sid
=
SECSID_NULL
;
return
0
;
}
return
selinux_xfrm_skb_sid_ingress
(
skb
,
sid
,
ckall
);
}
int
selinux_xfrm_skb_sid
(
struct
sk_buff
*
skb
,
u32
*
sid
)
{
int
rc
;
rc
=
selinux_xfrm_skb_sid_ingress
(
skb
,
sid
,
0
);
if
(
rc
==
0
&&
*
sid
==
SECSID_NULL
)
*
sid
=
selinux_xfrm_skb_sid_egress
(
skb
);
return
rc
;
}
/*
* LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
*/
...
...
@@ -327,19 +358,22 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
return
rc
;
ctx
=
kmalloc
(
sizeof
(
*
ctx
)
+
str_len
,
GFP_ATOMIC
);
if
(
!
ctx
)
return
-
ENOMEM
;
if
(
!
ctx
)
{
rc
=
-
ENOMEM
;
goto
out
;
}
ctx
->
ctx_doi
=
XFRM_SC_DOI_LSM
;
ctx
->
ctx_alg
=
XFRM_SC_ALG_SELINUX
;
ctx
->
ctx_sid
=
secid
;
ctx
->
ctx_len
=
str_len
;
memcpy
(
ctx
->
ctx_str
,
ctx_str
,
str_len
);
kfree
(
ctx_str
);
x
->
security
=
ctx
;
atomic_inc
(
&
selinux_xfrm_refcount
);
return
0
;
out:
kfree
(
ctx_str
);
return
rc
;
}
/*
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录