Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
3e5f206c
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
3e5f206c
编写于
9年前
作者:
J
James Morris
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next' of
git://git.infradead.org/users/pcmoore/selinux
into next
上级
0e38c358
fda4d578
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
915 addition
and
110 deletion
+915
-110
include/linux/lsm_audit.h
include/linux/lsm_audit.h
+7
-0
scripts/selinux/mdp/mdp.c
scripts/selinux/mdp/mdp.c
+1
-0
security/lsm_audit.c
security/lsm_audit.c
+15
-0
security/selinux/avc.c
security/selinux/avc.c
+402
-16
security/selinux/hooks.c
security/selinux/hooks.c
+97
-50
security/selinux/include/avc.h
security/selinux/include/avc.h
+6
-0
security/selinux/include/security.h
security/selinux/include/security.h
+30
-2
security/selinux/ss/avtab.c
security/selinux/ss/avtab.c
+90
-14
security/selinux/ss/avtab.h
security/selinux/ss/avtab.h
+32
-1
security/selinux/ss/conditional.c
security/selinux/ss/conditional.c
+27
-5
security/selinux/ss/conditional.h
security/selinux/ss/conditional.h
+4
-2
security/selinux/ss/policydb.c
security/selinux/ss/policydb.c
+5
-0
security/selinux/ss/services.c
security/selinux/ss/services.c
+193
-20
security/selinux/ss/services.h
security/selinux/ss/services.h
+6
-0
未找到文件。
include/linux/lsm_audit.h
浏览文件 @
3e5f206c
...
...
@@ -40,6 +40,11 @@ struct lsm_network_audit {
}
fam
;
};
struct
lsm_ioctlop_audit
{
struct
path
path
;
u16
cmd
;
};
/* Auxiliary data to use in generating the audit record. */
struct
common_audit_data
{
char
type
;
...
...
@@ -53,6 +58,7 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_KMOD 8
#define LSM_AUDIT_DATA_INODE 9
#define LSM_AUDIT_DATA_DENTRY 10
#define LSM_AUDIT_DATA_IOCTL_OP 11
union
{
struct
path
path
;
struct
dentry
*
dentry
;
...
...
@@ -68,6 +74,7 @@ struct common_audit_data {
}
key_struct
;
#endif
char
*
kmod_name
;
struct
lsm_ioctlop_audit
*
op
;
}
u
;
/* this union contains LSM specific data */
union
{
...
...
This diff is collapsed.
Click to expand it.
scripts/selinux/mdp/mdp.c
浏览文件 @
3e5f206c
...
...
@@ -98,6 +98,7 @@ int main(int argc, char *argv[])
/* types, roles, and allows */
fprintf
(
fout
,
"type base_t;
\n
"
);
fprintf
(
fout
,
"role base_r;
\n
"
);
fprintf
(
fout
,
"role base_r types { base_t };
\n
"
);
for
(
i
=
0
;
secclass_map
[
i
].
name
;
i
++
)
fprintf
(
fout
,
"allow base_t base_t:%s *;
\n
"
,
...
...
This diff is collapsed.
Click to expand it.
security/lsm_audit.c
浏览文件 @
3e5f206c
...
...
@@ -245,6 +245,21 @@ static void dump_common_audit_data(struct audit_buffer *ab,
}
break
;
}
case
LSM_AUDIT_DATA_IOCTL_OP
:
{
struct
inode
*
inode
;
audit_log_d_path
(
ab
,
" path="
,
&
a
->
u
.
op
->
path
);
inode
=
a
->
u
.
op
->
path
.
dentry
->
d_inode
;
if
(
inode
)
{
audit_log_format
(
ab
,
" dev="
);
audit_log_untrustedstring
(
ab
,
inode
->
i_sb
->
s_id
);
audit_log_format
(
ab
,
" ino=%lu"
,
inode
->
i_ino
);
}
audit_log_format
(
ab
,
" ioctlcmd=%hx"
,
a
->
u
.
op
->
cmd
);
break
;
}
case
LSM_AUDIT_DATA_DENTRY
:
{
struct
inode
*
inode
;
...
...
This diff is collapsed.
Click to expand it.
security/selinux/avc.c
浏览文件 @
3e5f206c
...
...
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/percpu.h>
#include <linux/list.h>
#include <net/sock.h>
#include <linux/un.h>
#include <net/af_unix.h>
...
...
@@ -48,6 +49,7 @@ struct avc_entry {
u32
tsid
;
u16
tclass
;
struct
av_decision
avd
;
struct
avc_xperms_node
*
xp_node
;
};
struct
avc_node
{
...
...
@@ -56,6 +58,16 @@ struct avc_node {
struct
rcu_head
rhead
;
};
struct
avc_xperms_decision_node
{
struct
extended_perms_decision
xpd
;
struct
list_head
xpd_list
;
/* list of extended_perms_decision */
};
struct
avc_xperms_node
{
struct
extended_perms
xp
;
struct
list_head
xpd_head
;
/* list head of extended_perms_decision */
};
struct
avc_cache
{
struct
hlist_head
slots
[
AVC_CACHE_SLOTS
];
/* head for avc_node->list */
spinlock_t
slots_lock
[
AVC_CACHE_SLOTS
];
/* lock for writes */
...
...
@@ -80,6 +92,9 @@ DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 };
static
struct
avc_cache
avc_cache
;
static
struct
avc_callback_node
*
avc_callbacks
;
static
struct
kmem_cache
*
avc_node_cachep
;
static
struct
kmem_cache
*
avc_xperms_data_cachep
;
static
struct
kmem_cache
*
avc_xperms_decision_cachep
;
static
struct
kmem_cache
*
avc_xperms_cachep
;
static
inline
int
avc_hash
(
u32
ssid
,
u32
tsid
,
u16
tclass
)
{
...
...
@@ -101,6 +116,7 @@ static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
return
;
}
BUG_ON
(
!
tclass
||
tclass
>=
ARRAY_SIZE
(
secclass_map
));
perms
=
secclass_map
[
tclass
-
1
].
perms
;
audit_log_format
(
ab
,
" {"
);
...
...
@@ -149,7 +165,7 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla
kfree
(
scontext
);
}
BUG_ON
(
tclass
>=
ARRAY_SIZE
(
secclass_map
));
BUG_ON
(
!
tclass
||
tclass
>=
ARRAY_SIZE
(
secclass_map
));
audit_log_format
(
ab
,
" tclass=%s"
,
secclass_map
[
tclass
-
1
].
name
);
}
...
...
@@ -170,7 +186,17 @@ void __init avc_init(void)
atomic_set
(
&
avc_cache
.
lru_hint
,
0
);
avc_node_cachep
=
kmem_cache_create
(
"avc_node"
,
sizeof
(
struct
avc_node
),
0
,
SLAB_PANIC
,
NULL
);
0
,
SLAB_PANIC
,
NULL
);
avc_xperms_cachep
=
kmem_cache_create
(
"avc_xperms_node"
,
sizeof
(
struct
avc_xperms_node
),
0
,
SLAB_PANIC
,
NULL
);
avc_xperms_decision_cachep
=
kmem_cache_create
(
"avc_xperms_decision_node"
,
sizeof
(
struct
avc_xperms_decision_node
),
0
,
SLAB_PANIC
,
NULL
);
avc_xperms_data_cachep
=
kmem_cache_create
(
"avc_xperms_data"
,
sizeof
(
struct
extended_perms_data
),
0
,
SLAB_PANIC
,
NULL
);
audit_log
(
current
->
audit_context
,
GFP_KERNEL
,
AUDIT_KERNEL
,
"AVC INITIALIZED
\n
"
);
}
...
...
@@ -205,9 +231,261 @@ int avc_get_hash_stats(char *page)
slots_used
,
AVC_CACHE_SLOTS
,
max_chain_len
);
}
/*
* using a linked list for extended_perms_decision lookup because the list is
* always small. i.e. less than 5, typically 1
*/
static
struct
extended_perms_decision
*
avc_xperms_decision_lookup
(
u8
driver
,
struct
avc_xperms_node
*
xp_node
)
{
struct
avc_xperms_decision_node
*
xpd_node
;
list_for_each_entry
(
xpd_node
,
&
xp_node
->
xpd_head
,
xpd_list
)
{
if
(
xpd_node
->
xpd
.
driver
==
driver
)
return
&
xpd_node
->
xpd
;
}
return
NULL
;
}
static
inline
unsigned
int
avc_xperms_has_perm
(
struct
extended_perms_decision
*
xpd
,
u8
perm
,
u8
which
)
{
unsigned
int
rc
=
0
;
if
((
which
==
XPERMS_ALLOWED
)
&&
(
xpd
->
used
&
XPERMS_ALLOWED
))
rc
=
security_xperm_test
(
xpd
->
allowed
->
p
,
perm
);
else
if
((
which
==
XPERMS_AUDITALLOW
)
&&
(
xpd
->
used
&
XPERMS_AUDITALLOW
))
rc
=
security_xperm_test
(
xpd
->
auditallow
->
p
,
perm
);
else
if
((
which
==
XPERMS_DONTAUDIT
)
&&
(
xpd
->
used
&
XPERMS_DONTAUDIT
))
rc
=
security_xperm_test
(
xpd
->
dontaudit
->
p
,
perm
);
return
rc
;
}
static
void
avc_xperms_allow_perm
(
struct
avc_xperms_node
*
xp_node
,
u8
driver
,
u8
perm
)
{
struct
extended_perms_decision
*
xpd
;
security_xperm_set
(
xp_node
->
xp
.
drivers
.
p
,
driver
);
xpd
=
avc_xperms_decision_lookup
(
driver
,
xp_node
);
if
(
xpd
&&
xpd
->
allowed
)
security_xperm_set
(
xpd
->
allowed
->
p
,
perm
);
}
static
void
avc_xperms_decision_free
(
struct
avc_xperms_decision_node
*
xpd_node
)
{
struct
extended_perms_decision
*
xpd
;
xpd
=
&
xpd_node
->
xpd
;
if
(
xpd
->
allowed
)
kmem_cache_free
(
avc_xperms_data_cachep
,
xpd
->
allowed
);
if
(
xpd
->
auditallow
)
kmem_cache_free
(
avc_xperms_data_cachep
,
xpd
->
auditallow
);
if
(
xpd
->
dontaudit
)
kmem_cache_free
(
avc_xperms_data_cachep
,
xpd
->
dontaudit
);
kmem_cache_free
(
avc_xperms_decision_cachep
,
xpd_node
);
}
static
void
avc_xperms_free
(
struct
avc_xperms_node
*
xp_node
)
{
struct
avc_xperms_decision_node
*
xpd_node
,
*
tmp
;
if
(
!
xp_node
)
return
;
list_for_each_entry_safe
(
xpd_node
,
tmp
,
&
xp_node
->
xpd_head
,
xpd_list
)
{
list_del
(
&
xpd_node
->
xpd_list
);
avc_xperms_decision_free
(
xpd_node
);
}
kmem_cache_free
(
avc_xperms_cachep
,
xp_node
);
}
static
void
avc_copy_xperms_decision
(
struct
extended_perms_decision
*
dest
,
struct
extended_perms_decision
*
src
)
{
dest
->
driver
=
src
->
driver
;
dest
->
used
=
src
->
used
;
if
(
dest
->
used
&
XPERMS_ALLOWED
)
memcpy
(
dest
->
allowed
->
p
,
src
->
allowed
->
p
,
sizeof
(
src
->
allowed
->
p
));
if
(
dest
->
used
&
XPERMS_AUDITALLOW
)
memcpy
(
dest
->
auditallow
->
p
,
src
->
auditallow
->
p
,
sizeof
(
src
->
auditallow
->
p
));
if
(
dest
->
used
&
XPERMS_DONTAUDIT
)
memcpy
(
dest
->
dontaudit
->
p
,
src
->
dontaudit
->
p
,
sizeof
(
src
->
dontaudit
->
p
));
}
/*
* similar to avc_copy_xperms_decision, but only copy decision
* information relevant to this perm
*/
static
inline
void
avc_quick_copy_xperms_decision
(
u8
perm
,
struct
extended_perms_decision
*
dest
,
struct
extended_perms_decision
*
src
)
{
/*
* compute index of the u32 of the 256 bits (8 u32s) that contain this
* command permission
*/
u8
i
=
perm
>>
5
;
dest
->
used
=
src
->
used
;
if
(
dest
->
used
&
XPERMS_ALLOWED
)
dest
->
allowed
->
p
[
i
]
=
src
->
allowed
->
p
[
i
];
if
(
dest
->
used
&
XPERMS_AUDITALLOW
)
dest
->
auditallow
->
p
[
i
]
=
src
->
auditallow
->
p
[
i
];
if
(
dest
->
used
&
XPERMS_DONTAUDIT
)
dest
->
dontaudit
->
p
[
i
]
=
src
->
dontaudit
->
p
[
i
];
}
static
struct
avc_xperms_decision_node
*
avc_xperms_decision_alloc
(
u8
which
)
{
struct
avc_xperms_decision_node
*
xpd_node
;
struct
extended_perms_decision
*
xpd
;
xpd_node
=
kmem_cache_zalloc
(
avc_xperms_decision_cachep
,
GFP_ATOMIC
|
__GFP_NOMEMALLOC
);
if
(
!
xpd_node
)
return
NULL
;
xpd
=
&
xpd_node
->
xpd
;
if
(
which
&
XPERMS_ALLOWED
)
{
xpd
->
allowed
=
kmem_cache_zalloc
(
avc_xperms_data_cachep
,
GFP_ATOMIC
|
__GFP_NOMEMALLOC
);
if
(
!
xpd
->
allowed
)
goto
error
;
}
if
(
which
&
XPERMS_AUDITALLOW
)
{
xpd
->
auditallow
=
kmem_cache_zalloc
(
avc_xperms_data_cachep
,
GFP_ATOMIC
|
__GFP_NOMEMALLOC
);
if
(
!
xpd
->
auditallow
)
goto
error
;
}
if
(
which
&
XPERMS_DONTAUDIT
)
{
xpd
->
dontaudit
=
kmem_cache_zalloc
(
avc_xperms_data_cachep
,
GFP_ATOMIC
|
__GFP_NOMEMALLOC
);
if
(
!
xpd
->
dontaudit
)
goto
error
;
}
return
xpd_node
;
error:
avc_xperms_decision_free
(
xpd_node
);
return
NULL
;
}
static
int
avc_add_xperms_decision
(
struct
avc_node
*
node
,
struct
extended_perms_decision
*
src
)
{
struct
avc_xperms_decision_node
*
dest_xpd
;
node
->
ae
.
xp_node
->
xp
.
len
++
;
dest_xpd
=
avc_xperms_decision_alloc
(
src
->
used
);
if
(
!
dest_xpd
)
return
-
ENOMEM
;
avc_copy_xperms_decision
(
&
dest_xpd
->
xpd
,
src
);
list_add
(
&
dest_xpd
->
xpd_list
,
&
node
->
ae
.
xp_node
->
xpd_head
);
return
0
;
}
static
struct
avc_xperms_node
*
avc_xperms_alloc
(
void
)
{
struct
avc_xperms_node
*
xp_node
;
xp_node
=
kmem_cache_zalloc
(
avc_xperms_cachep
,
GFP_ATOMIC
|
__GFP_NOMEMALLOC
);
if
(
!
xp_node
)
return
xp_node
;
INIT_LIST_HEAD
(
&
xp_node
->
xpd_head
);
return
xp_node
;
}
static
int
avc_xperms_populate
(
struct
avc_node
*
node
,
struct
avc_xperms_node
*
src
)
{
struct
avc_xperms_node
*
dest
;
struct
avc_xperms_decision_node
*
dest_xpd
;
struct
avc_xperms_decision_node
*
src_xpd
;
if
(
src
->
xp
.
len
==
0
)
return
0
;
dest
=
avc_xperms_alloc
();
if
(
!
dest
)
return
-
ENOMEM
;
memcpy
(
dest
->
xp
.
drivers
.
p
,
src
->
xp
.
drivers
.
p
,
sizeof
(
dest
->
xp
.
drivers
.
p
));
dest
->
xp
.
len
=
src
->
xp
.
len
;
/* for each source xpd allocate a destination xpd and copy */
list_for_each_entry
(
src_xpd
,
&
src
->
xpd_head
,
xpd_list
)
{
dest_xpd
=
avc_xperms_decision_alloc
(
src_xpd
->
xpd
.
used
);
if
(
!
dest_xpd
)
goto
error
;
avc_copy_xperms_decision
(
&
dest_xpd
->
xpd
,
&
src_xpd
->
xpd
);
list_add
(
&
dest_xpd
->
xpd_list
,
&
dest
->
xpd_head
);
}
node
->
ae
.
xp_node
=
dest
;
return
0
;
error:
avc_xperms_free
(
dest
);
return
-
ENOMEM
;
}
static
inline
u32
avc_xperms_audit_required
(
u32
requested
,
struct
av_decision
*
avd
,
struct
extended_perms_decision
*
xpd
,
u8
perm
,
int
result
,
u32
*
deniedp
)
{
u32
denied
,
audited
;
denied
=
requested
&
~
avd
->
allowed
;
if
(
unlikely
(
denied
))
{
audited
=
denied
&
avd
->
auditdeny
;
if
(
audited
&&
xpd
)
{
if
(
avc_xperms_has_perm
(
xpd
,
perm
,
XPERMS_DONTAUDIT
))
audited
&=
~
requested
;
}
}
else
if
(
result
)
{
audited
=
denied
=
requested
;
}
else
{
audited
=
requested
&
avd
->
auditallow
;
if
(
audited
&&
xpd
)
{
if
(
!
avc_xperms_has_perm
(
xpd
,
perm
,
XPERMS_AUDITALLOW
))
audited
&=
~
requested
;
}
}
*
deniedp
=
denied
;
return
audited
;
}
static
inline
int
avc_xperms_audit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
struct
av_decision
*
avd
,
struct
extended_perms_decision
*
xpd
,
u8
perm
,
int
result
,
struct
common_audit_data
*
ad
)
{
u32
audited
,
denied
;
audited
=
avc_xperms_audit_required
(
requested
,
avd
,
xpd
,
perm
,
result
,
&
denied
);
if
(
likely
(
!
audited
))
return
0
;
return
slow_avc_audit
(
ssid
,
tsid
,
tclass
,
requested
,
audited
,
denied
,
result
,
ad
,
0
);
}
static
void
avc_node_free
(
struct
rcu_head
*
rhead
)
{
struct
avc_node
*
node
=
container_of
(
rhead
,
struct
avc_node
,
rhead
);
avc_xperms_free
(
node
->
ae
.
xp_node
);
kmem_cache_free
(
avc_node_cachep
,
node
);
avc_cache_stats_incr
(
frees
);
}
...
...
@@ -221,6 +499,7 @@ static void avc_node_delete(struct avc_node *node)
static
void
avc_node_kill
(
struct
avc_node
*
node
)
{
avc_xperms_free
(
node
->
ae
.
xp_node
);
kmem_cache_free
(
avc_node_cachep
,
node
);
avc_cache_stats_incr
(
frees
);
atomic_dec
(
&
avc_cache
.
active_nodes
);
...
...
@@ -367,6 +646,7 @@ static int avc_latest_notif_update(int seqno, int is_insert)
* @tsid: target security identifier
* @tclass: target security class
* @avd: resulting av decision
* @xp_node: resulting extended permissions
*
* Insert an AVC entry for the SID pair
* (@ssid, @tsid) and class @tclass.
...
...
@@ -378,7 +658,9 @@ static int avc_latest_notif_update(int seqno, int is_insert)
* the access vectors into a cache entry, returns
* avc_node inserted. Otherwise, this function returns NULL.
*/
static
struct
avc_node
*
avc_insert
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
struct
av_decision
*
avd
)
static
struct
avc_node
*
avc_insert
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
struct
av_decision
*
avd
,
struct
avc_xperms_node
*
xp_node
)
{
struct
avc_node
*
pos
,
*
node
=
NULL
;
int
hvalue
;
...
...
@@ -391,10 +673,15 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_dec
if
(
node
)
{
struct
hlist_head
*
head
;
spinlock_t
*
lock
;
int
rc
=
0
;
hvalue
=
avc_hash
(
ssid
,
tsid
,
tclass
);
avc_node_populate
(
node
,
ssid
,
tsid
,
tclass
,
avd
);
rc
=
avc_xperms_populate
(
node
,
xp_node
);
if
(
rc
)
{
kmem_cache_free
(
avc_node_cachep
,
node
);
return
NULL
;
}
head
=
&
avc_cache
.
slots
[
hvalue
];
lock
=
&
avc_cache
.
slots_lock
[
hvalue
];
...
...
@@ -523,14 +810,17 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events)
* @perms : Permission mask bits
* @ssid,@tsid,@tclass : identifier of an AVC entry
* @seqno : sequence number when decision was made
* @xpd: extended_perms_decision to be added to the node
*
* if a valid AVC entry doesn't exist,this function returns -ENOENT.
* if kmalloc() called internal returns NULL, this function returns -ENOMEM.
* otherwise, this function updates the AVC entry. The original AVC-entry object
* will release later by RCU.
*/
static
int
avc_update_node
(
u32
event
,
u32
perms
,
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
seqno
)
static
int
avc_update_node
(
u32
event
,
u32
perms
,
u8
driver
,
u8
xperm
,
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
seqno
,
struct
extended_perms_decision
*
xpd
,
u32
flags
)
{
int
hvalue
,
rc
=
0
;
unsigned
long
flag
;
...
...
@@ -574,9 +864,19 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
avc_node_populate
(
node
,
ssid
,
tsid
,
tclass
,
&
orig
->
ae
.
avd
);
if
(
orig
->
ae
.
xp_node
)
{
rc
=
avc_xperms_populate
(
node
,
orig
->
ae
.
xp_node
);
if
(
rc
)
{
kmem_cache_free
(
avc_node_cachep
,
node
);
goto
out_unlock
;
}
}
switch
(
event
)
{
case
AVC_CALLBACK_GRANT
:
node
->
ae
.
avd
.
allowed
|=
perms
;
if
(
node
->
ae
.
xp_node
&&
(
flags
&
AVC_EXTENDED_PERMS
))
avc_xperms_allow_perm
(
node
->
ae
.
xp_node
,
driver
,
xperm
);
break
;
case
AVC_CALLBACK_TRY_REVOKE
:
case
AVC_CALLBACK_REVOKE
:
...
...
@@ -594,6 +894,9 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
case
AVC_CALLBACK_AUDITDENY_DISABLE
:
node
->
ae
.
avd
.
auditdeny
&=
~
perms
;
break
;
case
AVC_CALLBACK_ADD_XPERMS
:
avc_add_xperms_decision
(
node
,
xpd
);
break
;
}
avc_node_replace
(
node
,
orig
);
out_unlock:
...
...
@@ -665,18 +968,20 @@ int avc_ss_reset(u32 seqno)
* results in a bigger stack frame.
*/
static
noinline
struct
avc_node
*
avc_compute_av
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
struct
av_decision
*
avd
)
u16
tclass
,
struct
av_decision
*
avd
,
struct
avc_xperms_node
*
xp_node
)
{
rcu_read_unlock
();
security_compute_av
(
ssid
,
tsid
,
tclass
,
avd
);
INIT_LIST_HEAD
(
&
xp_node
->
xpd_head
);
security_compute_av
(
ssid
,
tsid
,
tclass
,
avd
,
&
xp_node
->
xp
);
rcu_read_lock
();
return
avc_insert
(
ssid
,
tsid
,
tclass
,
avd
);
return
avc_insert
(
ssid
,
tsid
,
tclass
,
avd
,
xp_node
);
}
static
noinline
int
avc_denied
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
unsigned
flags
,
struct
av_decision
*
avd
)
u16
tclass
,
u32
requested
,
u8
driver
,
u8
xperm
,
unsigned
flags
,
struct
av_decision
*
avd
)
{
if
(
flags
&
AVC_STRICT
)
return
-
EACCES
;
...
...
@@ -684,11 +989,91 @@ static noinline int avc_denied(u32 ssid, u32 tsid,
if
(
selinux_enforcing
&&
!
(
avd
->
flags
&
AVD_FLAGS_PERMISSIVE
))
return
-
EACCES
;
avc_update_node
(
AVC_CALLBACK_GRANT
,
requested
,
ssid
,
tsid
,
tclass
,
avd
->
seqno
);
avc_update_node
(
AVC_CALLBACK_GRANT
,
requested
,
driver
,
xperm
,
ssid
,
tsid
,
tclass
,
avd
->
seqno
,
NULL
,
flags
);
return
0
;
}
/*
* The avc extended permissions logic adds an additional 256 bits of
* permissions to an avc node when extended permissions for that node are
* specified in the avtab. If the additional 256 permissions is not adequate,
* as-is the case with ioctls, then multiple may be chained together and the
* driver field is used to specify which set contains the permission.
*/
int
avc_has_extended_perms
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
u8
driver
,
u8
xperm
,
struct
common_audit_data
*
ad
)
{
struct
avc_node
*
node
;
struct
av_decision
avd
;
u32
denied
;
struct
extended_perms_decision
local_xpd
;
struct
extended_perms_decision
*
xpd
=
NULL
;
struct
extended_perms_data
allowed
;
struct
extended_perms_data
auditallow
;
struct
extended_perms_data
dontaudit
;
struct
avc_xperms_node
local_xp_node
;
struct
avc_xperms_node
*
xp_node
;
int
rc
=
0
,
rc2
;
xp_node
=
&
local_xp_node
;
BUG_ON
(
!
requested
);
rcu_read_lock
();
node
=
avc_lookup
(
ssid
,
tsid
,
tclass
);
if
(
unlikely
(
!
node
))
{
node
=
avc_compute_av
(
ssid
,
tsid
,
tclass
,
&
avd
,
xp_node
);
}
else
{
memcpy
(
&
avd
,
&
node
->
ae
.
avd
,
sizeof
(
avd
));
xp_node
=
node
->
ae
.
xp_node
;
}
/* if extended permissions are not defined, only consider av_decision */
if
(
!
xp_node
||
!
xp_node
->
xp
.
len
)
goto
decision
;
local_xpd
.
allowed
=
&
allowed
;
local_xpd
.
auditallow
=
&
auditallow
;
local_xpd
.
dontaudit
=
&
dontaudit
;
xpd
=
avc_xperms_decision_lookup
(
driver
,
xp_node
);
if
(
unlikely
(
!
xpd
))
{
/*
* Compute the extended_perms_decision only if the driver
* is flagged
*/
if
(
!
security_xperm_test
(
xp_node
->
xp
.
drivers
.
p
,
driver
))
{
avd
.
allowed
&=
~
requested
;
goto
decision
;
}
rcu_read_unlock
();
security_compute_xperms_decision
(
ssid
,
tsid
,
tclass
,
driver
,
&
local_xpd
);
rcu_read_lock
();
avc_update_node
(
AVC_CALLBACK_ADD_XPERMS
,
requested
,
driver
,
xperm
,
ssid
,
tsid
,
tclass
,
avd
.
seqno
,
&
local_xpd
,
0
);
}
else
{
avc_quick_copy_xperms_decision
(
xperm
,
&
local_xpd
,
xpd
);
}
xpd
=
&
local_xpd
;
if
(
!
avc_xperms_has_perm
(
xpd
,
xperm
,
XPERMS_ALLOWED
))
avd
.
allowed
&=
~
requested
;
decision:
denied
=
requested
&
~
(
avd
.
allowed
);
if
(
unlikely
(
denied
))
rc
=
avc_denied
(
ssid
,
tsid
,
tclass
,
requested
,
driver
,
xperm
,
AVC_EXTENDED_PERMS
,
&
avd
);
rcu_read_unlock
();
rc2
=
avc_xperms_audit
(
ssid
,
tsid
,
tclass
,
requested
,
&
avd
,
xpd
,
xperm
,
rc
,
ad
);
if
(
rc2
)
return
rc2
;
return
rc
;
}
/**
* avc_has_perm_noaudit - Check permissions but perform no auditing.
...
...
@@ -716,6 +1101,7 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
struct
av_decision
*
avd
)
{
struct
avc_node
*
node
;
struct
avc_xperms_node
xp_node
;
int
rc
=
0
;
u32
denied
;
...
...
@@ -725,13 +1111,13 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
node
=
avc_lookup
(
ssid
,
tsid
,
tclass
);
if
(
unlikely
(
!
node
))
node
=
avc_compute_av
(
ssid
,
tsid
,
tclass
,
avd
);
node
=
avc_compute_av
(
ssid
,
tsid
,
tclass
,
avd
,
&
xp_node
);
else
memcpy
(
avd
,
&
node
->
ae
.
avd
,
sizeof
(
*
avd
));
denied
=
requested
&
~
(
avd
->
allowed
);
if
(
unlikely
(
denied
))
rc
=
avc_denied
(
ssid
,
tsid
,
tclass
,
requested
,
flags
,
avd
);
rc
=
avc_denied
(
ssid
,
tsid
,
tclass
,
requested
,
0
,
0
,
flags
,
avd
);
rcu_read_unlock
();
return
rc
;
...
...
This diff is collapsed.
Click to expand it.
security/selinux/hooks.c
浏览文件 @
3e5f206c
...
...
@@ -254,10 +254,21 @@ static void inode_free_security(struct inode *inode)
struct
inode_security_struct
*
isec
=
inode
->
i_security
;
struct
superblock_security_struct
*
sbsec
=
inode
->
i_sb
->
s_security
;
spin_lock
(
&
sbsec
->
isec_lock
);
if
(
!
list_empty
(
&
isec
->
list
))
/*
* As not all inode security structures are in a list, we check for
* empty list outside of the lock to make sure that we won't waste
* time taking a lock doing nothing.
*
* The list_del_init() function can be safely called more than once.
* It should not be possible for this function to be called with
* concurrent list_add(), but for better safety against future changes
* in the code, we use list_empty_careful() here.
*/
if
(
!
list_empty_careful
(
&
isec
->
list
))
{
spin_lock
(
&
sbsec
->
isec_lock
);
list_del_init
(
&
isec
->
list
);
spin_unlock
(
&
sbsec
->
isec_lock
);
spin_unlock
(
&
sbsec
->
isec_lock
);
}
/*
* The inode may still be referenced in a path walk and
...
...
@@ -1698,6 +1709,32 @@ static int file_has_perm(const struct cred *cred,
return
rc
;
}
/*
* Determine the label for an inode that might be unioned.
*/
static
int
selinux_determine_inode_label
(
const
struct
inode
*
dir
,
const
struct
qstr
*
name
,
u16
tclass
,
u32
*
_new_isid
)
{
const
struct
superblock_security_struct
*
sbsec
=
dir
->
i_sb
->
s_security
;
const
struct
inode_security_struct
*
dsec
=
dir
->
i_security
;
const
struct
task_security_struct
*
tsec
=
current_security
();
if
((
sbsec
->
flags
&
SE_SBINITIALIZED
)
&&
(
sbsec
->
behavior
==
SECURITY_FS_USE_MNTPOINT
))
{
*
_new_isid
=
sbsec
->
mntpoint_sid
;
}
else
if
((
sbsec
->
flags
&
SBLABEL_MNT
)
&&
tsec
->
create_sid
)
{
*
_new_isid
=
tsec
->
create_sid
;
}
else
{
return
security_transition_sid
(
tsec
->
sid
,
dsec
->
sid
,
tclass
,
name
,
_new_isid
);
}
return
0
;
}
/* Check whether a task can create a file. */
static
int
may_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
...
...
@@ -1714,7 +1751,6 @@ static int may_create(struct inode *dir,
sbsec
=
dir
->
i_sb
->
s_security
;
sid
=
tsec
->
sid
;
newsid
=
tsec
->
create_sid
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
dentry
;
...
...
@@ -1725,12 +1761,10 @@ static int may_create(struct inode *dir,
if
(
rc
)
return
rc
;
if
(
!
newsid
||
!
(
sbsec
->
flags
&
SBLABEL_MNT
))
{
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
tclass
,
&
dentry
->
d_name
,
&
newsid
);
if
(
rc
)
return
rc
;
}
rc
=
selinux_determine_inode_label
(
dir
,
&
dentry
->
d_name
,
tclass
,
&
newsid
);
if
(
rc
)
return
rc
;
rc
=
avc_has_perm
(
sid
,
newsid
,
tclass
,
FILE__CREATE
,
&
ad
);
if
(
rc
)
...
...
@@ -2704,32 +2738,14 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
struct
qstr
*
name
,
void
**
ctx
,
u32
*
ctxlen
)
{
const
struct
cred
*
cred
=
current_cred
();
struct
task_security_struct
*
tsec
;
struct
inode_security_struct
*
dsec
;
struct
superblock_security_struct
*
sbsec
;
struct
inode
*
dir
=
d_backing_inode
(
dentry
->
d_parent
);
u32
newsid
;
int
rc
;
tsec
=
cred
->
security
;
dsec
=
dir
->
i_security
;
sbsec
=
dir
->
i_sb
->
s_security
;
if
(
tsec
->
create_sid
&&
sbsec
->
behavior
!=
SECURITY_FS_USE_MNTPOINT
)
{
newsid
=
tsec
->
create_sid
;
}
else
{
rc
=
security_transition_sid
(
tsec
->
sid
,
dsec
->
sid
,
inode_mode_to_security_class
(
mode
),
name
,
&
newsid
);
if
(
rc
)
{
printk
(
KERN_WARNING
"%s: security_transition_sid failed, rc=%d
\n
"
,
__func__
,
-
rc
);
return
rc
;
}
}
rc
=
selinux_determine_inode_label
(
d_inode
(
dentry
->
d_parent
),
name
,
inode_mode_to_security_class
(
mode
),
&
newsid
);
if
(
rc
)
return
rc
;
return
security_sid_to_context
(
newsid
,
(
char
**
)
ctx
,
ctxlen
);
}
...
...
@@ -2752,22 +2768,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
sid
=
tsec
->
sid
;
newsid
=
tsec
->
create_sid
;
if
((
sbsec
->
flags
&
SE_SBINITIALIZED
)
&&
(
sbsec
->
behavior
==
SECURITY_FS_USE_MNTPOINT
))
newsid
=
sbsec
->
mntpoint_sid
;
else
if
(
!
newsid
||
!
(
sbsec
->
flags
&
SBLABEL_MNT
))
{
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
inode_mode_to_security_class
(
inode
->
i_mode
),
qstr
,
&
newsid
);
if
(
rc
)
{
printk
(
KERN_WARNING
"%s: "
"security_transition_sid failed, rc=%d (dev=%s "
"ino=%ld)
\n
"
,
__func__
,
-
rc
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
);
return
rc
;
}
}
rc
=
selinux_determine_inode_label
(
dir
,
qstr
,
inode_mode_to_security_class
(
inode
->
i_mode
),
&
newsid
);
if
(
rc
)
return
rc
;
/* Possibly defer initialization to selinux_complete_init. */
if
(
sbsec
->
flags
&
SE_SBINITIALIZED
)
{
...
...
@@ -3228,6 +3234,46 @@ static void selinux_file_free_security(struct file *file)
file_free_security
(
file
);
}
/*
* Check whether a task has the ioctl permission and cmd
* operation to an inode.
*/
int
ioctl_has_perm
(
const
struct
cred
*
cred
,
struct
file
*
file
,
u32
requested
,
u16
cmd
)
{
struct
common_audit_data
ad
;
struct
file_security_struct
*
fsec
=
file
->
f_security
;
struct
inode
*
inode
=
file_inode
(
file
);
struct
inode_security_struct
*
isec
=
inode
->
i_security
;
struct
lsm_ioctlop_audit
ioctl
;
u32
ssid
=
cred_sid
(
cred
);
int
rc
;
u8
driver
=
cmd
>>
8
;
u8
xperm
=
cmd
&
0xff
;
ad
.
type
=
LSM_AUDIT_DATA_IOCTL_OP
;
ad
.
u
.
op
=
&
ioctl
;
ad
.
u
.
op
->
cmd
=
cmd
;
ad
.
u
.
op
->
path
=
file
->
f_path
;
if
(
ssid
!=
fsec
->
sid
)
{
rc
=
avc_has_perm
(
ssid
,
fsec
->
sid
,
SECCLASS_FD
,
FD__USE
,
&
ad
);
if
(
rc
)
goto
out
;
}
if
(
unlikely
(
IS_PRIVATE
(
inode
)))
return
0
;
rc
=
avc_has_extended_perms
(
ssid
,
isec
->
sid
,
isec
->
sclass
,
requested
,
driver
,
xperm
,
&
ad
);
out:
return
rc
;
}
static
int
selinux_file_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
...
...
@@ -3270,7 +3316,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
* to the file's ioctl() function.
*/
default:
error
=
file_has_perm
(
cred
,
file
,
FILE__IOCTL
);
error
=
ioctl_has_perm
(
cred
,
file
,
FILE__IOCTL
,
(
u16
)
cmd
);
}
return
error
;
}
...
...
@@ -4520,6 +4566,7 @@ static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority
sksec
->
peer_sid
=
SECINITSID_UNLABELED
;
sksec
->
sid
=
SECINITSID_UNLABELED
;
sksec
->
sclass
=
SECCLASS_SOCKET
;
selinux_netlbl_sk_security_reset
(
sksec
);
sk
->
sk_security
=
sksec
;
...
...
This diff is collapsed.
Click to expand it.
security/selinux/include/avc.h
浏览文件 @
3e5f206c
...
...
@@ -143,6 +143,7 @@ static inline int avc_audit(u32 ssid, u32 tsid,
}
#define AVC_STRICT 1
/* Ignore permissive mode. */
#define AVC_EXTENDED_PERMS 2
/* update extended permissions */
int
avc_has_perm_noaudit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
unsigned
flags
,
...
...
@@ -156,6 +157,10 @@ int avc_has_perm_flags(u32 ssid, u32 tsid,
struct
common_audit_data
*
auditdata
,
int
flags
);
int
avc_has_extended_perms
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
u8
driver
,
u8
perm
,
struct
common_audit_data
*
ad
);
u32
avc_policy_seqno
(
void
);
#define AVC_CALLBACK_GRANT 1
...
...
@@ -166,6 +171,7 @@ u32 avc_policy_seqno(void);
#define AVC_CALLBACK_AUDITALLOW_DISABLE 32
#define AVC_CALLBACK_AUDITDENY_ENABLE 64
#define AVC_CALLBACK_AUDITDENY_DISABLE 128
#define AVC_CALLBACK_ADD_XPERMS 256
int
avc_add_callback
(
int
(
*
callback
)(
u32
event
),
u32
events
);
...
...
This diff is collapsed.
Click to expand it.
security/selinux/include/security.h
浏览文件 @
3e5f206c
...
...
@@ -35,13 +35,14 @@
#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
#define POLICYDB_VERSION_DEFAULT_TYPE 28
#define POLICYDB_VERSION_CONSTRAINT_NAMES 29
#define POLICYDB_VERSION_XPERMS_IOCTL 30
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_
CONSTRAINT_NAMES
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_
XPERMS_IOCTL
#endif
/* Mask for just the mount related flags */
...
...
@@ -109,11 +110,38 @@ struct av_decision {
u32
flags
;
};
#define XPERMS_ALLOWED 1
#define XPERMS_AUDITALLOW 2
#define XPERMS_DONTAUDIT 4
#define security_xperm_set(perms, x) (perms[x >> 5] |= 1 << (x & 0x1f))
#define security_xperm_test(perms, x) (1 & (perms[x >> 5] >> (x & 0x1f)))
struct
extended_perms_data
{
u32
p
[
8
];
};
struct
extended_perms_decision
{
u8
used
;
u8
driver
;
struct
extended_perms_data
*
allowed
;
struct
extended_perms_data
*
auditallow
;
struct
extended_perms_data
*
dontaudit
;
};
struct
extended_perms
{
u16
len
;
/* length associated decision chain */
struct
extended_perms_data
drivers
;
/* flag drivers that are used */
};
/* definitions of av_decision.flags */
#define AVD_FLAGS_PERMISSIVE 0x0001
void
security_compute_av
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
struct
av_decision
*
avd
);
u16
tclass
,
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
);
void
security_compute_xperms_decision
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u8
driver
,
struct
extended_perms_decision
*
xpermd
);
void
security_compute_av_user
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
struct
av_decision
*
avd
);
...
...
This diff is collapsed.
Click to expand it.
security/selinux/ss/avtab.c
浏览文件 @
3e5f206c
...
...
@@ -24,6 +24,7 @@
#include "policydb.h"
static
struct
kmem_cache
*
avtab_node_cachep
;
static
struct
kmem_cache
*
avtab_xperms_cachep
;
/* Based on MurmurHash3, written by Austin Appleby and placed in the
* public domain.
...
...
@@ -70,11 +71,24 @@ avtab_insert_node(struct avtab *h, int hvalue,
struct
avtab_key
*
key
,
struct
avtab_datum
*
datum
)
{
struct
avtab_node
*
newnode
;
struct
avtab_extended_perms
*
xperms
;
newnode
=
kmem_cache_zalloc
(
avtab_node_cachep
,
GFP_KERNEL
);
if
(
newnode
==
NULL
)
return
NULL
;
newnode
->
key
=
*
key
;
newnode
->
datum
=
*
datum
;
if
(
key
->
specified
&
AVTAB_XPERMS
)
{
xperms
=
kmem_cache_zalloc
(
avtab_xperms_cachep
,
GFP_KERNEL
);
if
(
xperms
==
NULL
)
{
kmem_cache_free
(
avtab_node_cachep
,
newnode
);
return
NULL
;
}
*
xperms
=
*
(
datum
->
u
.
xperms
);
newnode
->
datum
.
u
.
xperms
=
xperms
;
}
else
{
newnode
->
datum
.
u
.
data
=
datum
->
u
.
data
;
}
if
(
prev
)
{
newnode
->
next
=
prev
->
next
;
prev
->
next
=
newnode
;
...
...
@@ -107,8 +121,12 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
if
(
key
->
source_type
==
cur
->
key
.
source_type
&&
key
->
target_type
==
cur
->
key
.
target_type
&&
key
->
target_class
==
cur
->
key
.
target_class
&&
(
specified
&
cur
->
key
.
specified
))
(
specified
&
cur
->
key
.
specified
))
{
/* extended perms may not be unique */
if
(
specified
&
AVTAB_XPERMS
)
break
;
return
-
EEXIST
;
}
if
(
key
->
source_type
<
cur
->
key
.
source_type
)
break
;
if
(
key
->
source_type
==
cur
->
key
.
source_type
&&
...
...
@@ -271,6 +289,9 @@ void avtab_destroy(struct avtab *h)
while
(
cur
)
{
temp
=
cur
;
cur
=
cur
->
next
;
if
(
temp
->
key
.
specified
&
AVTAB_XPERMS
)
kmem_cache_free
(
avtab_xperms_cachep
,
temp
->
datum
.
u
.
xperms
);
kmem_cache_free
(
avtab_node_cachep
,
temp
);
}
}
...
...
@@ -359,7 +380,10 @@ static uint16_t spec_order[] = {
AVTAB_AUDITALLOW
,
AVTAB_TRANSITION
,
AVTAB_CHANGE
,
AVTAB_MEMBER
AVTAB_MEMBER
,
AVTAB_XPERMS_ALLOWED
,
AVTAB_XPERMS_AUDITALLOW
,
AVTAB_XPERMS_DONTAUDIT
};
int
avtab_read_item
(
struct
avtab
*
a
,
void
*
fp
,
struct
policydb
*
pol
,
...
...
@@ -369,10 +393,11 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
{
__le16
buf16
[
4
];
u16
enabled
;
__le32
buf32
[
7
];
u32
items
,
items2
,
val
,
vers
=
pol
->
policyvers
;
struct
avtab_key
key
;
struct
avtab_datum
datum
;
struct
avtab_extended_perms
xperms
;
__le32
buf32
[
ARRAY_SIZE
(
xperms
.
perms
.
p
)];
int
i
,
rc
;
unsigned
set
;
...
...
@@ -429,11 +454,15 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
printk
(
KERN_ERR
"SELinux: avtab: entry has both access vectors and types
\n
"
);
return
-
EINVAL
;
}
if
(
val
&
AVTAB_XPERMS
)
{
printk
(
KERN_ERR
"SELinux: avtab: entry has extended permissions
\n
"
);
return
-
EINVAL
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
spec_order
);
i
++
)
{
if
(
val
&
spec_order
[
i
])
{
key
.
specified
=
spec_order
[
i
]
|
enabled
;
datum
.
data
=
le32_to_cpu
(
buf32
[
items
++
]);
datum
.
u
.
data
=
le32_to_cpu
(
buf32
[
items
++
]);
rc
=
insertf
(
a
,
&
key
,
&
datum
,
p
);
if
(
rc
)
return
rc
;
...
...
@@ -476,14 +505,42 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
return
-
EINVAL
;
}
rc
=
next_entry
(
buf32
,
fp
,
sizeof
(
u32
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
if
((
vers
<
POLICYDB_VERSION_XPERMS_IOCTL
)
&&
(
key
.
specified
&
AVTAB_XPERMS
))
{
printk
(
KERN_ERR
"SELinux: avtab: policy version %u does not "
"support extended permissions rules and one "
"was specified
\n
"
,
vers
);
return
-
EINVAL
;
}
else
if
(
key
.
specified
&
AVTAB_XPERMS
)
{
memset
(
&
xperms
,
0
,
sizeof
(
struct
avtab_extended_perms
));
rc
=
next_entry
(
&
xperms
.
specified
,
fp
,
sizeof
(
u8
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
}
rc
=
next_entry
(
&
xperms
.
driver
,
fp
,
sizeof
(
u8
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
}
rc
=
next_entry
(
buf32
,
fp
,
sizeof
(
u32
)
*
ARRAY_SIZE
(
xperms
.
perms
.
p
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
xperms
.
perms
.
p
);
i
++
)
xperms
.
perms
.
p
[
i
]
=
le32_to_cpu
(
buf32
[
i
]);
datum
.
u
.
xperms
=
&
xperms
;
}
else
{
rc
=
next_entry
(
buf32
,
fp
,
sizeof
(
u32
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
}
datum
.
u
.
data
=
le32_to_cpu
(
*
buf32
);
}
datum
.
data
=
le32_to_cpu
(
*
buf32
);
if
((
key
.
specified
&
AVTAB_TYPE
)
&&
!
policydb_type_isvalid
(
pol
,
datum
.
data
))
{
!
policydb_type_isvalid
(
pol
,
datum
.
u
.
data
))
{
printk
(
KERN_ERR
"SELinux: avtab: invalid type
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -543,8 +600,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
int
avtab_write_item
(
struct
policydb
*
p
,
struct
avtab_node
*
cur
,
void
*
fp
)
{
__le16
buf16
[
4
];
__le32
buf32
[
1
];
__le32
buf32
[
ARRAY_SIZE
(
cur
->
datum
.
u
.
xperms
->
perms
.
p
)
];
int
rc
;
unsigned
int
i
;
buf16
[
0
]
=
cpu_to_le16
(
cur
->
key
.
source_type
);
buf16
[
1
]
=
cpu_to_le16
(
cur
->
key
.
target_type
);
...
...
@@ -553,8 +611,22 @@ int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)
rc
=
put_entry
(
buf16
,
sizeof
(
u16
),
4
,
fp
);
if
(
rc
)
return
rc
;
buf32
[
0
]
=
cpu_to_le32
(
cur
->
datum
.
data
);
rc
=
put_entry
(
buf32
,
sizeof
(
u32
),
1
,
fp
);
if
(
cur
->
key
.
specified
&
AVTAB_XPERMS
)
{
rc
=
put_entry
(
&
cur
->
datum
.
u
.
xperms
->
specified
,
sizeof
(
u8
),
1
,
fp
);
if
(
rc
)
return
rc
;
rc
=
put_entry
(
&
cur
->
datum
.
u
.
xperms
->
driver
,
sizeof
(
u8
),
1
,
fp
);
if
(
rc
)
return
rc
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
cur
->
datum
.
u
.
xperms
->
perms
.
p
);
i
++
)
buf32
[
i
]
=
cpu_to_le32
(
cur
->
datum
.
u
.
xperms
->
perms
.
p
[
i
]);
rc
=
put_entry
(
buf32
,
sizeof
(
u32
),
ARRAY_SIZE
(
cur
->
datum
.
u
.
xperms
->
perms
.
p
),
fp
);
}
else
{
buf32
[
0
]
=
cpu_to_le32
(
cur
->
datum
.
u
.
data
);
rc
=
put_entry
(
buf32
,
sizeof
(
u32
),
1
,
fp
);
}
if
(
rc
)
return
rc
;
return
0
;
...
...
@@ -588,9 +660,13 @@ void avtab_cache_init(void)
avtab_node_cachep
=
kmem_cache_create
(
"avtab_node"
,
sizeof
(
struct
avtab_node
),
0
,
SLAB_PANIC
,
NULL
);
avtab_xperms_cachep
=
kmem_cache_create
(
"avtab_extended_perms"
,
sizeof
(
struct
avtab_extended_perms
),
0
,
SLAB_PANIC
,
NULL
);
}
void
avtab_cache_destroy
(
void
)
{
kmem_cache_destroy
(
avtab_node_cachep
);
kmem_cache_destroy
(
avtab_xperms_cachep
);
}
This diff is collapsed.
Click to expand it.
security/selinux/ss/avtab.h
浏览文件 @
3e5f206c
...
...
@@ -23,6 +23,7 @@
#ifndef _SS_AVTAB_H_
#define _SS_AVTAB_H_
#include "security.h"
#include <linux/flex_array.h>
struct
avtab_key
{
...
...
@@ -37,13 +38,43 @@ struct avtab_key {
#define AVTAB_MEMBER 0x0020
#define AVTAB_CHANGE 0x0040
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
/* extended permissions */
#define AVTAB_XPERMS_ALLOWED 0x0100
#define AVTAB_XPERMS_AUDITALLOW 0x0200
#define AVTAB_XPERMS_DONTAUDIT 0x0400
#define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | \
AVTAB_XPERMS_AUDITALLOW | \
AVTAB_XPERMS_DONTAUDIT)
#define AVTAB_ENABLED_OLD 0x80000000
/* reserved for used in cond_avtab */
#define AVTAB_ENABLED 0x8000
/* reserved for used in cond_avtab */
u16
specified
;
/* what field is specified */
};
/*
* For operations that require more than the 32 permissions provided by the avc
* extended permissions may be used to provide 256 bits of permissions.
*/
struct
avtab_extended_perms
{
/* These are not flags. All 256 values may be used */
#define AVTAB_XPERMS_IOCTLFUNCTION 0x01
#define AVTAB_XPERMS_IOCTLDRIVER 0x02
/* extension of the avtab_key specified */
u8
specified
;
/* ioctl, netfilter, ... */
/*
* if 256 bits is not adequate as is often the case with ioctls, then
* multiple extended perms may be used and the driver field
* specifies which permissions are included.
*/
u8
driver
;
/* 256 bits of permissions */
struct
extended_perms_data
perms
;
};
struct
avtab_datum
{
u32
data
;
/* access vector or type value */
union
{
u32
data
;
/* access vector or type value */
struct
avtab_extended_perms
*
xperms
;
}
u
;
};
struct
avtab_node
{
...
...
This diff is collapsed.
Click to expand it.
security/selinux/ss/conditional.c
浏览文件 @
3e5f206c
...
...
@@ -15,6 +15,7 @@
#include "security.h"
#include "conditional.h"
#include "services.h"
/*
* cond_evaluate_expr evaluates a conditional expr
...
...
@@ -612,21 +613,39 @@ int cond_write_list(struct policydb *p, struct cond_node *list, void *fp)
return
0
;
}
void
cond_compute_xperms
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
extended_perms_decision
*
xpermd
)
{
struct
avtab_node
*
node
;
if
(
!
ctab
||
!
key
||
!
xpermd
)
return
;
for
(
node
=
avtab_search_node
(
ctab
,
key
);
node
;
node
=
avtab_search_node_next
(
node
,
key
->
specified
))
{
if
(
node
->
key
.
specified
&
AVTAB_ENABLED
)
services_compute_xperms_decision
(
xpermd
,
node
);
}
return
;
}
/* Determine whether additional permissions are granted by the conditional
* av table, and if so, add them to the result
*/
void
cond_compute_av
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
av_decision
*
avd
)
void
cond_compute_av
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
)
{
struct
avtab_node
*
node
;
if
(
!
ctab
||
!
key
||
!
avd
)
if
(
!
ctab
||
!
key
||
!
avd
||
!
xperms
)
return
;
for
(
node
=
avtab_search_node
(
ctab
,
key
);
node
;
node
=
avtab_search_node_next
(
node
,
key
->
specified
))
{
if
((
u16
)(
AVTAB_ALLOWED
|
AVTAB_ENABLED
)
==
(
node
->
key
.
specified
&
(
AVTAB_ALLOWED
|
AVTAB_ENABLED
)))
avd
->
allowed
|=
node
->
datum
.
data
;
avd
->
allowed
|=
node
->
datum
.
u
.
data
;
if
((
u16
)(
AVTAB_AUDITDENY
|
AVTAB_ENABLED
)
==
(
node
->
key
.
specified
&
(
AVTAB_AUDITDENY
|
AVTAB_ENABLED
)))
/* Since a '0' in an auditdeny mask represents a
...
...
@@ -634,10 +653,13 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
* the '&' operand to ensure that all '0's in the mask
* are retained (much unlike the allow and auditallow cases).
*/
avd
->
auditdeny
&=
node
->
datum
.
data
;
avd
->
auditdeny
&=
node
->
datum
.
u
.
data
;
if
((
u16
)(
AVTAB_AUDITALLOW
|
AVTAB_ENABLED
)
==
(
node
->
key
.
specified
&
(
AVTAB_AUDITALLOW
|
AVTAB_ENABLED
)))
avd
->
auditallow
|=
node
->
datum
.
data
;
avd
->
auditallow
|=
node
->
datum
.
u
.
data
;
if
((
node
->
key
.
specified
&
AVTAB_ENABLED
)
&&
(
node
->
key
.
specified
&
AVTAB_XPERMS
))
services_compute_xperms_drivers
(
xperms
,
node
);
}
return
;
}
This diff is collapsed.
Click to expand it.
security/selinux/ss/conditional.h
浏览文件 @
3e5f206c
...
...
@@ -73,8 +73,10 @@ int cond_read_list(struct policydb *p, void *fp);
int
cond_write_bool
(
void
*
key
,
void
*
datum
,
void
*
ptr
);
int
cond_write_list
(
struct
policydb
*
p
,
struct
cond_node
*
list
,
void
*
fp
);
void
cond_compute_av
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
av_decision
*
avd
);
void
cond_compute_av
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
);
void
cond_compute_xperms
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
extended_perms_decision
*
xpermd
);
int
evaluate_cond_node
(
struct
policydb
*
p
,
struct
cond_node
*
node
);
#endif
/* _CONDITIONAL_H_ */
This diff is collapsed.
Click to expand it.
security/selinux/ss/policydb.c
浏览文件 @
3e5f206c
...
...
@@ -148,6 +148,11 @@ static struct policydb_compat_info policydb_compat[] = {
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
{
.
version
=
POLICYDB_VERSION_XPERMS_IOCTL
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
};
static
struct
policydb_compat_info
*
policydb_lookup_compat
(
int
version
)
...
...
This diff is collapsed.
Click to expand it.
security/selinux/ss/services.c
浏览文件 @
3e5f206c
...
...
@@ -93,9 +93,10 @@ static int context_struct_to_string(struct context *context, char **scontext,
u32
*
scontext_len
);
static
void
context_struct_compute_av
(
struct
context
*
scontext
,
struct
context
*
tcontext
,
u16
tclass
,
struct
av_decision
*
avd
);
struct
context
*
tcontext
,
u16
tclass
,
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
);
struct
selinux_mapping
{
u16
value
;
/* policy value */
...
...
@@ -565,7 +566,8 @@ static void type_attribute_bounds_av(struct context *scontext,
context_struct_compute_av
(
&
lo_scontext
,
tcontext
,
tclass
,
&
lo_avd
);
&
lo_avd
,
NULL
);
if
((
lo_avd
.
allowed
&
avd
->
allowed
)
==
avd
->
allowed
)
return
;
/* no masked permission */
masked
=
~
lo_avd
.
allowed
&
avd
->
allowed
;
...
...
@@ -580,7 +582,8 @@ static void type_attribute_bounds_av(struct context *scontext,
context_struct_compute_av
(
scontext
,
&
lo_tcontext
,
tclass
,
&
lo_avd
);
&
lo_avd
,
NULL
);
if
((
lo_avd
.
allowed
&
avd
->
allowed
)
==
avd
->
allowed
)
return
;
/* no masked permission */
masked
=
~
lo_avd
.
allowed
&
avd
->
allowed
;
...
...
@@ -596,7 +599,8 @@ static void type_attribute_bounds_av(struct context *scontext,
context_struct_compute_av
(
&
lo_scontext
,
&
lo_tcontext
,
tclass
,
&
lo_avd
);
&
lo_avd
,
NULL
);
if
((
lo_avd
.
allowed
&
avd
->
allowed
)
==
avd
->
allowed
)
return
;
/* no masked permission */
masked
=
~
lo_avd
.
allowed
&
avd
->
allowed
;
...
...
@@ -613,13 +617,39 @@ static void type_attribute_bounds_av(struct context *scontext,
}
/*
* Compute access vectors based on a context structure pair for
* the permissions in a particular class.
* flag which drivers have permissions
* only looking for ioctl based extended permssions
*/
void
services_compute_xperms_drivers
(
struct
extended_perms
*
xperms
,
struct
avtab_node
*
node
)
{
unsigned
int
i
;
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLDRIVER
)
{
/* if one or more driver has all permissions allowed */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
xperms
->
drivers
.
p
);
i
++
)
xperms
->
drivers
.
p
[
i
]
|=
node
->
datum
.
u
.
xperms
->
perms
.
p
[
i
];
}
else
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLFUNCTION
)
{
/* if allowing permissions within a driver */
security_xperm_set
(
xperms
->
drivers
.
p
,
node
->
datum
.
u
.
xperms
->
driver
);
}
/* If no ioctl commands are allowed, ignore auditallow and auditdeny */
if
(
node
->
key
.
specified
&
AVTAB_XPERMS_ALLOWED
)
xperms
->
len
=
1
;
}
/*
* Compute access vectors and extended permissions based on a context
* structure pair for the permissions in a particular class.
*/
static
void
context_struct_compute_av
(
struct
context
*
scontext
,
struct
context
*
tcontext
,
u16
tclass
,
struct
av_decision
*
avd
)
struct
context
*
tcontext
,
u16
tclass
,
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
)
{
struct
constraint_node
*
constraint
;
struct
role_allow
*
ra
;
...
...
@@ -633,6 +663,10 @@ static void context_struct_compute_av(struct context *scontext,
avd
->
allowed
=
0
;
avd
->
auditallow
=
0
;
avd
->
auditdeny
=
0xffffffff
;
if
(
xperms
)
{
memset
(
&
xperms
->
drivers
,
0
,
sizeof
(
xperms
->
drivers
));
xperms
->
len
=
0
;
}
if
(
unlikely
(
!
tclass
||
tclass
>
policydb
.
p_classes
.
nprim
))
{
if
(
printk_ratelimit
())
...
...
@@ -647,7 +681,7 @@ static void context_struct_compute_av(struct context *scontext,
* this permission check, then use it.
*/
avkey
.
target_class
=
tclass
;
avkey
.
specified
=
AVTAB_AV
;
avkey
.
specified
=
AVTAB_AV
|
AVTAB_XPERMS
;
sattr
=
flex_array_get
(
policydb
.
type_attr_map_array
,
scontext
->
type
-
1
);
BUG_ON
(
!
sattr
);
tattr
=
flex_array_get
(
policydb
.
type_attr_map_array
,
tcontext
->
type
-
1
);
...
...
@@ -660,15 +694,18 @@ static void context_struct_compute_av(struct context *scontext,
node
;
node
=
avtab_search_node_next
(
node
,
avkey
.
specified
))
{
if
(
node
->
key
.
specified
==
AVTAB_ALLOWED
)
avd
->
allowed
|=
node
->
datum
.
data
;
avd
->
allowed
|=
node
->
datum
.
u
.
data
;
else
if
(
node
->
key
.
specified
==
AVTAB_AUDITALLOW
)
avd
->
auditallow
|=
node
->
datum
.
data
;
avd
->
auditallow
|=
node
->
datum
.
u
.
data
;
else
if
(
node
->
key
.
specified
==
AVTAB_AUDITDENY
)
avd
->
auditdeny
&=
node
->
datum
.
data
;
avd
->
auditdeny
&=
node
->
datum
.
u
.
data
;
else
if
(
xperms
&&
(
node
->
key
.
specified
&
AVTAB_XPERMS
))
services_compute_xperms_drivers
(
xperms
,
node
);
}
/* Check conditional av table for additional permissions */
cond_compute_av
(
&
policydb
.
te_cond_avtab
,
&
avkey
,
avd
);
cond_compute_av
(
&
policydb
.
te_cond_avtab
,
&
avkey
,
avd
,
xperms
);
}
}
...
...
@@ -899,6 +936,139 @@ static void avd_init(struct av_decision *avd)
avd
->
flags
=
0
;
}
void
services_compute_xperms_decision
(
struct
extended_perms_decision
*
xpermd
,
struct
avtab_node
*
node
)
{
unsigned
int
i
;
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLFUNCTION
)
{
if
(
xpermd
->
driver
!=
node
->
datum
.
u
.
xperms
->
driver
)
return
;
}
else
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLDRIVER
)
{
if
(
!
security_xperm_test
(
node
->
datum
.
u
.
xperms
->
perms
.
p
,
xpermd
->
driver
))
return
;
}
else
{
BUG
();
}
if
(
node
->
key
.
specified
==
AVTAB_XPERMS_ALLOWED
)
{
xpermd
->
used
|=
XPERMS_ALLOWED
;
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLDRIVER
)
{
memset
(
xpermd
->
allowed
->
p
,
0xff
,
sizeof
(
xpermd
->
allowed
->
p
));
}
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLFUNCTION
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
xpermd
->
allowed
->
p
);
i
++
)
xpermd
->
allowed
->
p
[
i
]
|=
node
->
datum
.
u
.
xperms
->
perms
.
p
[
i
];
}
}
else
if
(
node
->
key
.
specified
==
AVTAB_XPERMS_AUDITALLOW
)
{
xpermd
->
used
|=
XPERMS_AUDITALLOW
;
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLDRIVER
)
{
memset
(
xpermd
->
auditallow
->
p
,
0xff
,
sizeof
(
xpermd
->
auditallow
->
p
));
}
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLFUNCTION
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
xpermd
->
auditallow
->
p
);
i
++
)
xpermd
->
auditallow
->
p
[
i
]
|=
node
->
datum
.
u
.
xperms
->
perms
.
p
[
i
];
}
}
else
if
(
node
->
key
.
specified
==
AVTAB_XPERMS_DONTAUDIT
)
{
xpermd
->
used
|=
XPERMS_DONTAUDIT
;
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLDRIVER
)
{
memset
(
xpermd
->
dontaudit
->
p
,
0xff
,
sizeof
(
xpermd
->
dontaudit
->
p
));
}
if
(
node
->
datum
.
u
.
xperms
->
specified
==
AVTAB_XPERMS_IOCTLFUNCTION
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
xpermd
->
dontaudit
->
p
);
i
++
)
xpermd
->
dontaudit
->
p
[
i
]
|=
node
->
datum
.
u
.
xperms
->
perms
.
p
[
i
];
}
}
else
{
BUG
();
}
}
void
security_compute_xperms_decision
(
u32
ssid
,
u32
tsid
,
u16
orig_tclass
,
u8
driver
,
struct
extended_perms_decision
*
xpermd
)
{
u16
tclass
;
struct
context
*
scontext
,
*
tcontext
;
struct
avtab_key
avkey
;
struct
avtab_node
*
node
;
struct
ebitmap
*
sattr
,
*
tattr
;
struct
ebitmap_node
*
snode
,
*
tnode
;
unsigned
int
i
,
j
;
xpermd
->
driver
=
driver
;
xpermd
->
used
=
0
;
memset
(
xpermd
->
allowed
->
p
,
0
,
sizeof
(
xpermd
->
allowed
->
p
));
memset
(
xpermd
->
auditallow
->
p
,
0
,
sizeof
(
xpermd
->
auditallow
->
p
));
memset
(
xpermd
->
dontaudit
->
p
,
0
,
sizeof
(
xpermd
->
dontaudit
->
p
));
read_lock
(
&
policy_rwlock
);
if
(
!
ss_initialized
)
goto
allow
;
scontext
=
sidtab_search
(
&
sidtab
,
ssid
);
if
(
!
scontext
)
{
printk
(
KERN_ERR
"SELinux: %s: unrecognized SID %d
\n
"
,
__func__
,
ssid
);
goto
out
;
}
tcontext
=
sidtab_search
(
&
sidtab
,
tsid
);
if
(
!
tcontext
)
{
printk
(
KERN_ERR
"SELinux: %s: unrecognized SID %d
\n
"
,
__func__
,
tsid
);
goto
out
;
}
tclass
=
unmap_class
(
orig_tclass
);
if
(
unlikely
(
orig_tclass
&&
!
tclass
))
{
if
(
policydb
.
allow_unknown
)
goto
allow
;
goto
out
;
}
if
(
unlikely
(
!
tclass
||
tclass
>
policydb
.
p_classes
.
nprim
))
{
pr_warn_ratelimited
(
"SELinux: Invalid class %hu
\n
"
,
tclass
);
goto
out
;
}
avkey
.
target_class
=
tclass
;
avkey
.
specified
=
AVTAB_XPERMS
;
sattr
=
flex_array_get
(
policydb
.
type_attr_map_array
,
scontext
->
type
-
1
);
BUG_ON
(
!
sattr
);
tattr
=
flex_array_get
(
policydb
.
type_attr_map_array
,
tcontext
->
type
-
1
);
BUG_ON
(
!
tattr
);
ebitmap_for_each_positive_bit
(
sattr
,
snode
,
i
)
{
ebitmap_for_each_positive_bit
(
tattr
,
tnode
,
j
)
{
avkey
.
source_type
=
i
+
1
;
avkey
.
target_type
=
j
+
1
;
for
(
node
=
avtab_search_node
(
&
policydb
.
te_avtab
,
&
avkey
);
node
;
node
=
avtab_search_node_next
(
node
,
avkey
.
specified
))
services_compute_xperms_decision
(
xpermd
,
node
);
cond_compute_xperms
(
&
policydb
.
te_cond_avtab
,
&
avkey
,
xpermd
);
}
}
out:
read_unlock
(
&
policy_rwlock
);
return
;
allow:
memset
(
xpermd
->
allowed
->
p
,
0xff
,
sizeof
(
xpermd
->
allowed
->
p
));
goto
out
;
}
/**
* security_compute_av - Compute access vector decisions.
...
...
@@ -906,6 +1076,7 @@ static void avd_init(struct av_decision *avd)
* @tsid: target security identifier
* @tclass: target security class
* @avd: access vector decisions
* @xperms: extended permissions
*
* Compute a set of access vector decisions based on the
* SID pair (@ssid, @tsid) for the permissions in @tclass.
...
...
@@ -913,13 +1084,15 @@ static void avd_init(struct av_decision *avd)
void
security_compute_av
(
u32
ssid
,
u32
tsid
,
u16
orig_tclass
,
struct
av_decision
*
avd
)
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
)
{
u16
tclass
;
struct
context
*
scontext
=
NULL
,
*
tcontext
=
NULL
;
read_lock
(
&
policy_rwlock
);
avd_init
(
avd
);
xperms
->
len
=
0
;
if
(
!
ss_initialized
)
goto
allow
;
...
...
@@ -947,7 +1120,7 @@ void security_compute_av(u32 ssid,
goto
allow
;
goto
out
;
}
context_struct_compute_av
(
scontext
,
tcontext
,
tclass
,
avd
);
context_struct_compute_av
(
scontext
,
tcontext
,
tclass
,
avd
,
xperms
);
map_decision
(
orig_tclass
,
avd
,
policydb
.
allow_unknown
);
out:
read_unlock
(
&
policy_rwlock
);
...
...
@@ -993,7 +1166,7 @@ void security_compute_av_user(u32 ssid,
goto
out
;
}
context_struct_compute_av
(
scontext
,
tcontext
,
tclass
,
avd
);
context_struct_compute_av
(
scontext
,
tcontext
,
tclass
,
avd
,
NULL
);
out:
read_unlock
(
&
policy_rwlock
);
return
;
...
...
@@ -1515,7 +1688,7 @@ static int security_compute_sid(u32 ssid,
if
(
avdatum
)
{
/* Use the type from the type transition/member/change rule. */
newcontext
.
type
=
avdatum
->
data
;
newcontext
.
type
=
avdatum
->
u
.
data
;
}
/* if we have a objname this is a file trans check so check those rules */
...
...
This diff is collapsed.
Click to expand it.
security/selinux/ss/services.h
浏览文件 @
3e5f206c
...
...
@@ -11,5 +11,11 @@
extern
struct
policydb
policydb
;
void
services_compute_xperms_drivers
(
struct
extended_perms
*
xperms
,
struct
avtab_node
*
node
);
void
services_compute_xperms_decision
(
struct
extended_perms_decision
*
xpermd
,
struct
avtab_node
*
node
);
#endif
/* _SS_SERVICES_H_ */
This diff is collapsed.
Click to expand it.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录
新手
引导
客服
返回
顶部