Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
6f799c97
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
6f799c97
编写于
10月 22, 2013
作者:
J
James Morris
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.infradead.org/users/pcmoore/selinux
into ra-next
上级
eb8948a0
42d64e1a
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
450 addition
and
400 deletion
+450
-400
include/linux/security.h
include/linux/security.h
+18
-8
security/capability.c
security/capability.c
+11
-4
security/security.c
security/security.c
+4
-9
security/selinux/hooks.c
security/selinux/hooks.c
+94
-52
security/selinux/include/objsec.h
security/selinux/include/objsec.h
+2
-2
security/selinux/include/security.h
security/selinux/include/security.h
+8
-5
security/selinux/include/xfrm.h
security/selinux/include/xfrm.h
+19
-26
security/selinux/netlabel.c
security/selinux/netlabel.c
+2
-4
security/selinux/netnode.c
security/selinux/netnode.c
+2
-0
security/selinux/selinuxfs.c
security/selinux/selinuxfs.c
+3
-1
security/selinux/ss/ebitmap.c
security/selinux/ss/ebitmap.c
+18
-2
security/selinux/ss/ebitmap.h
security/selinux/ss/ebitmap.h
+8
-2
security/selinux/ss/mls.c
security/selinux/ss/mls.c
+7
-15
security/selinux/ss/mls_types.h
security/selinux/ss/mls_types.h
+1
-1
security/selinux/ss/policydb.c
security/selinux/ss/policydb.c
+1
-2
security/selinux/ss/services.c
security/selinux/ss/services.c
+50
-16
security/selinux/xfrm.c
security/selinux/xfrm.c
+202
-251
未找到文件。
include/linux/security.h
浏览文件 @
6f799c97
...
...
@@ -1052,17 +1052,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @xfrm_policy_delete_security:
* @ctx contains the xfrm_sec_ctx.
* Authorize deletion of xp->security.
* @xfrm_state_alloc
_security
:
* @xfrm_state_alloc:
* @x contains the xfrm_state being added to the Security Association
* Database by the XFRM system.
* @sec_ctx contains the security context information being provided by
* the user-level SA generation program (e.g., setkey or racoon).
* @secid contains the secid from which to take the mls portion of the context.
* Allocate a security structure to the x->security field; the security
* field is initialized to NULL when the xfrm_state is allocated. Set the
* context to correspond to either sec_ctx or polsec, with the mls portion
* taken from secid in the latter case.
* Return 0 if operation was successful (memory to allocate, legal context).
* context to correspond to sec_ctx. Return 0 if operation was successful
* (memory to allocate, legal context).
* @xfrm_state_alloc_acquire:
* @x contains the xfrm_state being added to the Security Association
* Database by the XFRM system.
* @polsec contains the policy's security context.
* @secid contains the secid from which to take the mls portion of the
* context.
* Allocate a security structure to the x->security field; the security
* field is initialized to NULL when the xfrm_state is allocated. Set the
* context to correspond to secid. Return 0 if operation was successful
* (memory to allocate, legal context).
* @xfrm_state_free_security:
* @x contains the xfrm_state.
* Deallocate x->security.
...
...
@@ -1679,9 +1687,11 @@ struct security_operations {
int
(
*
xfrm_policy_clone_security
)
(
struct
xfrm_sec_ctx
*
old_ctx
,
struct
xfrm_sec_ctx
**
new_ctx
);
void
(
*
xfrm_policy_free_security
)
(
struct
xfrm_sec_ctx
*
ctx
);
int
(
*
xfrm_policy_delete_security
)
(
struct
xfrm_sec_ctx
*
ctx
);
int
(
*
xfrm_state_alloc_security
)
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
sec_ctx
,
u32
secid
);
int
(
*
xfrm_state_alloc
)
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
sec_ctx
);
int
(
*
xfrm_state_alloc_acquire
)
(
struct
xfrm_state
*
x
,
struct
xfrm_sec_ctx
*
polsec
,
u32
secid
);
void
(
*
xfrm_state_free_security
)
(
struct
xfrm_state
*
x
);
int
(
*
xfrm_state_delete_security
)
(
struct
xfrm_state
*
x
);
int
(
*
xfrm_policy_lookup
)
(
struct
xfrm_sec_ctx
*
ctx
,
u32
fl_secid
,
u8
dir
);
...
...
security/capability.c
浏览文件 @
6f799c97
...
...
@@ -777,9 +777,15 @@ static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
return
0
;
}
static
int
cap_xfrm_state_alloc_security
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
sec_ctx
,
u32
secid
)
static
int
cap_xfrm_state_alloc
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
sec_ctx
)
{
return
0
;
}
static
int
cap_xfrm_state_alloc_acquire
(
struct
xfrm_state
*
x
,
struct
xfrm_sec_ctx
*
polsec
,
u32
secid
)
{
return
0
;
}
...
...
@@ -1101,7 +1107,8 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null
(
ops
,
xfrm_policy_clone_security
);
set_to_cap_if_null
(
ops
,
xfrm_policy_free_security
);
set_to_cap_if_null
(
ops
,
xfrm_policy_delete_security
);
set_to_cap_if_null
(
ops
,
xfrm_state_alloc_security
);
set_to_cap_if_null
(
ops
,
xfrm_state_alloc
);
set_to_cap_if_null
(
ops
,
xfrm_state_alloc_acquire
);
set_to_cap_if_null
(
ops
,
xfrm_state_free_security
);
set_to_cap_if_null
(
ops
,
xfrm_state_delete_security
);
set_to_cap_if_null
(
ops
,
xfrm_policy_lookup
);
...
...
security/security.c
浏览文件 @
6f799c97
...
...
@@ -1340,22 +1340,17 @@ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
return
security_ops
->
xfrm_policy_delete_security
(
ctx
);
}
int
security_xfrm_state_alloc
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
sec_ctx
)
int
security_xfrm_state_alloc
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
sec_ctx
)
{
return
security_ops
->
xfrm_state_alloc
_security
(
x
,
sec_ctx
,
0
);
return
security_ops
->
xfrm_state_alloc
(
x
,
sec_ctx
);
}
EXPORT_SYMBOL
(
security_xfrm_state_alloc
);
int
security_xfrm_state_alloc_acquire
(
struct
xfrm_state
*
x
,
struct
xfrm_sec_ctx
*
polsec
,
u32
secid
)
{
if
(
!
polsec
)
return
0
;
/*
* We want the context to be taken from secid which is usually
* from the sock.
*/
return
security_ops
->
xfrm_state_alloc_security
(
x
,
NULL
,
secid
);
return
security_ops
->
xfrm_state_alloc_acquire
(
x
,
polsec
,
secid
);
}
int
security_xfrm_state_delete
(
struct
xfrm_state
*
x
)
...
...
security/selinux/hooks.c
浏览文件 @
6f799c97
...
...
@@ -95,7 +95,9 @@
#include "audit.h"
#include "avc_ss.h"
#define NUM_SEL_MNT_OPTS 5
#define SB_TYPE_FMT "%s%s%s"
#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
extern
struct
security_operations
*
security_ops
;
...
...
@@ -139,12 +141,28 @@ static struct kmem_cache *sel_inode_cache;
* This function checks the SECMARK reference counter to see if any SECMARK
* targets are currently configured, if the reference counter is greater than
* zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
* enabled, false (0) if SECMARK is disabled.
* enabled, false (0) if SECMARK is disabled. If the always_check_network
* policy capability is enabled, SECMARK is always considered enabled.
*
*/
static
int
selinux_secmark_enabled
(
void
)
{
return
(
atomic_read
(
&
selinux_secmark_refcount
)
>
0
);
return
(
selinux_policycap_alwaysnetwork
||
atomic_read
(
&
selinux_secmark_refcount
));
}
/**
* selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
*
* Description:
* This function checks if NetLabel or labeled IPSEC is enabled. Returns true
* (1) if any are enabled or false (0) if neither are enabled. If the
* always_check_network policy capability is enabled, peer labeling
* is always considered enabled.
*
*/
static
int
selinux_peerlbl_enabled
(
void
)
{
return
(
selinux_policycap_alwaysnetwork
||
netlbl_enabled
()
||
selinux_xfrm_enabled
());
}
/*
...
...
@@ -309,8 +327,11 @@ enum {
Opt_defcontext
=
3
,
Opt_rootcontext
=
4
,
Opt_labelsupport
=
5
,
Opt_nextmntopt
=
6
,
};
#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
static
const
match_table_t
tokens
=
{
{
Opt_context
,
CONTEXT_STR
"%s"
},
{
Opt_fscontext
,
FSCONTEXT_STR
"%s"
},
...
...
@@ -355,6 +376,29 @@ static int may_context_mount_inode_relabel(u32 sid,
return
rc
;
}
static
int
selinux_is_sblabel_mnt
(
struct
super_block
*
sb
)
{
struct
superblock_security_struct
*
sbsec
=
sb
->
s_security
;
if
(
sbsec
->
behavior
==
SECURITY_FS_USE_XATTR
||
sbsec
->
behavior
==
SECURITY_FS_USE_TRANS
||
sbsec
->
behavior
==
SECURITY_FS_USE_TASK
)
return
1
;
/* Special handling for sysfs. Is genfs but also has setxattr handler*/
if
(
strncmp
(
sb
->
s_type
->
name
,
"sysfs"
,
sizeof
(
"sysfs"
))
==
0
)
return
1
;
/*
* Special handling for rootfs. Is genfs but supports
* setting SELinux context on in-core inodes.
*/
if
(
strncmp
(
sb
->
s_type
->
name
,
"rootfs"
,
sizeof
(
"rootfs"
))
==
0
)
return
1
;
return
0
;
}
static
int
sb_finish_set_opts
(
struct
super_block
*
sb
)
{
struct
superblock_security_struct
*
sbsec
=
sb
->
s_security
;
...
...
@@ -369,8 +413,8 @@ static int sb_finish_set_opts(struct super_block *sb)
the first boot of the SELinux kernel before we have
assigned xattr values to the filesystem. */
if
(
!
root_inode
->
i_op
->
getxattr
)
{
printk
(
KERN_WARNING
"SELinux: (dev %s, type
%s
) has no "
"xattr support
\n
"
,
sb
->
s_id
,
sb
->
s_type
->
name
);
printk
(
KERN_WARNING
"SELinux: (dev %s, type
"
SB_TYPE_FMT
"
) has no "
"xattr support
\n
"
,
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
)
);
rc
=
-
EOPNOTSUPP
;
goto
out
;
}
...
...
@@ -378,35 +422,27 @@ static int sb_finish_set_opts(struct super_block *sb)
if
(
rc
<
0
&&
rc
!=
-
ENODATA
)
{
if
(
rc
==
-
EOPNOTSUPP
)
printk
(
KERN_WARNING
"SELinux: (dev %s, type "
"%s
) has no security xattr handler
\n
"
,
sb
->
s_id
,
sb
->
s_type
->
name
);
SB_TYPE_FMT
"
) has no security xattr handler
\n
"
,
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
)
);
else
printk
(
KERN_WARNING
"SELinux: (dev %s, type "
"%s
) getxattr errno %d
\n
"
,
sb
->
s_id
,
sb
->
s_type
->
name
,
-
rc
);
SB_TYPE_FMT
"
) getxattr errno %d
\n
"
,
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
)
,
-
rc
);
goto
out
;
}
}
sbsec
->
flags
|=
(
SE_SBINITIALIZED
|
SE_SBLABELSUPP
);
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
);
printk
(
KERN_ERR
"SELinux: initialized (dev %s, type
"
SB_TYPE_FMT
"
), unknown behavior
\n
"
,
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
)
);
else
printk
(
KERN_DEBUG
"SELinux: initialized (dev %s, type
%s
), %s
\n
"
,
sb
->
s_id
,
sb
->
s_type
->
name
,
printk
(
KERN_DEBUG
"SELinux: initialized (dev %s, type
"
SB_TYPE_FMT
"
), %s
\n
"
,
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
)
,
labeling_behaviors
[
sbsec
->
behavior
-
1
]);
if
(
sbsec
->
behavior
==
SECURITY_FS_USE_GENFS
||
sbsec
->
behavior
==
SECURITY_FS_USE_MNTPOINT
||
sbsec
->
behavior
==
SECURITY_FS_USE_NONE
||
sbsec
->
behavior
>
ARRAY_SIZE
(
labeling_behaviors
))
sbsec
->
flags
&=
~
SE_SBLABELSUPP
;
/* Special handling for sysfs. Is genfs but also has setxattr handler*/
if
(
strncmp
(
sb
->
s_type
->
name
,
"sysfs"
,
sizeof
(
"sysfs"
))
==
0
)
sbsec
->
flags
|=
SE_SBLABELSUPP
;
sbsec
->
flags
|=
SE_SBINITIALIZED
;
if
(
selinux_is_sblabel_mnt
(
sb
))
sbsec
->
flags
|=
SBLABEL_MNT
;
/* Initialize the root inode. */
rc
=
inode_doinit_with_dentry
(
root_inode
,
root
);
...
...
@@ -460,15 +496,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
if
(
!
ss_initialized
)
return
-
EINVAL
;
/* make sure we always check enough bits to cover the mask */
BUILD_BUG_ON
(
SE_MNTMASK
>=
(
1
<<
NUM_SEL_MNT_OPTS
));
tmp
=
sbsec
->
flags
&
SE_MNTMASK
;
/* count the number of mount options for this sb */
for
(
i
=
0
;
i
<
8
;
i
++
)
{
for
(
i
=
0
;
i
<
NUM_SEL_MNT_OPTS
;
i
++
)
{
if
(
tmp
&
0x01
)
opts
->
num_mnt_opts
++
;
tmp
>>=
1
;
}
/* Check if the Label support flag is set */
if
(
sbsec
->
flags
&
S
E_SBLABELSUPP
)
if
(
sbsec
->
flags
&
S
BLABEL_MNT
)
opts
->
num_mnt_opts
++
;
opts
->
mnt_opts
=
kcalloc
(
opts
->
num_mnt_opts
,
sizeof
(
char
*
),
GFP_ATOMIC
);
...
...
@@ -515,9 +554,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
opts
->
mnt_opts
[
i
]
=
context
;
opts
->
mnt_opts_flags
[
i
++
]
=
ROOTCONTEXT_MNT
;
}
if
(
sbsec
->
flags
&
S
E_SBLABELSUPP
)
{
if
(
sbsec
->
flags
&
S
BLABEL_MNT
)
{
opts
->
mnt_opts
[
i
]
=
NULL
;
opts
->
mnt_opts_flags
[
i
++
]
=
S
E_SBLABELSUPP
;
opts
->
mnt_opts_flags
[
i
++
]
=
S
BLABEL_MNT
;
}
BUG_ON
(
i
!=
opts
->
num_mnt_opts
);
...
...
@@ -561,7 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb,
const
struct
cred
*
cred
=
current_cred
();
int
rc
=
0
,
i
;
struct
superblock_security_struct
*
sbsec
=
sb
->
s_security
;
const
char
*
name
=
sb
->
s_type
->
name
;
struct
inode
*
inode
=
sbsec
->
sb
->
s_root
->
d_inode
;
struct
inode_security_struct
*
root_isec
=
inode
->
i_security
;
u32
fscontext_sid
=
0
,
context_sid
=
0
,
rootcontext_sid
=
0
;
...
...
@@ -614,14 +652,14 @@ static int selinux_set_mnt_opts(struct super_block *sb,
for
(
i
=
0
;
i
<
num_opts
;
i
++
)
{
u32
sid
;
if
(
flags
[
i
]
==
S
E_SBLABELSUPP
)
if
(
flags
[
i
]
==
S
BLABEL_MNT
)
continue
;
rc
=
security_context_to_sid
(
mount_options
[
i
],
strlen
(
mount_options
[
i
]),
&
sid
);
if
(
rc
)
{
printk
(
KERN_WARNING
"SELinux: security_context_to_sid"
"(%s) failed for (dev %s, type
%s
) errno=%d
\n
"
,
mount_options
[
i
],
sb
->
s_id
,
name
,
rc
);
"(%s) failed for (dev %s, type
"
SB_TYPE_FMT
"
) errno=%d
\n
"
,
mount_options
[
i
],
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
)
,
rc
);
goto
out
;
}
switch
(
flags
[
i
])
{
...
...
@@ -685,9 +723,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
* Determine the labeling behavior to use for this
* filesystem type.
*/
rc
=
security_fs_use
((
sbsec
->
flags
&
SE_SBPROC
)
?
"proc"
:
sb
->
s_type
->
name
,
&
sbsec
->
behavior
,
&
sbsec
->
sid
);
rc
=
security_fs_use
(
sb
);
if
(
rc
)
{
printk
(
KERN_WARNING
"%s: security_fs_use(%s) returned %d
\n
"
,
...
...
@@ -770,7 +806,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
out_double_mount:
rc
=
-
EINVAL
;
printk
(
KERN_WARNING
"SELinux: mount invalid. Same superblock, different "
"security settings for (dev %s, type %s)
\n
"
,
sb
->
s_id
,
name
);
"security settings for (dev %s, type "
SB_TYPE_FMT
")
\n
"
,
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
));
goto
out
;
}
...
...
@@ -1037,7 +1074,7 @@ static void selinux_write_opts(struct seq_file *m,
case
DEFCONTEXT_MNT
:
prefix
=
DEFCONTEXT_STR
;
break
;
case
S
E_SBLABELSUPP
:
case
S
BLABEL_MNT
:
seq_putc
(
m
,
','
);
seq_puts
(
m
,
LABELSUPP_STR
);
continue
;
...
...
@@ -1650,7 +1687,7 @@ static int may_create(struct inode *dir,
if
(
rc
)
return
rc
;
if
(
!
newsid
||
!
(
sbsec
->
flags
&
S
E_SBLABELSUPP
))
{
if
(
!
newsid
||
!
(
sbsec
->
flags
&
S
BLABEL_MNT
))
{
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
tclass
,
&
dentry
->
d_name
,
&
newsid
);
if
(
rc
)
...
...
@@ -2438,14 +2475,14 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
u32
sid
;
size_t
len
;
if
(
flags
[
i
]
==
S
E_SBLABELSUPP
)
if
(
flags
[
i
]
==
S
BLABEL_MNT
)
continue
;
len
=
strlen
(
mount_options
[
i
]);
rc
=
security_context_to_sid
(
mount_options
[
i
],
len
,
&
sid
);
if
(
rc
)
{
printk
(
KERN_WARNING
"SELinux: security_context_to_sid"
"(%s) failed for (dev %s, type
%s
) errno=%d
\n
"
,
mount_options
[
i
],
sb
->
s_id
,
sb
->
s_type
->
name
,
rc
);
"(%s) failed for (dev %s, type
"
SB_TYPE_FMT
"
) errno=%d
\n
"
,
mount_options
[
i
],
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
)
,
rc
);
goto
out_free_opts
;
}
rc
=
-
EINVAL
;
...
...
@@ -2483,8 +2520,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
return
rc
;
out_bad_option:
printk
(
KERN_WARNING
"SELinux: unable to change security options "
"during remount (dev %s, type
=%s
)
\n
"
,
sb
->
s_id
,
sb
->
s_type
->
name
);
"during remount (dev %s, type
"
SB_TYPE_FMT
"
)
\n
"
,
sb
->
s_id
,
SB_TYPE_ARGS
(
sb
)
);
goto
out_free_opts
;
}
...
...
@@ -2607,7 +2644,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
if
((
sbsec
->
flags
&
SE_SBINITIALIZED
)
&&
(
sbsec
->
behavior
==
SECURITY_FS_USE_MNTPOINT
))
newsid
=
sbsec
->
mntpoint_sid
;
else
if
(
!
newsid
||
!
(
sbsec
->
flags
&
S
E_SBLABELSUPP
))
{
else
if
(
!
newsid
||
!
(
sbsec
->
flags
&
S
BLABEL_MNT
))
{
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
inode_mode_to_security_class
(
inode
->
i_mode
),
qstr
,
&
newsid
);
...
...
@@ -2629,7 +2666,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
isec
->
initialized
=
1
;
}
if
(
!
ss_initialized
||
!
(
sbsec
->
flags
&
S
E_SBLABELSUPP
))
if
(
!
ss_initialized
||
!
(
sbsec
->
flags
&
S
BLABEL_MNT
))
return
-
EOPNOTSUPP
;
if
(
name
)
...
...
@@ -2831,7 +2868,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
return
selinux_inode_setotherxattr
(
dentry
,
name
);
sbsec
=
inode
->
i_sb
->
s_security
;
if
(
!
(
sbsec
->
flags
&
S
E_SBLABELSUPP
))
if
(
!
(
sbsec
->
flags
&
S
BLABEL_MNT
))
return
-
EOPNOTSUPP
;
if
(
!
inode_owner_or_capable
(
inode
))
...
...
@@ -3792,8 +3829,12 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
u32
nlbl_sid
;
u32
nlbl_type
;
selinux_skb_xfrm_sid
(
skb
,
&
xfrm_sid
);
selinux_netlbl_skbuff_getsid
(
skb
,
family
,
&
nlbl_type
,
&
nlbl_sid
);
err
=
selinux_skb_xfrm_sid
(
skb
,
&
xfrm_sid
);
if
(
unlikely
(
err
))
return
-
EACCES
;
err
=
selinux_netlbl_skbuff_getsid
(
skb
,
family
,
&
nlbl_type
,
&
nlbl_sid
);
if
(
unlikely
(
err
))
return
-
EACCES
;
err
=
security_net_peersid_resolve
(
nlbl_sid
,
nlbl_type
,
xfrm_sid
,
sid
);
if
(
unlikely
(
err
))
{
...
...
@@ -4247,7 +4288,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
return
selinux_sock_rcv_skb_compat
(
sk
,
skb
,
family
);
secmark_active
=
selinux_secmark_enabled
();
peerlbl_active
=
netlbl_enabled
()
||
selinux_xfrm
_enabled
();
peerlbl_active
=
selinux_peerlbl
_enabled
();
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
0
;
...
...
@@ -4629,7 +4670,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
secmark_active
=
selinux_secmark_enabled
();
netlbl_active
=
netlbl_enabled
();
peerlbl_active
=
netlbl_active
||
selinux_xfrm
_enabled
();
peerlbl_active
=
selinux_peerlbl
_enabled
();
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
NF_ACCEPT
;
...
...
@@ -4781,7 +4822,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
return
NF_ACCEPT
;
#endif
secmark_active
=
selinux_secmark_enabled
();
peerlbl_active
=
netlbl_enabled
()
||
selinux_xfrm
_enabled
();
peerlbl_active
=
selinux_peerlbl
_enabled
();
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
NF_ACCEPT
;
...
...
@@ -5785,7 +5826,8 @@ static struct security_operations selinux_ops = {
.
xfrm_policy_clone_security
=
selinux_xfrm_policy_clone
,
.
xfrm_policy_free_security
=
selinux_xfrm_policy_free
,
.
xfrm_policy_delete_security
=
selinux_xfrm_policy_delete
,
.
xfrm_state_alloc_security
=
selinux_xfrm_state_alloc
,
.
xfrm_state_alloc
=
selinux_xfrm_state_alloc
,
.
xfrm_state_alloc_acquire
=
selinux_xfrm_state_alloc_acquire
,
.
xfrm_state_free_security
=
selinux_xfrm_state_free
,
.
xfrm_state_delete_security
=
selinux_xfrm_state_delete
,
.
xfrm_policy_lookup
=
selinux_xfrm_policy_lookup
,
...
...
security/selinux/include/objsec.h
浏览文件 @
6f799c97
...
...
@@ -58,8 +58,8 @@ struct superblock_security_struct {
u32
sid
;
/* SID of file system superblock */
u32
def_sid
;
/* default SID for labeling */
u32
mntpoint_sid
;
/* SECURITY_FS_USE_MNTPOINT context for files */
unsigned
int
behavior
;
/* labeling behavior */
unsigned
char
flags
;
/* which mount options were specified */
unsigned
short
behavior
;
/* labeling behavior */
unsigned
short
flags
;
/* which mount options were specified */
struct
mutex
lock
;
struct
list_head
isec_head
;
spinlock_t
isec_lock
;
...
...
security/selinux/include/security.h
浏览文件 @
6f799c97
...
...
@@ -45,14 +45,15 @@
/* Mask for just the mount related flags */
#define SE_MNTMASK 0x0f
/* Super block security struct flags for mount options */
/* BE CAREFUL, these need to be the low order bits for selinux_get_mnt_opts */
#define CONTEXT_MNT 0x01
#define FSCONTEXT_MNT 0x02
#define ROOTCONTEXT_MNT 0x04
#define DEFCONTEXT_MNT 0x08
#define SBLABEL_MNT 0x10
/* Non-mount related flags */
#define SE_SBINITIALIZED 0x10
#define SE_SBPROC 0x20
#define SE_SBLABELSUPP 0x40
#define SE_SBINITIALIZED 0x0100
#define SE_SBPROC 0x0200
#define CONTEXT_STR "context="
#define FSCONTEXT_STR "fscontext="
...
...
@@ -68,12 +69,15 @@ extern int selinux_enabled;
enum
{
POLICYDB_CAPABILITY_NETPEER
,
POLICYDB_CAPABILITY_OPENPERM
,
POLICYDB_CAPABILITY_REDHAT1
,
POLICYDB_CAPABILITY_ALWAYSNETWORK
,
__POLICYDB_CAPABILITY_MAX
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
extern
int
selinux_policycap_netpeer
;
extern
int
selinux_policycap_openperm
;
extern
int
selinux_policycap_alwaysnetwork
;
/*
* type_datum properties
...
...
@@ -172,8 +176,7 @@ int security_get_allow_unknown(void);
#define SECURITY_FS_USE_NATIVE 7
/* use native label support */
#define SECURITY_FS_USE_MAX 7
/* Highest SECURITY_FS_USE_XXX */
int
security_fs_use
(
const
char
*
fstype
,
unsigned
int
*
behavior
,
u32
*
sid
);
int
security_fs_use
(
struct
super_block
*
sb
);
int
security_genfs_sid
(
const
char
*
fstype
,
char
*
name
,
u16
sclass
,
u32
*
sid
);
...
...
security/selinux/include/xfrm.h
浏览文件 @
6f799c97
...
...
@@ -10,29 +10,21 @@
#include <net/flow.h>
int
selinux_xfrm_policy_alloc
(
struct
xfrm_sec_ctx
**
ctxp
,
struct
xfrm_user_sec_ctx
*
sec_
ctx
);
struct
xfrm_user_sec_ctx
*
u
ctx
);
int
selinux_xfrm_policy_clone
(
struct
xfrm_sec_ctx
*
old_ctx
,
struct
xfrm_sec_ctx
**
new_ctxp
);
void
selinux_xfrm_policy_free
(
struct
xfrm_sec_ctx
*
ctx
);
int
selinux_xfrm_policy_delete
(
struct
xfrm_sec_ctx
*
ctx
);
int
selinux_xfrm_state_alloc
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
sec_ctx
,
u32
secid
);
struct
xfrm_user_sec_ctx
*
uctx
);
int
selinux_xfrm_state_alloc_acquire
(
struct
xfrm_state
*
x
,
struct
xfrm_sec_ctx
*
polsec
,
u32
secid
);
void
selinux_xfrm_state_free
(
struct
xfrm_state
*
x
);
int
selinux_xfrm_state_delete
(
struct
xfrm_state
*
x
);
int
selinux_xfrm_policy_lookup
(
struct
xfrm_sec_ctx
*
ctx
,
u32
fl_secid
,
u8
dir
);
int
selinux_xfrm_state_pol_flow_match
(
struct
xfrm_state
*
x
,
struct
xfrm_policy
*
xp
,
const
struct
flowi
*
fl
);
/*
* Extract the security blob from the sock (it's actually on the socket)
*/
static
inline
struct
inode_security_struct
*
get_sock_isec
(
struct
sock
*
sk
)
{
if
(
!
sk
->
sk_socket
)
return
NULL
;
return
SOCK_INODE
(
sk
->
sk_socket
)
->
i_security
;
}
struct
xfrm_policy
*
xp
,
const
struct
flowi
*
fl
);
#ifdef CONFIG_SECURITY_NETWORK_XFRM
extern
atomic_t
selinux_xfrm_refcount
;
...
...
@@ -42,10 +34,10 @@ static inline int selinux_xfrm_enabled(void)
return
(
atomic_read
(
&
selinux_xfrm_refcount
)
>
0
);
}
int
selinux_xfrm_sock_rcv_skb
(
u32
sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
);
int
selinux_xfrm_postroute_last
(
u32
isec
_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
,
u8
proto
);
int
selinux_xfrm_sock_rcv_skb
(
u32
s
k_s
id
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
);
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
);
static
inline
void
selinux_xfrm_notify_policyload
(
void
)
...
...
@@ -64,19 +56,21 @@ static inline int selinux_xfrm_enabled(void)
return
0
;
}
static
inline
int
selinux_xfrm_sock_rcv_skb
(
u32
isec
_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
)
static
inline
int
selinux_xfrm_sock_rcv_skb
(
u32
sk
_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
)
{
return
0
;
}
static
inline
int
selinux_xfrm_postroute_last
(
u32
isec_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
,
u8
proto
)
static
inline
int
selinux_xfrm_postroute_last
(
u32
sk_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
,
u8
proto
)
{
return
0
;
}
static
inline
int
selinux_xfrm_decode_session
(
struct
sk_buff
*
skb
,
u32
*
sid
,
int
ckall
)
static
inline
int
selinux_xfrm_decode_session
(
struct
sk_buff
*
skb
,
u32
*
sid
,
int
ckall
)
{
*
sid
=
SECSID_NULL
;
return
0
;
...
...
@@ -87,10 +81,9 @@ static inline void selinux_xfrm_notify_policyload(void)
}
#endif
static
inline
void
selinux_skb_xfrm_sid
(
struct
sk_buff
*
skb
,
u32
*
sid
)
static
inline
int
selinux_skb_xfrm_sid
(
struct
sk_buff
*
skb
,
u32
*
sid
)
{
int
err
=
selinux_xfrm_decode_session
(
skb
,
sid
,
0
);
BUG_ON
(
err
);
return
selinux_xfrm_decode_session
(
skb
,
sid
,
0
);
}
#endif
/* _SELINUX_XFRM_H_ */
security/selinux/netlabel.c
浏览文件 @
6f799c97
...
...
@@ -442,8 +442,7 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
sksec
->
nlbl_state
!=
NLBL_CONNLABELED
)
return
0
;
local_bh_disable
();
bh_lock_sock_nested
(
sk
);
lock_sock
(
sk
);
/* connected sockets are allowed to disconnect when the address family
* is set to AF_UNSPEC, if that is what is happening we want to reset
...
...
@@ -464,7 +463,6 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
sksec
->
nlbl_state
=
NLBL_CONNLABELED
;
socket_connect_return:
bh_unlock_sock
(
sk
);
local_bh_enable
();
release_sock
(
sk
);
return
rc
;
}
security/selinux/netnode.c
浏览文件 @
6f799c97
...
...
@@ -166,6 +166,7 @@ static void sel_netnode_insert(struct sel_netnode *node)
break
;
default:
BUG
();
return
;
}
/* we need to impose a limit on the growth of the hash table so check
...
...
@@ -225,6 +226,7 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
break
;
default:
BUG
();
ret
=
-
EINVAL
;
}
if
(
ret
!=
0
)
goto
out
;
...
...
security/selinux/selinuxfs.c
浏览文件 @
6f799c97
...
...
@@ -44,7 +44,9 @@
/* Policy capability filenames */
static
char
*
policycap_names
[]
=
{
"network_peer_controls"
,
"open_perms"
"open_perms"
,
"redhat1"
,
"always_check_network"
};
unsigned
int
selinux_checkreqprot
=
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE
;
...
...
security/selinux/ss/ebitmap.c
浏览文件 @
6f799c97
...
...
@@ -213,7 +213,12 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
}
#endif
/* CONFIG_NETLABEL */
int
ebitmap_contains
(
struct
ebitmap
*
e1
,
struct
ebitmap
*
e2
)
/*
* Check to see if all the bits set in e2 are also set in e1. Optionally,
* if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
* last_e2bit.
*/
int
ebitmap_contains
(
struct
ebitmap
*
e1
,
struct
ebitmap
*
e2
,
u32
last_e2bit
)
{
struct
ebitmap_node
*
n1
,
*
n2
;
int
i
;
...
...
@@ -223,14 +228,25 @@ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
n1
=
e1
->
node
;
n2
=
e2
->
node
;
while
(
n1
&&
n2
&&
(
n1
->
startbit
<=
n2
->
startbit
))
{
if
(
n1
->
startbit
<
n2
->
startbit
)
{
n1
=
n1
->
next
;
continue
;
}
for
(
i
=
0
;
i
<
EBITMAP_UNIT_NUMS
;
i
++
)
{
for
(
i
=
EBITMAP_UNIT_NUMS
-
1
;
(
i
>=
0
)
&&
!
n2
->
maps
[
i
];
)
i
--
;
/* Skip trailing NULL map entries */
if
(
last_e2bit
&&
(
i
>=
0
))
{
u32
lastsetbit
=
n2
->
startbit
+
i
*
EBITMAP_UNIT_SIZE
+
__fls
(
n2
->
maps
[
i
]);
if
(
lastsetbit
>
last_e2bit
)
return
0
;
}
while
(
i
>=
0
)
{
if
((
n1
->
maps
[
i
]
&
n2
->
maps
[
i
])
!=
n2
->
maps
[
i
])
return
0
;
i
--
;
}
n1
=
n1
->
next
;
...
...
security/selinux/ss/ebitmap.h
浏览文件 @
6f799c97
...
...
@@ -16,7 +16,13 @@
#include <net/netlabel.h>
#define EBITMAP_UNIT_NUMS ((32 - sizeof(void *) - sizeof(u32)) \
#ifdef CONFIG_64BIT
#define EBITMAP_NODE_SIZE 64
#else
#define EBITMAP_NODE_SIZE 32
#endif
#define EBITMAP_UNIT_NUMS ((EBITMAP_NODE_SIZE-sizeof(void *)-sizeof(u32))\
/ sizeof(unsigned long))
#define EBITMAP_UNIT_SIZE BITS_PER_LONG
#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
...
...
@@ -117,7 +123,7 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
int
ebitmap_cmp
(
struct
ebitmap
*
e1
,
struct
ebitmap
*
e2
);
int
ebitmap_cpy
(
struct
ebitmap
*
dst
,
struct
ebitmap
*
src
);
int
ebitmap_contains
(
struct
ebitmap
*
e1
,
struct
ebitmap
*
e2
);
int
ebitmap_contains
(
struct
ebitmap
*
e1
,
struct
ebitmap
*
e2
,
u32
last_e2bit
);
int
ebitmap_get_bit
(
struct
ebitmap
*
e
,
unsigned
long
bit
);
int
ebitmap_set_bit
(
struct
ebitmap
*
e
,
unsigned
long
bit
,
int
value
);
void
ebitmap_destroy
(
struct
ebitmap
*
e
);
...
...
security/selinux/ss/mls.c
浏览文件 @
6f799c97
...
...
@@ -160,8 +160,6 @@ void mls_sid_to_context(struct context *context,
int
mls_level_isvalid
(
struct
policydb
*
p
,
struct
mls_level
*
l
)
{
struct
level_datum
*
levdatum
;
struct
ebitmap_node
*
node
;
int
i
;
if
(
!
l
->
sens
||
l
->
sens
>
p
->
p_levels
.
nprim
)
return
0
;
...
...
@@ -170,19 +168,13 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
if
(
!
levdatum
)
return
0
;
ebitmap_for_each_positive_bit
(
&
l
->
cat
,
node
,
i
)
{
if
(
i
>
p
->
p_cats
.
nprim
)
return
0
;
if
(
!
ebitmap_get_bit
(
&
levdatum
->
level
->
cat
,
i
))
{
/*
* Category may not be associated with
* sensitivity.
*/
return
0
;
}
}
return
1
;
/*
* Return 1 iff all the bits set in l->cat are also be set in
* levdatum->level->cat and no bit in l->cat is larger than
* p->p_cats.nprim.
*/
return
ebitmap_contains
(
&
levdatum
->
level
->
cat
,
&
l
->
cat
,
p
->
p_cats
.
nprim
);
}
int
mls_range_isvalid
(
struct
policydb
*
p
,
struct
mls_range
*
r
)
...
...
security/selinux/ss/mls_types.h
浏览文件 @
6f799c97
...
...
@@ -35,7 +35,7 @@ static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
static
inline
int
mls_level_dom
(
struct
mls_level
*
l1
,
struct
mls_level
*
l2
)
{
return
((
l1
->
sens
>=
l2
->
sens
)
&&
ebitmap_contains
(
&
l1
->
cat
,
&
l2
->
cat
));
ebitmap_contains
(
&
l1
->
cat
,
&
l2
->
cat
,
0
));
}
#define mls_level_incomp(l1, l2) \
...
...
security/selinux/ss/policydb.c
浏览文件 @
6f799c97
...
...
@@ -3203,9 +3203,8 @@ static int range_write_helper(void *key, void *data, void *ptr)
static
int
range_write
(
struct
policydb
*
p
,
void
*
fp
)
{
size_t
nel
;
__le32
buf
[
1
];
int
rc
;
int
rc
,
nel
;
struct
policy_data
pd
;
pd
.
p
=
p
;
...
...
security/selinux/ss/services.c
浏览文件 @
6f799c97
...
...
@@ -72,6 +72,7 @@
int
selinux_policycap_netpeer
;
int
selinux_policycap_openperm
;
int
selinux_policycap_alwaysnetwork
;
static
DEFINE_RWLOCK
(
policy_rwlock
);
...
...
@@ -1812,6 +1813,8 @@ static void security_load_policycaps(void)
POLICYDB_CAPABILITY_NETPEER
);
selinux_policycap_openperm
=
ebitmap_get_bit
(
&
policydb
.
policycaps
,
POLICYDB_CAPABILITY_OPENPERM
);
selinux_policycap_alwaysnetwork
=
ebitmap_get_bit
(
&
policydb
.
policycaps
,
POLICYDB_CAPABILITY_ALWAYSNETWORK
);
}
static
int
security_preserve_bools
(
struct
policydb
*
p
);
...
...
@@ -2323,43 +2326,74 @@ int security_genfs_sid(const char *fstype,
/**
* security_fs_use - Determine how to handle labeling for a filesystem.
* @fstype: filesystem type
* @behavior: labeling behavior
* @sid: SID for filesystem (superblock)
* @sb: superblock in question
*/
int
security_fs_use
(
const
char
*
fstype
,
unsigned
int
*
behavior
,
u32
*
sid
)
int
security_fs_use
(
struct
super_block
*
sb
)
{
int
rc
=
0
;
struct
ocontext
*
c
;
struct
superblock_security_struct
*
sbsec
=
sb
->
s_security
;
const
char
*
fstype
=
sb
->
s_type
->
name
;
const
char
*
subtype
=
(
sb
->
s_subtype
&&
sb
->
s_subtype
[
0
])
?
sb
->
s_subtype
:
NULL
;
struct
ocontext
*
base
=
NULL
;
read_lock
(
&
policy_rwlock
);
c
=
policydb
.
ocontexts
[
OCON_FSUSE
];
while
(
c
)
{
if
(
strcmp
(
fstype
,
c
->
u
.
name
)
==
0
)
for
(
c
=
policydb
.
ocontexts
[
OCON_FSUSE
];
c
;
c
=
c
->
next
)
{
char
*
sub
;
int
baselen
;
baselen
=
strlen
(
fstype
);
/* if base does not match, this is not the one */
if
(
strncmp
(
fstype
,
c
->
u
.
name
,
baselen
))
continue
;
/* if there is no subtype, this is the one! */
if
(
!
subtype
)
break
;
/* skip past the base in this entry */
sub
=
c
->
u
.
name
+
baselen
;
/* entry is only a base. save it. keep looking for subtype */
if
(
sub
[
0
]
==
'\0'
)
{
base
=
c
;
continue
;
}
/* entry is not followed by a subtype, so it is not a match */
if
(
sub
[
0
]
!=
'.'
)
continue
;
/* whew, we found a subtype of this fstype */
sub
++
;
/* move past '.' */
/* exact match of fstype AND subtype */
if
(
!
strcmp
(
subtype
,
sub
))
break
;
c
=
c
->
next
;
}
/* in case we had found an fstype match but no subtype match */
if
(
!
c
)
c
=
base
;
if
(
c
)
{
*
behavior
=
c
->
v
.
behavior
;
sbsec
->
behavior
=
c
->
v
.
behavior
;
if
(
!
c
->
sid
[
0
])
{
rc
=
sidtab_context_to_sid
(
&
sidtab
,
&
c
->
context
[
0
],
&
c
->
sid
[
0
]);
if
(
rc
)
goto
out
;
}
*
sid
=
c
->
sid
[
0
];
sbsec
->
sid
=
c
->
sid
[
0
];
}
else
{
rc
=
security_genfs_sid
(
fstype
,
"/"
,
SECCLASS_DIR
,
sid
);
rc
=
security_genfs_sid
(
fstype
,
"/"
,
SECCLASS_DIR
,
&
sbsec
->
sid
);
if
(
rc
)
{
*
behavior
=
SECURITY_FS_USE_NONE
;
sbsec
->
behavior
=
SECURITY_FS_USE_NONE
;
rc
=
0
;
}
else
{
*
behavior
=
SECURITY_FS_USE_GENFS
;
sbsec
->
behavior
=
SECURITY_FS_USE_GENFS
;
}
}
...
...
security/selinux/xfrm.c
浏览文件 @
6f799c97
...
...
@@ -56,7 +56,7 @@
atomic_t
selinux_xfrm_refcount
=
ATOMIC_INIT
(
0
);
/*
* Returns true if
an LSM/SELinux context
* Returns true if
the context is an LSM/SELinux context.
*/
static
inline
int
selinux_authorizable_ctx
(
struct
xfrm_sec_ctx
*
ctx
)
{
...
...
@@ -66,7 +66,7 @@ static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
}
/*
* Returns true if the xfrm contains a security blob for SELinux
* Returns true if the xfrm contains a security blob for SELinux
.
*/
static
inline
int
selinux_authorizable_xfrm
(
struct
xfrm_state
*
x
)
{
...
...
@@ -74,48 +74,111 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
}
/*
*
LSM hook implementation that authorizes that a flow can use
*
a xfrm policy rule
.
*
Allocates a xfrm_sec_state and populates it using the supplied security
*
xfrm_user_sec_ctx context
.
*/
int
selinux_xfrm_policy_lookup
(
struct
xfrm_sec_ctx
*
ctx
,
u32
fl_secid
,
u8
dir
)
static
int
selinux_xfrm_alloc_user
(
struct
xfrm_sec_ctx
**
ctxp
,
struct
xfrm_user_sec_ctx
*
uctx
)
{
int
rc
;
u32
sel_sid
;
const
struct
task_security_struct
*
tsec
=
current_security
();
struct
xfrm_sec_ctx
*
ctx
=
NULL
;
u32
str_len
;
/* Context sid is either set to label or ANY_ASSOC */
if
(
ctx
)
{
if
(
!
selinux_authorizable_ctx
(
ctx
))
return
-
EINVAL
;
sel_sid
=
ctx
->
ctx_sid
;
}
else
/*
* All flows should be treated as polmatch'ing an
* otherwise applicable "non-labeled" policy. This
* would prevent inadvertent "leaks".
*/
return
0
;
if
(
ctxp
==
NULL
||
uctx
==
NULL
||
uctx
->
ctx_doi
!=
XFRM_SC_DOI_LSM
||
uctx
->
ctx_alg
!=
XFRM_SC_ALG_SELINUX
)
return
-
EINVAL
;
rc
=
avc_has_perm
(
fl_secid
,
sel_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__POLMATCH
,
NULL
)
;
str_len
=
uctx
->
ctx_len
;
if
(
str_len
>=
PAGE_SIZE
)
return
-
ENOMEM
;
if
(
rc
==
-
EACCES
)
return
-
ESRCH
;
ctx
=
kmalloc
(
sizeof
(
*
ctx
)
+
str_len
+
1
,
GFP_KERNEL
);
if
(
!
ctx
)
return
-
ENOMEM
;
ctx
->
ctx_doi
=
XFRM_SC_DOI_LSM
;
ctx
->
ctx_alg
=
XFRM_SC_ALG_SELINUX
;
ctx
->
ctx_len
=
str_len
;
memcpy
(
ctx
->
ctx_str
,
&
uctx
[
1
],
str_len
);
ctx
->
ctx_str
[
str_len
]
=
'\0'
;
rc
=
security_context_to_sid
(
ctx
->
ctx_str
,
str_len
,
&
ctx
->
ctx_sid
);
if
(
rc
)
goto
err
;
rc
=
avc_has_perm
(
tsec
->
sid
,
ctx
->
ctx_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SETCONTEXT
,
NULL
);
if
(
rc
)
goto
err
;
*
ctxp
=
ctx
;
atomic_inc
(
&
selinux_xfrm_refcount
);
return
0
;
err:
kfree
(
ctx
);
return
rc
;
}
/*
* Free the xfrm_sec_ctx structure.
*/
static
void
selinux_xfrm_free
(
struct
xfrm_sec_ctx
*
ctx
)
{
if
(
!
ctx
)
return
;
atomic_dec
(
&
selinux_xfrm_refcount
);
kfree
(
ctx
);
}
/*
* Authorize the deletion of a labeled SA or policy rule.
*/
static
int
selinux_xfrm_delete
(
struct
xfrm_sec_ctx
*
ctx
)
{
const
struct
task_security_struct
*
tsec
=
current_security
();
if
(
!
ctx
)
return
0
;
return
avc_has_perm
(
tsec
->
sid
,
ctx
->
ctx_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SETCONTEXT
,
NULL
);
}
/*
* LSM hook implementation that authorizes that a flow can use a xfrm policy
* rule.
*/
int
selinux_xfrm_policy_lookup
(
struct
xfrm_sec_ctx
*
ctx
,
u32
fl_secid
,
u8
dir
)
{
int
rc
;
/* All flows should be treated as polmatch'ing an otherwise applicable
* "non-labeled" policy. This would prevent inadvertent "leaks". */
if
(
!
ctx
)
return
0
;
/* Context sid is either set to label or ANY_ASSOC */
if
(
!
selinux_authorizable_ctx
(
ctx
))
return
-
EINVAL
;
rc
=
avc_has_perm
(
fl_secid
,
ctx
->
ctx_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__POLMATCH
,
NULL
);
return
(
rc
==
-
EACCES
?
-
ESRCH
:
rc
);
}
/*
* LSM hook implementation that authorizes that a state matches
* the given policy, flow combo.
*/
int
selinux_xfrm_state_pol_flow_match
(
struct
xfrm_state
*
x
,
struct
xfrm_policy
*
xp
,
const
struct
flowi
*
fl
)
int
selinux_xfrm_state_pol_flow_match
(
struct
xfrm_state
*
x
,
struct
xfrm_policy
*
xp
,
const
struct
flowi
*
fl
)
{
u32
state_sid
;
int
rc
;
if
(
!
xp
->
security
)
if
(
x
->
security
)
...
...
@@ -138,187 +201,80 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
if
(
fl
->
flowi_secid
!=
state_sid
)
return
0
;
rc
=
avc_has_perm
(
fl
->
flowi_secid
,
state_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SENDTO
,
NULL
)
?
0
:
1
;
/*
* We don't need a separate SA Vs. policy polmatch check
* since the SA is now of the same label as the flow and
* a flow Vs. policy polmatch check had already happened
* in selinux_xfrm_policy_lookup() above.
*/
return
rc
;
/* We don't need a separate SA Vs. policy polmatch check since the SA
* is now of the same label as the flow and a flow Vs. policy polmatch
* check had already happened in selinux_xfrm_policy_lookup() above. */
return
(
avc_has_perm
(
fl
->
flowi_secid
,
state_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SENDTO
,
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
)
{
u32
sid_session
=
SECSID_NULL
;
struct
sec_path
*
sp
;
*
sid
=
SECSID_NULL
;
if
(
skb
==
NULL
)
return
0
;
goto
out
;
sp
=
skb
->
sp
;
if
(
sp
)
{
int
i
,
sid_set
=
0
;
int
i
;
for
(
i
=
sp
->
len
-
1
;
i
>=
0
;
i
--
)
{
for
(
i
=
sp
->
len
-
1
;
i
>=
0
;
i
--
)
{
struct
xfrm_state
*
x
=
sp
->
xvec
[
i
];
if
(
selinux_authorizable_xfrm
(
x
))
{
struct
xfrm_sec_ctx
*
ctx
=
x
->
security
;
if
(
!
sid_set
)
{
*
sid
=
ctx
->
ctx_sid
;
sid_set
=
1
;
if
(
sid_session
==
SECSID_NULL
)
{
sid_session
=
ctx
->
ctx_sid
;
if
(
!
ckall
)
break
;
}
else
if
(
*
sid
!=
ctx
->
ctx_sid
)
goto
out
;
}
else
if
(
sid_session
!=
ctx
->
ctx_sid
)
{
*
sid
=
SECSID_NULL
;
return
-
EINVAL
;
}
}
}
}
return
0
;
}
/*
* Security blob allocation for xfrm_policy and xfrm_state
* CTX does not have a meaningful value on input
*/
static
int
selinux_xfrm_sec_ctx_alloc
(
struct
xfrm_sec_ctx
**
ctxp
,
struct
xfrm_user_sec_ctx
*
uctx
,
u32
sid
)
{
int
rc
=
0
;
const
struct
task_security_struct
*
tsec
=
current_security
();
struct
xfrm_sec_ctx
*
ctx
=
NULL
;
char
*
ctx_str
=
NULL
;
u32
str_len
;
BUG_ON
(
uctx
&&
sid
);
if
(
!
uctx
)
goto
not_from_user
;
if
(
uctx
->
ctx_alg
!=
XFRM_SC_ALG_SELINUX
)
return
-
EINVAL
;
str_len
=
uctx
->
ctx_len
;
if
(
str_len
>=
PAGE_SIZE
)
return
-
ENOMEM
;
*
ctxp
=
ctx
=
kmalloc
(
sizeof
(
*
ctx
)
+
str_len
+
1
,
GFP_KERNEL
);
if
(
!
ctx
)
return
-
ENOMEM
;
ctx
->
ctx_doi
=
uctx
->
ctx_doi
;
ctx
->
ctx_len
=
str_len
;
ctx
->
ctx_alg
=
uctx
->
ctx_alg
;
memcpy
(
ctx
->
ctx_str
,
uctx
+
1
,
str_len
);
ctx
->
ctx_str
[
str_len
]
=
0
;
rc
=
security_context_to_sid
(
ctx
->
ctx_str
,
str_len
,
&
ctx
->
ctx_sid
);
if
(
rc
)
goto
out
;
/*
* Does the subject have permission to set security context?
*/
rc
=
avc_has_perm
(
tsec
->
sid
,
ctx
->
ctx_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SETCONTEXT
,
NULL
);
if
(
rc
)
goto
out
;
return
rc
;
not_from_user:
rc
=
security_sid_to_context
(
sid
,
&
ctx_str
,
&
str_len
);
if
(
rc
)
goto
out
;
*
ctxp
=
ctx
=
kmalloc
(
sizeof
(
*
ctx
)
+
str_len
,
GFP_ATOMIC
);
if
(
!
ctx
)
{
rc
=
-
ENOMEM
;
goto
out
;
}
ctx
->
ctx_doi
=
XFRM_SC_DOI_LSM
;
ctx
->
ctx_alg
=
XFRM_SC_ALG_SELINUX
;
ctx
->
ctx_sid
=
sid
;
ctx
->
ctx_len
=
str_len
;
memcpy
(
ctx
->
ctx_str
,
ctx_str
,
str_len
);
goto
out2
;
out:
*
ctxp
=
NULL
;
kfree
(
ctx
);
out2:
kfree
(
ctx_str
);
return
rc
;
*
sid
=
sid_session
;
return
0
;
}
/*
* LSM hook implementation that allocs and transfers uctx spec to
* xfrm_policy.
* LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
*/
int
selinux_xfrm_policy_alloc
(
struct
xfrm_sec_ctx
**
ctxp
,
struct
xfrm_user_sec_ctx
*
uctx
)
{
int
err
;
BUG_ON
(
!
uctx
);
err
=
selinux_xfrm_sec_ctx_alloc
(
ctxp
,
uctx
,
0
);
if
(
err
==
0
)
atomic_inc
(
&
selinux_xfrm_refcount
);
return
err
;
return
selinux_xfrm_alloc_user
(
ctxp
,
uctx
);
}
/*
* LSM hook implementation that copies security data structure from old to
*
new
for policy cloning.
* LSM hook implementation that copies security data structure from old to
new
* for policy cloning.
*/
int
selinux_xfrm_policy_clone
(
struct
xfrm_sec_ctx
*
old_ctx
,
struct
xfrm_sec_ctx
**
new_ctxp
)
{
struct
xfrm_sec_ctx
*
new_ctx
;
if
(
old_ctx
)
{
new_ctx
=
kmalloc
(
sizeof
(
*
old_ctx
)
+
old_ctx
->
ctx_len
,
GFP_ATOMIC
);
if
(
!
new_ctx
)
return
-
ENOMEM
;
if
(
!
old_ctx
)
return
0
;
new_ctx
=
kmemdup
(
old_ctx
,
sizeof
(
*
old_ctx
)
+
old_ctx
->
ctx_len
,
GFP_ATOMIC
);
if
(
!
new_ctx
)
return
-
ENOMEM
;
atomic_inc
(
&
selinux_xfrm_refcount
);
*
new_ctxp
=
new_ctx
;
memcpy
(
new_ctx
,
old_ctx
,
sizeof
(
*
new_ctx
));
memcpy
(
new_ctx
->
ctx_str
,
old_ctx
->
ctx_str
,
new_ctx
->
ctx_len
);
atomic_inc
(
&
selinux_xfrm_refcount
);
*
new_ctxp
=
new_ctx
;
}
return
0
;
}
...
...
@@ -327,8 +283,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
*/
void
selinux_xfrm_policy_free
(
struct
xfrm_sec_ctx
*
ctx
)
{
atomic_dec
(
&
selinux_xfrm_refcount
);
kfree
(
ctx
);
selinux_xfrm_free
(
ctx
);
}
/*
...
...
@@ -336,31 +291,55 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
*/
int
selinux_xfrm_policy_delete
(
struct
xfrm_sec_ctx
*
ctx
)
{
const
struct
task_security_struct
*
tsec
=
current_security
();
if
(
!
ctx
)
return
0
;
return
selinux_xfrm_delete
(
ctx
);
}
return
avc_has_perm
(
tsec
->
sid
,
ctx
->
ctx_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SETCONTEXT
,
NULL
);
/*
* LSM hook implementation that allocates a xfrm_sec_state, populates it using
* the supplied security context, and assigns it to the xfrm_state.
*/
int
selinux_xfrm_state_alloc
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
uctx
)
{
return
selinux_xfrm_alloc_user
(
&
x
->
security
,
uctx
);
}
/*
* LSM hook implementation that alloc
s and transfers sec_ctx spec to
*
xfrm_state
.
* LSM hook implementation that alloc
ates a xfrm_sec_state and populates based
*
on a secid
.
*/
int
selinux_xfrm_state_alloc
(
struct
xfrm_state
*
x
,
struct
xfrm_user_sec_ctx
*
uct
x
,
u32
secid
)
int
selinux_xfrm_state_alloc
_acquire
(
struct
xfrm_state
*
x
,
struct
xfrm_sec_ctx
*
polsec
,
u32
secid
)
{
int
err
;
int
rc
;
struct
xfrm_sec_ctx
*
ctx
;
char
*
ctx_str
=
NULL
;
int
str_len
;
if
(
!
polsec
)
return
0
;
BUG_ON
(
!
x
);
if
(
secid
==
0
)
return
-
EINVAL
;
err
=
selinux_xfrm_sec_ctx_alloc
(
&
x
->
security
,
uctx
,
secid
);
if
(
err
==
0
)
atomic_inc
(
&
selinux_xfrm_refcount
);
return
err
;
rc
=
security_sid_to_context
(
secid
,
&
ctx_str
,
&
str_len
);
if
(
rc
)
return
rc
;
ctx
=
kmalloc
(
sizeof
(
*
ctx
)
+
str_len
,
GFP_ATOMIC
);
if
(
!
ctx
)
return
-
ENOMEM
;
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
;
}
/*
...
...
@@ -368,24 +347,15 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
*/
void
selinux_xfrm_state_free
(
struct
xfrm_state
*
x
)
{
atomic_dec
(
&
selinux_xfrm_refcount
);
kfree
(
x
->
security
);
selinux_xfrm_free
(
x
->
security
);
}
/*
* LSM hook implementation that authorizes deletion of labeled SAs.
*/
/*
* LSM hook implementation that authorizes deletion of labeled SAs.
*/
int
selinux_xfrm_state_delete
(
struct
xfrm_state
*
x
)
{
const
struct
task_security_struct
*
tsec
=
current_security
();
struct
xfrm_sec_ctx
*
ctx
=
x
->
security
;
if
(
!
ctx
)
return
0
;
return
avc_has_perm
(
tsec
->
sid
,
ctx
->
ctx_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SETCONTEXT
,
NULL
);
return
selinux_xfrm_delete
(
x
->
security
);
}
/*
...
...
@@ -395,14 +365,12 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
* we need to check for unlabelled access since this may not have
* gone thru the IPSec process.
*/
int
selinux_xfrm_sock_rcv_skb
(
u32
isec
_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
)
int
selinux_xfrm_sock_rcv_skb
(
u32
sk
_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
)
{
int
i
,
rc
=
0
;
struct
sec_path
*
sp
;
u32
sel_sid
=
SECINITSID_UNLABELED
;
sp
=
skb
->
sp
;
int
i
;
struct
sec_path
*
sp
=
skb
->
sp
;
u32
peer_sid
=
SECINITSID_UNLABELED
;
if
(
sp
)
{
for
(
i
=
0
;
i
<
sp
->
len
;
i
++
)
{
...
...
@@ -410,23 +378,17 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
if
(
x
&&
selinux_authorizable_xfrm
(
x
))
{
struct
xfrm_sec_ctx
*
ctx
=
x
->
security
;
sel
_sid
=
ctx
->
ctx_sid
;
peer
_sid
=
ctx
->
ctx_sid
;
break
;
}
}
}
/*
* This check even when there's no association involved is
* intended, according to Trent Jaeger, to make sure a
* process can't engage in non-ipsec communication unless
* explicitly allowed by policy.
*/
rc
=
avc_has_perm
(
isec_sid
,
sel_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__RECVFROM
,
ad
);
return
rc
;
/* This check even when there's no association involved is intended,
* according to Trent Jaeger, to make sure a process can't engage in
* non-IPsec communication unless explicitly allowed by policy. */
return
avc_has_perm
(
sk_sid
,
peer_sid
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__RECVFROM
,
ad
);
}
/*
...
...
@@ -436,49 +398,38 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
* If we do have a authorizable security association, then it has already been
* checked in the selinux_xfrm_state_pol_flow_match hook above.
*/
int
selinux_xfrm_postroute_last
(
u32
isec
_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
,
u8
proto
)
int
selinux_xfrm_postroute_last
(
u32
sk
_sid
,
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
,
u8
proto
)
{
struct
dst_entry
*
dst
;
int
rc
=
0
;
dst
=
skb_dst
(
skb
);
if
(
dst
)
{
struct
dst_entry
*
dst_test
;
for
(
dst_test
=
dst
;
dst_test
!=
NULL
;
dst_test
=
dst_test
->
child
)
{
struct
xfrm_state
*
x
=
dst_test
->
xfrm
;
if
(
x
&&
selinux_authorizable_xfrm
(
x
))
goto
out
;
}
}
switch
(
proto
)
{
case
IPPROTO_AH
:
case
IPPROTO_ESP
:
case
IPPROTO_COMP
:
/*
* We should have already seen this packet once before
* it underwent xfrm(s). No need to subject it to the
* unlabeled check.
*/
goto
out
;
/* We should have already seen this packet once before it
* underwent xfrm(s). No need to subject it to the unlabeled
* check. */
return
0
;
default:
break
;
}
/*
* This check even when there's no association involved is
* intended, according to Trent Jaeger, to make sure a
* process can't engage in non-ipsec communication unless
* explicitly allowed by policy.
*/
dst
=
skb_dst
(
skb
);
if
(
dst
)
{
struct
dst_entry
*
iter
;
rc
=
avc_has_perm
(
isec_sid
,
SECINITSID_UNLABELED
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SENDTO
,
ad
);
out:
return
rc
;
for
(
iter
=
dst
;
iter
!=
NULL
;
iter
=
iter
->
child
)
{
struct
xfrm_state
*
x
=
iter
->
xfrm
;
if
(
x
&&
selinux_authorizable_xfrm
(
x
))
return
0
;
}
}
/* This check even when there's no association involved is intended,
* according to Trent Jaeger, to make sure a process can't engage in
* non-IPsec communication unless explicitly allowed by policy. */
return
avc_has_perm
(
sk_sid
,
SECINITSID_UNLABELED
,
SECCLASS_ASSOCIATION
,
ASSOCIATION__SENDTO
,
ad
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录