Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
a002951c
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 大约 4 年
通知
14
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看板
提交
a002951c
编写于
3月 16, 2011
作者:
J
James Morris
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next' into for-linus
上级
521cb40b
c151694b
变更
85
隐藏空白更改
内联
并排
Showing
85 changed file
with
1549 addition
and
712 deletion
+1549
-712
Documentation/keys-request-key.txt
Documentation/keys-request-key.txt
+5
-4
Documentation/keys.txt
Documentation/keys.txt
+24
-4
arch/x86/Kconfig
arch/x86/Kconfig
+5
-0
fs/btrfs/inode.c
fs/btrfs/inode.c
+7
-6
fs/btrfs/xattr.c
fs/btrfs/xattr.c
+4
-2
fs/btrfs/xattr.h
fs/btrfs/xattr.h
+2
-1
fs/cachefiles/namei.c
fs/cachefiles/namei.c
+44
-8
fs/ext2/ext2.h
fs/ext2/ext2.h
+1
-1
fs/ext2/ialloc.c
fs/ext2/ialloc.c
+3
-2
fs/ext2/namei.c
fs/ext2/namei.c
+4
-4
fs/ext2/xattr.h
fs/ext2/xattr.h
+4
-2
fs/ext2/xattr_security.c
fs/ext2/xattr_security.c
+3
-2
fs/ext3/ialloc.c
fs/ext3/ialloc.c
+3
-2
fs/ext3/namei.c
fs/ext3/namei.c
+4
-4
fs/ext3/xattr.h
fs/ext3/xattr.h
+2
-2
fs/ext3/xattr_security.c
fs/ext3/xattr_security.c
+3
-2
fs/ext4/ialloc.c
fs/ext4/ialloc.c
+1
-1
fs/ext4/xattr.h
fs/ext4/xattr.h
+2
-2
fs/ext4/xattr_security.c
fs/ext4/xattr_security.c
+3
-2
fs/file_table.c
fs/file_table.c
+4
-1
fs/gfs2/inode.c
fs/gfs2/inode.c
+4
-3
fs/jffs2/dir.c
fs/jffs2/dir.c
+4
-5
fs/jffs2/nodelist.h
fs/jffs2/nodelist.h
+1
-1
fs/jffs2/security.c
fs/jffs2/security.c
+3
-2
fs/jffs2/write.c
fs/jffs2/write.c
+10
-8
fs/jffs2/xattr.h
fs/jffs2/xattr.h
+3
-2
fs/jfs/jfs_xattr.h
fs/jfs/jfs_xattr.h
+3
-2
fs/jfs/namei.c
fs/jfs/namei.c
+4
-4
fs/jfs/xattr.c
fs/jfs/xattr.c
+4
-2
fs/namespace.c
fs/namespace.c
+4
-0
fs/ocfs2/namei.c
fs/ocfs2/namei.c
+2
-2
fs/ocfs2/refcounttree.c
fs/ocfs2/refcounttree.c
+2
-1
fs/ocfs2/xattr.c
fs/ocfs2/xattr.c
+6
-4
fs/ocfs2/xattr.h
fs/ocfs2/xattr.h
+3
-1
fs/open.c
fs/open.c
+2
-1
fs/proc/proc_sysctl.c
fs/proc/proc_sysctl.c
+0
-1
fs/reiserfs/namei.c
fs/reiserfs/namei.c
+5
-4
fs/reiserfs/xattr_security.c
fs/reiserfs/xattr_security.c
+2
-1
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_iops.c
+5
-4
include/linux/ext3_fs.h
include/linux/ext3_fs.h
+2
-1
include/linux/fs.h
include/linux/fs.h
+21
-2
include/linux/ima.h
include/linux/ima.h
+0
-6
include/linux/key-type.h
include/linux/key-type.h
+13
-1
include/linux/key.h
include/linux/key.h
+5
-0
include/linux/keyctl.h
include/linux/keyctl.h
+2
-0
include/linux/reiserfs_xattr.h
include/linux/reiserfs_xattr.h
+2
-0
include/linux/security.h
include/linux/security.h
+20
-15
include/linux/xattr.h
include/linux/xattr.h
+2
-0
kernel/sysctl.c
kernel/sysctl.c
+0
-5
mm/shmem.c
mm/shmem.c
+5
-4
net/rxrpc/ar-key.c
net/rxrpc/ar-key.c
+19
-0
scripts/selinux/genheaders/genheaders.c
scripts/selinux/genheaders/genheaders.c
+20
-0
security/apparmor/Makefile
security/apparmor/Makefile
+33
-5
security/apparmor/lsm.c
security/apparmor/lsm.c
+0
-2
security/capability.c
security/capability.c
+8
-7
security/integrity/ima/ima.h
security/integrity/ima/ima.h
+1
-2
security/integrity/ima/ima_api.c
security/integrity/ima/ima_api.c
+3
-10
security/integrity/ima/ima_iint.c
security/integrity/ima/ima_iint.c
+0
-5
security/integrity/ima/ima_main.c
security/integrity/ima/ima_main.c
+16
-120
security/keys/compat.c
security/keys/compat.c
+50
-0
security/keys/encrypted.c
security/keys/encrypted.c
+1
-2
security/keys/internal.h
security/keys/internal.h
+8
-0
security/keys/key.c
security/keys/key.c
+19
-8
security/keys/keyctl.c
security/keys/keyctl.c
+134
-9
security/keys/keyring.c
security/keys/keyring.c
+2
-2
security/keys/request_key.c
security/keys/request_key.c
+1
-1
security/keys/trusted.c
security/keys/trusted.c
+1
-2
security/keys/user_defined.c
security/keys/user_defined.c
+1
-2
security/security.c
security/security.c
+12
-7
security/selinux/hooks.c
security/selinux/hooks.c
+188
-162
security/selinux/include/classmap.h
security/selinux/include/classmap.h
+5
-2
security/selinux/include/security.h
security/selinux/include/security.h
+5
-3
security/selinux/ss/avtab.h
security/selinux/ss/avtab.h
+11
-12
security/selinux/ss/ebitmap.h
security/selinux/ss/ebitmap.h
+0
-1
security/selinux/ss/mls.c
security/selinux/ss/mls.c
+3
-2
security/selinux/ss/mls.h
security/selinux/ss/mls.h
+2
-1
security/selinux/ss/policydb.c
security/selinux/ss/policydb.c
+130
-0
security/selinux/ss/policydb.h
security/selinux/ss/policydb.h
+13
-1
security/selinux/ss/services.c
security/selinux/ss/services.c
+55
-18
security/selinux/xfrm.c
security/selinux/xfrm.c
+1
-1
security/smack/smack.h
security/smack/smack.h
+6
-11
security/smack/smack_access.c
security/smack/smack_access.c
+34
-18
security/smack/smack_lsm.c
security/smack/smack_lsm.c
+244
-43
security/smack/smackfs.c
security/smack/smackfs.c
+255
-115
security/tomoyo/file.c
security/tomoyo/file.c
+1
-4
未找到文件。
Documentation/keys-request-key.txt
浏览文件 @
a002951c
...
...
@@ -127,14 +127,15 @@ This is because process A's keyrings can't simply be attached to
of them, and (b) it requires the same UID/GID/Groups all the way through.
======================
NEGATIVE INSTANTIATION
======================
======================
==============
NEGATIVE INSTANTIATION
AND REJECTION
======================
==============
Rather than instantiating a key, it is possible for the possessor of an
authorisation key to negatively instantiate a key that's under construction.
This is a short duration placeholder that causes any attempt at re-requesting
the key whilst it exists to fail with error ENOKEY.
the key whilst it exists to fail with error ENOKEY if negated or the specified
error if rejected.
This is provided to prevent excessive repeated spawning of /sbin/request-key
processes for a key that will never be obtainable.
...
...
Documentation/keys.txt
浏览文件 @
a002951c
...
...
@@ -637,6 +637,9 @@ The keyctl syscall functions are:
long keyctl(KEYCTL_INSTANTIATE, key_serial_t key,
const void *payload, size_t plen,
key_serial_t keyring);
long keyctl(KEYCTL_INSTANTIATE_IOV, key_serial_t key,
const struct iovec *payload_iov, unsigned ioc,
key_serial_t keyring);
If the kernel calls back to userspace to complete the instantiation of a
key, userspace should use this call to supply data for the key before the
...
...
@@ -652,11 +655,16 @@ The keyctl syscall functions are:
The payload and plen arguments describe the payload data as for add_key().
The payload_iov and ioc arguments describe the payload data in an iovec
array instead of a single buffer.
(*) Negatively instantiate a partially constructed key.
long keyctl(KEYCTL_NEGATE, key_serial_t key,
unsigned timeout, key_serial_t keyring);
long keyctl(KEYCTL_REJECT, key_serial_t key,
unsigned timeout, unsigned error, key_serial_t keyring);
If the kernel calls back to userspace to complete the instantiation of a
key, userspace should use this call mark the key as negative before the
...
...
@@ -669,6 +677,10 @@ The keyctl syscall functions are:
that keyring, however all the constraints applying in KEYCTL_LINK apply in
this case too.
If the key is rejected, future searches for it will return the specified
error code until the rejected key expires. Negating the key is the same
as rejecting the key with ENOKEY as the error code.
(*) Set the default request-key destination keyring.
...
...
@@ -1062,6 +1074,13 @@ The structure has a number of fields, some of which are mandatory:
viable.
(*) int (*vet_description)(const char *description);
This optional method is called to vet a key description. If the key type
doesn't approve of the key description, it may return an error, otherwise
it should return 0.
(*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
This method is called to attach a payload to a key during construction.
...
...
@@ -1231,10 +1250,11 @@ hand the request off to (perhaps a path held in placed in another key by, for
example, the KDE desktop manager).
The program (or whatever it calls) should finish construction of the key by
calling KEYCTL_INSTANTIATE, which also permits it to cache the key in one of
the keyrings (probably the session ring) before returning. Alternatively, the
key can be marked as negative with KEYCTL_NEGATE; this also permits the key to
be cached in one of the keyrings.
calling KEYCTL_INSTANTIATE or KEYCTL_INSTANTIATE_IOV, which also permits it to
cache the key in one of the keyrings (probably the session ring) before
returning. Alternatively, the key can be marked as negative with KEYCTL_NEGATE
or KEYCTL_REJECT; this also permits the key to be cached in one of the
keyrings.
If it returns with the key remaining in the unconstructed state, the key will
be marked as being negative, it will be added to the session keyring, and an
...
...
arch/x86/Kconfig
浏览文件 @
a002951c
...
...
@@ -2138,6 +2138,11 @@ config SYSVIPC_COMPAT
def_bool y
depends on COMPAT && SYSVIPC
config KEYS_COMPAT
bool
depends on COMPAT && KEYS
default y
endmenu
...
...
fs/btrfs/inode.c
浏览文件 @
a002951c
...
...
@@ -90,13 +90,14 @@ static noinline int cow_file_range(struct inode *inode,
unsigned
long
*
nr_written
,
int
unlock
);
static
int
btrfs_init_inode_security
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
inode
*
dir
)
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
int
err
;
err
=
btrfs_init_acl
(
trans
,
inode
,
dir
);
if
(
!
err
)
err
=
btrfs_xattr_security_init
(
trans
,
inode
,
dir
);
err
=
btrfs_xattr_security_init
(
trans
,
inode
,
dir
,
qstr
);
return
err
;
}
...
...
@@ -4704,7 +4705,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
if
(
IS_ERR
(
inode
))
goto
out_unlock
;
err
=
btrfs_init_inode_security
(
trans
,
inode
,
dir
);
err
=
btrfs_init_inode_security
(
trans
,
inode
,
dir
,
&
dentry
->
d_name
);
if
(
err
)
{
drop_inode
=
1
;
goto
out_unlock
;
...
...
@@ -4765,7 +4766,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
if
(
IS_ERR
(
inode
))
goto
out_unlock
;
err
=
btrfs_init_inode_security
(
trans
,
inode
,
dir
);
err
=
btrfs_init_inode_security
(
trans
,
inode
,
dir
,
&
dentry
->
d_name
);
if
(
err
)
{
drop_inode
=
1
;
goto
out_unlock
;
...
...
@@ -4894,7 +4895,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
drop_on_err
=
1
;
err
=
btrfs_init_inode_security
(
trans
,
inode
,
dir
);
err
=
btrfs_init_inode_security
(
trans
,
inode
,
dir
,
&
dentry
->
d_name
);
if
(
err
)
goto
out_fail
;
...
...
@@ -7106,7 +7107,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
if
(
IS_ERR
(
inode
))
goto
out_unlock
;
err
=
btrfs_init_inode_security
(
trans
,
inode
,
dir
);
err
=
btrfs_init_inode_security
(
trans
,
inode
,
dir
,
&
dentry
->
d_name
);
if
(
err
)
{
drop_inode
=
1
;
goto
out_unlock
;
...
...
fs/btrfs/xattr.c
浏览文件 @
a002951c
...
...
@@ -370,7 +370,8 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
}
int
btrfs_xattr_security_init
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
inode
*
dir
)
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
int
err
;
size_t
len
;
...
...
@@ -378,7 +379,8 @@ int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
char
*
suffix
;
char
*
name
;
err
=
security_inode_init_security
(
inode
,
dir
,
&
suffix
,
&
value
,
&
len
);
err
=
security_inode_init_security
(
inode
,
dir
,
qstr
,
&
suffix
,
&
value
,
&
len
);
if
(
err
)
{
if
(
err
==
-
EOPNOTSUPP
)
return
0
;
...
...
fs/btrfs/xattr.h
浏览文件 @
a002951c
...
...
@@ -37,6 +37,7 @@ extern int btrfs_setxattr(struct dentry *dentry, const char *name,
extern
int
btrfs_removexattr
(
struct
dentry
*
dentry
,
const
char
*
name
);
extern
int
btrfs_xattr_security_init
(
struct
btrfs_trans_handle
*
trans
,
struct
inode
*
inode
,
struct
inode
*
dir
);
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
);
#endif
/* __XATTR__ */
fs/cachefiles/namei.c
浏览文件 @
a002951c
...
...
@@ -275,6 +275,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
bool
preemptive
)
{
struct
dentry
*
grave
,
*
trap
;
struct
path
path
,
path_to_graveyard
;
char
nbuffer
[
8
+
8
+
1
];
int
ret
;
...
...
@@ -287,10 +288,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
/* non-directories can just be unlinked */
if
(
!
S_ISDIR
(
rep
->
d_inode
->
i_mode
))
{
_debug
(
"unlink stale object"
);
ret
=
vfs_unlink
(
dir
->
d_inode
,
rep
);
if
(
preemptive
)
cachefiles_mark_object_buried
(
cache
,
rep
);
path
.
mnt
=
cache
->
mnt
;
path
.
dentry
=
dir
;
ret
=
security_path_unlink
(
&
path
,
rep
);
if
(
ret
<
0
)
{
cachefiles_io_error
(
cache
,
"Unlink security error"
);
}
else
{
ret
=
vfs_unlink
(
dir
->
d_inode
,
rep
);
if
(
preemptive
)
cachefiles_mark_object_buried
(
cache
,
rep
);
}
mutex_unlock
(
&
dir
->
d_inode
->
i_mutex
);
...
...
@@ -379,12 +388,23 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
}
/* attempt the rename */
ret
=
vfs_rename
(
dir
->
d_inode
,
rep
,
cache
->
graveyard
->
d_inode
,
grave
);
if
(
ret
!=
0
&&
ret
!=
-
ENOMEM
)
cachefiles_io_error
(
cache
,
"Rename failed with error %d"
,
ret
);
path
.
mnt
=
cache
->
mnt
;
path
.
dentry
=
dir
;
path_to_graveyard
.
mnt
=
cache
->
mnt
;
path_to_graveyard
.
dentry
=
cache
->
graveyard
;
ret
=
security_path_rename
(
&
path
,
rep
,
&
path_to_graveyard
,
grave
);
if
(
ret
<
0
)
{
cachefiles_io_error
(
cache
,
"Rename security error %d"
,
ret
);
}
else
{
ret
=
vfs_rename
(
dir
->
d_inode
,
rep
,
cache
->
graveyard
->
d_inode
,
grave
);
if
(
ret
!=
0
&&
ret
!=
-
ENOMEM
)
cachefiles_io_error
(
cache
,
"Rename failed with error %d"
,
ret
);
if
(
preemptive
)
cachefiles_mark_object_buried
(
cache
,
rep
);
if
(
preemptive
)
cachefiles_mark_object_buried
(
cache
,
rep
);
}
unlock_rename
(
cache
->
graveyard
,
dir
);
dput
(
grave
);
...
...
@@ -448,6 +468,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
{
struct
cachefiles_cache
*
cache
;
struct
dentry
*
dir
,
*
next
=
NULL
;
struct
path
path
;
unsigned
long
start
;
const
char
*
name
;
int
ret
,
nlen
;
...
...
@@ -458,6 +479,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
cache
=
container_of
(
parent
->
fscache
.
cache
,
struct
cachefiles_cache
,
cache
);
path
.
mnt
=
cache
->
mnt
;
ASSERT
(
parent
->
dentry
);
ASSERT
(
parent
->
dentry
->
d_inode
);
...
...
@@ -511,6 +533,10 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
if
(
ret
<
0
)
goto
create_error
;
path
.
dentry
=
dir
;
ret
=
security_path_mkdir
(
&
path
,
next
,
0
);
if
(
ret
<
0
)
goto
create_error
;
start
=
jiffies
;
ret
=
vfs_mkdir
(
dir
->
d_inode
,
next
,
0
);
cachefiles_hist
(
cachefiles_mkdir_histogram
,
start
);
...
...
@@ -536,6 +562,10 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
if
(
ret
<
0
)
goto
create_error
;
path
.
dentry
=
dir
;
ret
=
security_path_mknod
(
&
path
,
next
,
S_IFREG
,
0
);
if
(
ret
<
0
)
goto
create_error
;
start
=
jiffies
;
ret
=
vfs_create
(
dir
->
d_inode
,
next
,
S_IFREG
,
NULL
);
cachefiles_hist
(
cachefiles_create_histogram
,
start
);
...
...
@@ -692,6 +722,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
{
struct
dentry
*
subdir
;
unsigned
long
start
;
struct
path
path
;
int
ret
;
_enter
(
",,%s"
,
dirname
);
...
...
@@ -719,6 +750,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
_debug
(
"attempt mkdir"
);
path
.
mnt
=
cache
->
mnt
;
path
.
dentry
=
dir
;
ret
=
security_path_mkdir
(
&
path
,
subdir
,
0700
);
if
(
ret
<
0
)
goto
mkdir_error
;
ret
=
vfs_mkdir
(
dir
->
d_inode
,
subdir
,
0700
);
if
(
ret
<
0
)
goto
mkdir_error
;
...
...
fs/ext2/ext2.h
浏览文件 @
a002951c
...
...
@@ -110,7 +110,7 @@ extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
extern
void
ext2_set_link
(
struct
inode
*
,
struct
ext2_dir_entry_2
*
,
struct
page
*
,
struct
inode
*
,
int
);
/* ialloc.c */
extern
struct
inode
*
ext2_new_inode
(
struct
inode
*
,
int
);
extern
struct
inode
*
ext2_new_inode
(
struct
inode
*
,
int
,
const
struct
qstr
*
);
extern
void
ext2_free_inode
(
struct
inode
*
);
extern
unsigned
long
ext2_count_free_inodes
(
struct
super_block
*
);
extern
void
ext2_check_inodes_bitmap
(
struct
super_block
*
);
...
...
fs/ext2/ialloc.c
浏览文件 @
a002951c
...
...
@@ -429,7 +429,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
return
group
;
}
struct
inode
*
ext2_new_inode
(
struct
inode
*
dir
,
int
mode
)
struct
inode
*
ext2_new_inode
(
struct
inode
*
dir
,
int
mode
,
const
struct
qstr
*
qstr
)
{
struct
super_block
*
sb
;
struct
buffer_head
*
bitmap_bh
=
NULL
;
...
...
@@ -585,7 +586,7 @@ struct inode *ext2_new_inode(struct inode *dir, int mode)
if
(
err
)
goto
fail_free_drop
;
err
=
ext2_init_security
(
inode
,
di
r
);
err
=
ext2_init_security
(
inode
,
dir
,
qst
r
);
if
(
err
)
goto
fail_free_drop
;
...
...
fs/ext2/namei.c
浏览文件 @
a002951c
...
...
@@ -104,7 +104,7 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st
dquot_initialize
(
dir
);
inode
=
ext2_new_inode
(
dir
,
mode
);
inode
=
ext2_new_inode
(
dir
,
mode
,
&
dentry
->
d_name
);
if
(
IS_ERR
(
inode
))
return
PTR_ERR
(
inode
);
...
...
@@ -133,7 +133,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_
dquot_initialize
(
dir
);
inode
=
ext2_new_inode
(
dir
,
mode
);
inode
=
ext2_new_inode
(
dir
,
mode
,
&
dentry
->
d_name
);
err
=
PTR_ERR
(
inode
);
if
(
!
IS_ERR
(
inode
))
{
init_special_inode
(
inode
,
inode
->
i_mode
,
rdev
);
...
...
@@ -159,7 +159,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,
dquot_initialize
(
dir
);
inode
=
ext2_new_inode
(
dir
,
S_IFLNK
|
S_IRWXUGO
);
inode
=
ext2_new_inode
(
dir
,
S_IFLNK
|
S_IRWXUGO
,
&
dentry
->
d_name
);
err
=
PTR_ERR
(
inode
);
if
(
IS_ERR
(
inode
))
goto
out
;
...
...
@@ -230,7 +230,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
inode_inc_link_count
(
dir
);
inode
=
ext2_new_inode
(
dir
,
S_IFDIR
|
mod
e
);
inode
=
ext2_new_inode
(
dir
,
S_IFDIR
|
mode
,
&
dentry
->
d_nam
e
);
err
=
PTR_ERR
(
inode
);
if
(
IS_ERR
(
inode
))
goto
out_dir
;
...
...
fs/ext2/xattr.h
浏览文件 @
a002951c
...
...
@@ -116,9 +116,11 @@ exit_ext2_xattr(void)
# endif
/* CONFIG_EXT2_FS_XATTR */
#ifdef CONFIG_EXT2_FS_SECURITY
extern
int
ext2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
);
extern
int
ext2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
);
#else
static
inline
int
ext2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
)
static
inline
int
ext2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
return
0
;
}
...
...
fs/ext2/xattr_security.c
浏览文件 @
a002951c
...
...
@@ -47,14 +47,15 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,
}
int
ext2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
)
ext2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
int
err
;
size_t
len
;
void
*
value
;
char
*
name
;
err
=
security_inode_init_security
(
inode
,
dir
,
&
name
,
&
value
,
&
len
);
err
=
security_inode_init_security
(
inode
,
dir
,
qstr
,
&
name
,
&
value
,
&
len
);
if
(
err
)
{
if
(
err
==
-
EOPNOTSUPP
)
return
0
;
...
...
fs/ext3/ialloc.c
浏览文件 @
a002951c
...
...
@@ -404,7 +404,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
* For other inodes, search forward from the parent directory's block
* group to find a free inode.
*/
struct
inode
*
ext3_new_inode
(
handle_t
*
handle
,
struct
inode
*
dir
,
int
mode
)
struct
inode
*
ext3_new_inode
(
handle_t
*
handle
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
,
int
mode
)
{
struct
super_block
*
sb
;
struct
buffer_head
*
bitmap_bh
=
NULL
;
...
...
@@ -589,7 +590,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
if
(
err
)
goto
fail_free_drop
;
err
=
ext3_init_security
(
handle
,
inode
,
di
r
);
err
=
ext3_init_security
(
handle
,
inode
,
dir
,
qst
r
);
if
(
err
)
goto
fail_free_drop
;
...
...
fs/ext3/namei.c
浏览文件 @
a002951c
...
...
@@ -1710,7 +1710,7 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
if
(
IS_DIRSYNC
(
dir
))
handle
->
h_sync
=
1
;
inode
=
ext3_new_inode
(
handle
,
dir
,
mode
);
inode
=
ext3_new_inode
(
handle
,
dir
,
&
dentry
->
d_name
,
mode
);
err
=
PTR_ERR
(
inode
);
if
(
!
IS_ERR
(
inode
))
{
inode
->
i_op
=
&
ext3_file_inode_operations
;
...
...
@@ -1746,7 +1746,7 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
if
(
IS_DIRSYNC
(
dir
))
handle
->
h_sync
=
1
;
inode
=
ext3_new_inode
(
handle
,
dir
,
mode
);
inode
=
ext3_new_inode
(
handle
,
dir
,
&
dentry
->
d_name
,
mode
);
err
=
PTR_ERR
(
inode
);
if
(
!
IS_ERR
(
inode
))
{
init_special_inode
(
inode
,
inode
->
i_mode
,
rdev
);
...
...
@@ -1784,7 +1784,7 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
if
(
IS_DIRSYNC
(
dir
))
handle
->
h_sync
=
1
;
inode
=
ext3_new_inode
(
handle
,
dir
,
S_IFDIR
|
mode
);
inode
=
ext3_new_inode
(
handle
,
dir
,
&
dentry
->
d_name
,
S_IFDIR
|
mode
);
err
=
PTR_ERR
(
inode
);
if
(
IS_ERR
(
inode
))
goto
out_stop
;
...
...
@@ -2206,7 +2206,7 @@ static int ext3_symlink (struct inode * dir,
if
(
IS_DIRSYNC
(
dir
))
handle
->
h_sync
=
1
;
inode
=
ext3_new_inode
(
handle
,
dir
,
S_IFLNK
|
S_IRWXUGO
);
inode
=
ext3_new_inode
(
handle
,
dir
,
&
dentry
->
d_name
,
S_IFLNK
|
S_IRWXUGO
);
err
=
PTR_ERR
(
inode
);
if
(
IS_ERR
(
inode
))
goto
out_stop
;
...
...
fs/ext3/xattr.h
浏览文件 @
a002951c
...
...
@@ -128,10 +128,10 @@ exit_ext3_xattr(void)
#ifdef CONFIG_EXT3_FS_SECURITY
extern
int
ext3_init_security
(
handle_t
*
handle
,
struct
inode
*
inode
,
struct
inode
*
di
r
);
struct
inode
*
dir
,
const
struct
qstr
*
qst
r
);
#else
static
inline
int
ext3_init_security
(
handle_t
*
handle
,
struct
inode
*
inode
,
struct
inode
*
di
r
)
struct
inode
*
dir
,
const
struct
qstr
*
qst
r
)
{
return
0
;
}
...
...
fs/ext3/xattr_security.c
浏览文件 @
a002951c
...
...
@@ -49,14 +49,15 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,
}
int
ext3_init_security
(
handle_t
*
handle
,
struct
inode
*
inode
,
struct
inode
*
dir
)
ext3_init_security
(
handle_t
*
handle
,
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
int
err
;
size_t
len
;
void
*
value
;
char
*
name
;
err
=
security_inode_init_security
(
inode
,
dir
,
&
name
,
&
value
,
&
len
);
err
=
security_inode_init_security
(
inode
,
dir
,
qstr
,
&
name
,
&
value
,
&
len
);
if
(
err
)
{
if
(
err
==
-
EOPNOTSUPP
)
return
0
;
...
...
fs/ext4/ialloc.c
浏览文件 @
a002951c
...
...
@@ -1042,7 +1042,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
if
(
err
)
goto
fail_free_drop
;
err
=
ext4_init_security
(
handle
,
inode
,
dir
);
err
=
ext4_init_security
(
handle
,
inode
,
dir
,
qstr
);
if
(
err
)
goto
fail_free_drop
;
...
...
fs/ext4/xattr.h
浏览文件 @
a002951c
...
...
@@ -145,10 +145,10 @@ ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
#ifdef CONFIG_EXT4_FS_SECURITY
extern
int
ext4_init_security
(
handle_t
*
handle
,
struct
inode
*
inode
,
struct
inode
*
di
r
);
struct
inode
*
dir
,
const
struct
qstr
*
qst
r
);
#else
static
inline
int
ext4_init_security
(
handle_t
*
handle
,
struct
inode
*
inode
,
struct
inode
*
di
r
)
struct
inode
*
dir
,
const
struct
qstr
*
qst
r
)
{
return
0
;
}
...
...
fs/ext4/xattr_security.c
浏览文件 @
a002951c
...
...
@@ -49,14 +49,15 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name,
}
int
ext4_init_security
(
handle_t
*
handle
,
struct
inode
*
inode
,
struct
inode
*
dir
)
ext4_init_security
(
handle_t
*
handle
,
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
int
err
;
size_t
len
;
void
*
value
;
char
*
name
;
err
=
security_inode_init_security
(
inode
,
dir
,
&
name
,
&
value
,
&
len
);
err
=
security_inode_init_security
(
inode
,
dir
,
qstr
,
&
name
,
&
value
,
&
len
);
if
(
err
)
{
if
(
err
==
-
EOPNOTSUPP
)
return
0
;
...
...
fs/file_table.c
浏览文件 @
a002951c
...
...
@@ -190,7 +190,8 @@ struct file *alloc_file(struct path *path, fmode_t mode,
file_take_write
(
file
);
WARN_ON
(
mnt_clone_write
(
path
->
mnt
));
}
ima_counts_get
(
file
);
if
((
mode
&
(
FMODE_READ
|
FMODE_WRITE
))
==
FMODE_READ
)
i_readcount_inc
(
path
->
dentry
->
d_inode
);
return
file
;
}
EXPORT_SYMBOL
(
alloc_file
);
...
...
@@ -251,6 +252,8 @@ static void __fput(struct file *file)
fops_put
(
file
->
f_op
);
put_pid
(
file
->
f_owner
.
pid
);
file_sb_list_del
(
file
);
if
((
file
->
f_mode
&
(
FMODE_READ
|
FMODE_WRITE
))
==
FMODE_READ
)
i_readcount_dec
(
inode
);
if
(
file
->
f_mode
&
FMODE_WRITE
)
drop_file_write_access
(
file
);
file
->
f_path
.
dentry
=
NULL
;
...
...
fs/gfs2/inode.c
浏览文件 @
a002951c
...
...
@@ -763,14 +763,15 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
return
error
;
}
static
int
gfs2_security_init
(
struct
gfs2_inode
*
dip
,
struct
gfs2_inode
*
ip
)
static
int
gfs2_security_init
(
struct
gfs2_inode
*
dip
,
struct
gfs2_inode
*
ip
,
const
struct
qstr
*
qstr
)
{
int
err
;
size_t
len
;
void
*
value
;
char
*
name
;
err
=
security_inode_init_security
(
&
ip
->
i_inode
,
&
dip
->
i_inode
,
err
=
security_inode_init_security
(
&
ip
->
i_inode
,
&
dip
->
i_inode
,
qstr
,
&
name
,
&
value
,
&
len
);
if
(
err
)
{
...
...
@@ -854,7 +855,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if
(
error
)
goto
fail_gunlock2
;
error
=
gfs2_security_init
(
dip
,
GFS2_I
(
inode
));
error
=
gfs2_security_init
(
dip
,
GFS2_I
(
inode
)
,
name
);
if
(
error
)
goto
fail_gunlock2
;
...
...
fs/jffs2/dir.c
浏览文件 @
a002951c
...
...
@@ -215,8 +215,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
no chance of AB-BA deadlock involving its f->sem). */
mutex_unlock
(
&
f
->
sem
);
ret
=
jffs2_do_create
(
c
,
dir_f
,
f
,
ri
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
);
ret
=
jffs2_do_create
(
c
,
dir_f
,
f
,
ri
,
&
dentry
->
d_name
);
if
(
ret
)
goto
fail
;
...
...
@@ -386,7 +385,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
jffs2_complete_reservation
(
c
);
ret
=
jffs2_init_security
(
inode
,
dir_i
);
ret
=
jffs2_init_security
(
inode
,
dir_i
,
&
dentry
->
d_name
);
if
(
ret
)
goto
fail
;
...
...
@@ -530,7 +529,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
jffs2_complete_reservation
(
c
);
ret
=
jffs2_init_security
(
inode
,
dir_i
);
ret
=
jffs2_init_security
(
inode
,
dir_i
,
&
dentry
->
d_name
);
if
(
ret
)
goto
fail
;
...
...
@@ -703,7 +702,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
jffs2_complete_reservation
(
c
);
ret
=
jffs2_init_security
(
inode
,
dir_i
);
ret
=
jffs2_init_security
(
inode
,
dir_i
,
&
dentry
->
d_name
);
if
(
ret
)
goto
fail
;
...
...
fs/jffs2/nodelist.h
浏览文件 @
a002951c
...
...
@@ -401,7 +401,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
struct
jffs2_raw_inode
*
ri
,
unsigned
char
*
buf
,
uint32_t
offset
,
uint32_t
writelen
,
uint32_t
*
retlen
);
int
jffs2_do_create
(
struct
jffs2_sb_info
*
c
,
struct
jffs2_inode_info
*
dir_f
,
struct
jffs2_inode_info
*
f
,
struct
jffs2_raw_inode
*
ri
,
const
char
*
name
,
int
namelen
);
struct
jffs2_raw_inode
*
ri
,
const
struct
qstr
*
qstr
);
int
jffs2_do_unlink
(
struct
jffs2_sb_info
*
c
,
struct
jffs2_inode_info
*
dir_f
,
const
char
*
name
,
int
namelen
,
struct
jffs2_inode_info
*
dead_f
,
uint32_t
time
);
int
jffs2_do_link
(
struct
jffs2_sb_info
*
c
,
struct
jffs2_inode_info
*
dir_f
,
uint32_t
ino
,
...
...
fs/jffs2/security.c
浏览文件 @
a002951c
...
...
@@ -23,14 +23,15 @@
#include "nodelist.h"
/* ---- Initial Security Label Attachment -------------- */
int
jffs2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
)
int
jffs2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
int
rc
;
size_t
len
;
void
*
value
;
char
*
name
;
rc
=
security_inode_init_security
(
inode
,
dir
,
&
name
,
&
value
,
&
len
);
rc
=
security_inode_init_security
(
inode
,
dir
,
qstr
,
&
name
,
&
value
,
&
len
);
if
(
rc
)
{
if
(
rc
==
-
EOPNOTSUPP
)
return
0
;
...
...
fs/jffs2/write.c
浏览文件 @
a002951c
...
...
@@ -424,7 +424,9 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
return
ret
;
}
int
jffs2_do_create
(
struct
jffs2_sb_info
*
c
,
struct
jffs2_inode_info
*
dir_f
,
struct
jffs2_inode_info
*
f
,
struct
jffs2_raw_inode
*
ri
,
const
char
*
name
,
int
namelen
)
int
jffs2_do_create
(
struct
jffs2_sb_info
*
c
,
struct
jffs2_inode_info
*
dir_f
,
struct
jffs2_inode_info
*
f
,
struct
jffs2_raw_inode
*
ri
,
const
struct
qstr
*
qstr
)
{
struct
jffs2_raw_dirent
*
rd
;
struct
jffs2_full_dnode
*
fn
;
...
...
@@ -466,15 +468,15 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
mutex_unlock
(
&
f
->
sem
);
jffs2_complete_reservation
(
c
);
ret
=
jffs2_init_security
(
&
f
->
vfs_inode
,
&
dir_f
->
vfs_inode
);
ret
=
jffs2_init_security
(
&
f
->
vfs_inode
,
&
dir_f
->
vfs_inode
,
qstr
);
if
(
ret
)
return
ret
;
ret
=
jffs2_init_acl_post
(
&
f
->
vfs_inode
);
if
(
ret
)
return
ret
;
ret
=
jffs2_reserve_space
(
c
,
sizeof
(
*
rd
)
+
name
len
,
&
alloclen
,
ALLOC_NORMAL
,
JFFS2_SUMMARY_DIRENT_SIZE
(
name
len
));
ret
=
jffs2_reserve_space
(
c
,
sizeof
(
*
rd
)
+
qstr
->
len
,
&
alloclen
,
ALLOC_NORMAL
,
JFFS2_SUMMARY_DIRENT_SIZE
(
qstr
->
len
));
if
(
ret
)
{
/* Eep. */
...
...
@@ -493,19 +495,19 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
rd
->
magic
=
cpu_to_je16
(
JFFS2_MAGIC_BITMASK
);
rd
->
nodetype
=
cpu_to_je16
(
JFFS2_NODETYPE_DIRENT
);
rd
->
totlen
=
cpu_to_je32
(
sizeof
(
*
rd
)
+
name
len
);
rd
->
totlen
=
cpu_to_je32
(
sizeof
(
*
rd
)
+
qstr
->
len
);
rd
->
hdr_crc
=
cpu_to_je32
(
crc32
(
0
,
rd
,
sizeof
(
struct
jffs2_unknown_node
)
-
4
));
rd
->
pino
=
cpu_to_je32
(
dir_f
->
inocache
->
ino
);
rd
->
version
=
cpu_to_je32
(
++
dir_f
->
highest_version
);
rd
->
ino
=
ri
->
ino
;
rd
->
mctime
=
ri
->
ctime
;
rd
->
nsize
=
name
len
;
rd
->
nsize
=
qstr
->
len
;
rd
->
type
=
DT_REG
;
rd
->
node_crc
=
cpu_to_je32
(
crc32
(
0
,
rd
,
sizeof
(
*
rd
)
-
8
));
rd
->
name_crc
=
cpu_to_je32
(
crc32
(
0
,
name
,
name
len
));
rd
->
name_crc
=
cpu_to_je32
(
crc32
(
0
,
qstr
->
name
,
qstr
->
len
));
fd
=
jffs2_write_dirent
(
c
,
dir_f
,
rd
,
name
,
name
len
,
ALLOC_NORMAL
);
fd
=
jffs2_write_dirent
(
c
,
dir_f
,
rd
,
qstr
->
name
,
qstr
->
len
,
ALLOC_NORMAL
);
jffs2_free_raw_dirent
(
rd
);
...
...
fs/jffs2/xattr.h
浏览文件 @
a002951c
...
...
@@ -121,10 +121,11 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
#endif
/* CONFIG_JFFS2_FS_XATTR */
#ifdef CONFIG_JFFS2_FS_SECURITY
extern
int
jffs2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
);
extern
int
jffs2_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
);
extern
const
struct
xattr_handler
jffs2_security_xattr_handler
;
#else
#define jffs2_init_security(inode,dir) (0)
#define jffs2_init_security(inode,dir
,qstr
) (0)
#endif
/* CONFIG_JFFS2_FS_SECURITY */
#endif
/* _JFFS2_FS_XATTR_H_ */
fs/jfs/jfs_xattr.h
浏览文件 @
a002951c
...
...
@@ -62,10 +62,11 @@ extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
extern
int
jfs_removexattr
(
struct
dentry
*
,
const
char
*
);
#ifdef CONFIG_JFS_SECURITY
extern
int
jfs_init_security
(
tid_t
,
struct
inode
*
,
struct
inode
*
);
extern
int
jfs_init_security
(
tid_t
,
struct
inode
*
,
struct
inode
*
,
const
struct
qstr
*
);
#else
static
inline
int
jfs_init_security
(
tid_t
tid
,
struct
inode
*
inode
,
struct
inode
*
dir
)
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
return
0
;
}
...
...
fs/jfs/namei.c
浏览文件 @
a002951c
...
...
@@ -115,7 +115,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
if
(
rc
)
goto
out3
;
rc
=
jfs_init_security
(
tid
,
ip
,
dip
);
rc
=
jfs_init_security
(
tid
,
ip
,
dip
,
&
dentry
->
d_name
);
if
(
rc
)
{
txAbort
(
tid
,
0
);
goto
out3
;
...
...
@@ -253,7 +253,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
if
(
rc
)
goto
out3
;
rc
=
jfs_init_security
(
tid
,
ip
,
dip
);
rc
=
jfs_init_security
(
tid
,
ip
,
dip
,
&
dentry
->
d_name
);
if
(
rc
)
{
txAbort
(
tid
,
0
);
goto
out3
;
...
...
@@ -932,7 +932,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
mutex_lock_nested
(
&
JFS_IP
(
dip
)
->
commit_mutex
,
COMMIT_MUTEX_PARENT
);
mutex_lock_nested
(
&
JFS_IP
(
ip
)
->
commit_mutex
,
COMMIT_MUTEX_CHILD
);
rc
=
jfs_init_security
(
tid
,
ip
,
dip
);
rc
=
jfs_init_security
(
tid
,
ip
,
dip
,
&
dentry
->
d_name
);
if
(
rc
)
goto
out3
;
...
...
@@ -1395,7 +1395,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
if
(
rc
)
goto
out3
;
rc
=
jfs_init_security
(
tid
,
ip
,
dir
);
rc
=
jfs_init_security
(
tid
,
ip
,
dir
,
&
dentry
->
d_name
);
if
(
rc
)
{
txAbort
(
tid
,
0
);
goto
out3
;
...
...
fs/jfs/xattr.c
浏览文件 @
a002951c
...
...
@@ -1091,7 +1091,8 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
}
#ifdef CONFIG_JFS_SECURITY
int
jfs_init_security
(
tid_t
tid
,
struct
inode
*
inode
,
struct
inode
*
dir
)
int
jfs_init_security
(
tid_t
tid
,
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
int
rc
;
size_t
len
;
...
...
@@ -1099,7 +1100,8 @@ int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir)
char
*
suffix
;
char
*
name
;
rc
=
security_inode_init_security
(
inode
,
dir
,
&
suffix
,
&
value
,
&
len
);
rc
=
security_inode_init_security
(
inode
,
dir
,
qstr
,
&
suffix
,
&
value
,
&
len
);
if
(
rc
)
{
if
(
rc
==
-
EOPNOTSUPP
)
return
0
;
...
...
fs/namespace.c
浏览文件 @
a002951c
...
...
@@ -1767,6 +1767,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
if
(
path
->
dentry
!=
path
->
mnt
->
mnt_root
)
return
-
EINVAL
;
err
=
security_sb_remount
(
sb
,
data
);
if
(
err
)
return
err
;
down_write
(
&
sb
->
s_umount
);
if
(
flags
&
MS_BIND
)
err
=
change_mount_flags
(
path
->
mnt
,
flags
);
...
...
fs/ocfs2/namei.c
浏览文件 @
a002951c
...
...
@@ -293,7 +293,7 @@ static int ocfs2_mknod(struct inode *dir,
}
/* get security xattr */
status
=
ocfs2_init_security_get
(
inode
,
dir
,
&
si
);
status
=
ocfs2_init_security_get
(
inode
,
dir
,
&
dentry
->
d_name
,
&
si
);
if
(
status
)
{
if
(
status
==
-
EOPNOTSUPP
)
si
.
enable
=
0
;
...
...
@@ -1665,7 +1665,7 @@ static int ocfs2_symlink(struct inode *dir,
}
/* get security xattr */
status
=
ocfs2_init_security_get
(
inode
,
dir
,
&
si
);
status
=
ocfs2_init_security_get
(
inode
,
dir
,
&
dentry
->
d_name
,
&
si
);
if
(
status
)
{
if
(
status
==
-
EOPNOTSUPP
)
si
.
enable
=
0
;
...
...
fs/ocfs2/refcounttree.c
浏览文件 @
a002951c
...
...
@@ -4328,7 +4328,8 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
/* If the security isn't preserved, we need to re-initialize them. */
if
(
!
preserve
)
{
error
=
ocfs2_init_security_and_acl
(
dir
,
new_orphan_inode
);
error
=
ocfs2_init_security_and_acl
(
dir
,
new_orphan_inode
,
&
new_dentry
->
d_name
);
if
(
error
)
mlog_errno
(
error
);
}
...
...
fs/ocfs2/xattr.c
浏览文件 @
a002951c
...
...
@@ -7185,7 +7185,8 @@ int ocfs2_reflink_xattrs(struct inode *old_inode,
* must not hold any lock expect i_mutex.
*/
int
ocfs2_init_security_and_acl
(
struct
inode
*
dir
,
struct
inode
*
inode
)
struct
inode
*
inode
,
const
struct
qstr
*
qstr
)
{
int
ret
=
0
;
struct
buffer_head
*
dir_bh
=
NULL
;
...
...
@@ -7193,7 +7194,7 @@ int ocfs2_init_security_and_acl(struct inode *dir,
.
enable
=
1
,
};
ret
=
ocfs2_init_security_get
(
inode
,
dir
,
&
si
);
ret
=
ocfs2_init_security_get
(
inode
,
dir
,
qstr
,
&
si
);
if
(
!
ret
)
{
ret
=
ocfs2_xattr_set
(
inode
,
OCFS2_XATTR_INDEX_SECURITY
,
si
.
name
,
si
.
value
,
si
.
value_len
,
...
...
@@ -7261,13 +7262,14 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
int
ocfs2_init_security_get
(
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
,
struct
ocfs2_security_xattr_info
*
si
)
{
/* check whether ocfs2 support feature xattr */
if
(
!
ocfs2_supports_xattr
(
OCFS2_SB
(
dir
->
i_sb
)))
return
-
EOPNOTSUPP
;
return
security_inode_init_security
(
inode
,
dir
,
&
si
->
name
,
&
si
->
valu
e
,
&
si
->
value_len
);
return
security_inode_init_security
(
inode
,
dir
,
qstr
,
&
si
->
nam
e
,
&
si
->
value
,
&
si
->
value
_len
);
}
int
ocfs2_init_security_set
(
handle_t
*
handle
,
...
...
fs/ocfs2/xattr.h
浏览文件 @
a002951c
...
...
@@ -57,6 +57,7 @@ int ocfs2_has_inline_xattr_value_outside(struct inode *inode,
struct
ocfs2_dinode
*
di
);
int
ocfs2_xattr_remove
(
struct
inode
*
,
struct
buffer_head
*
);
int
ocfs2_init_security_get
(
struct
inode
*
,
struct
inode
*
,
const
struct
qstr
*
,
struct
ocfs2_security_xattr_info
*
);
int
ocfs2_init_security_set
(
handle_t
*
,
struct
inode
*
,
struct
buffer_head
*
,
...
...
@@ -94,5 +95,6 @@ int ocfs2_reflink_xattrs(struct inode *old_inode,
struct
buffer_head
*
new_bh
,
bool
preserve_security
);
int
ocfs2_init_security_and_acl
(
struct
inode
*
dir
,
struct
inode
*
inode
);
struct
inode
*
inode
,
const
struct
qstr
*
qstr
);
#endif
/* OCFS2_XATTR_H */
fs/open.c
浏览文件 @
a002951c
...
...
@@ -701,7 +701,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
if
(
error
)
goto
cleanup_all
;
}
ima_counts_get
(
f
);
if
((
f
->
f_mode
&
(
FMODE_READ
|
FMODE_WRITE
))
==
FMODE_READ
)
i_readcount_inc
(
inode
);
f
->
f_flags
&=
~
(
O_CREAT
|
O_EXCL
|
O_NOCTTY
|
O_TRUNC
);
...
...
fs/proc/proc_sysctl.c
浏览文件 @
a002951c
...
...
@@ -32,7 +32,6 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
ei
->
sysctl_entry
=
table
;
inode
->
i_mtime
=
inode
->
i_atime
=
inode
->
i_ctime
=
CURRENT_TIME
;
inode
->
i_flags
|=
S_PRIVATE
;
/* tell selinux to ignore this inode */
inode
->
i_mode
=
table
->
mode
;
if
(
!
table
->
child
)
{
inode
->
i_mode
|=
S_IFREG
;
...
...
fs/reiserfs/namei.c
浏览文件 @
a002951c
...
...
@@ -593,7 +593,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
new_inode_init
(
inode
,
dir
,
mode
);
jbegin_count
+=
reiserfs_cache_default_acl
(
dir
);
retval
=
reiserfs_security_init
(
dir
,
inode
,
&
security
);
retval
=
reiserfs_security_init
(
dir
,
inode
,
&
dentry
->
d_name
,
&
security
);
if
(
retval
<
0
)
{
drop_new_inode
(
inode
);
return
retval
;
...
...
@@ -667,7 +667,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
new_inode_init
(
inode
,
dir
,
mode
);
jbegin_count
+=
reiserfs_cache_default_acl
(
dir
);
retval
=
reiserfs_security_init
(
dir
,
inode
,
&
security
);
retval
=
reiserfs_security_init
(
dir
,
inode
,
&
dentry
->
d_name
,
&
security
);
if
(
retval
<
0
)
{
drop_new_inode
(
inode
);
return
retval
;
...
...
@@ -747,7 +747,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
new_inode_init
(
inode
,
dir
,
mode
);
jbegin_count
+=
reiserfs_cache_default_acl
(
dir
);
retval
=
reiserfs_security_init
(
dir
,
inode
,
&
security
);
retval
=
reiserfs_security_init
(
dir
,
inode
,
&
dentry
->
d_name
,
&
security
);
if
(
retval
<
0
)
{
drop_new_inode
(
inode
);
return
retval
;
...
...
@@ -1032,7 +1032,8 @@ static int reiserfs_symlink(struct inode *parent_dir,
}
new_inode_init
(
inode
,
parent_dir
,
mode
);
retval
=
reiserfs_security_init
(
parent_dir
,
inode
,
&
security
);
retval
=
reiserfs_security_init
(
parent_dir
,
inode
,
&
dentry
->
d_name
,
&
security
);
if
(
retval
<
0
)
{
drop_new_inode
(
inode
);
return
retval
;
...
...
fs/reiserfs/xattr_security.c
浏览文件 @
a002951c
...
...
@@ -54,6 +54,7 @@ static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
* of blocks needed for the transaction. If successful, reiserfs_security
* must be released using reiserfs_security_free when the caller is done. */
int
reiserfs_security_init
(
struct
inode
*
dir
,
struct
inode
*
inode
,
const
struct
qstr
*
qstr
,
struct
reiserfs_security_handle
*
sec
)
{
int
blocks
=
0
;
...
...
@@ -65,7 +66,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
if
(
IS_PRIVATE
(
dir
))
return
0
;
error
=
security_inode_init_security
(
inode
,
dir
,
&
sec
->
name
,
error
=
security_inode_init_security
(
inode
,
dir
,
qstr
,
&
sec
->
name
,
&
sec
->
value
,
&
sec
->
length
);
if
(
error
)
{
if
(
error
==
-
EOPNOTSUPP
)
...
...
fs/xfs/linux-2.6/xfs_iops.c
浏览文件 @
a002951c
...
...
@@ -102,7 +102,8 @@ xfs_mark_inode_dirty(
STATIC
int
xfs_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
)
struct
inode
*
dir
,
const
struct
qstr
*
qstr
)
{
struct
xfs_inode
*
ip
=
XFS_I
(
inode
);
size_t
length
;
...
...
@@ -110,7 +111,7 @@ xfs_init_security(
unsigned
char
*
name
;
int
error
;
error
=
security_inode_init_security
(
inode
,
dir
,
(
char
**
)
&
name
,
error
=
security_inode_init_security
(
inode
,
dir
,
qstr
,
(
char
**
)
&
name
,
&
value
,
&
length
);
if
(
error
)
{
if
(
error
==
-
EOPNOTSUPP
)
...
...
@@ -194,7 +195,7 @@ xfs_vn_mknod(
inode
=
VFS_I
(
ip
);
error
=
xfs_init_security
(
inode
,
dir
);
error
=
xfs_init_security
(
inode
,
dir
,
&
dentry
->
d_name
);
if
(
unlikely
(
error
))
goto
out_cleanup_inode
;
...
...
@@ -367,7 +368,7 @@ xfs_vn_symlink(
inode
=
VFS_I
(
cip
);
error
=
xfs_init_security
(
inode
,
dir
);
error
=
xfs_init_security
(
inode
,
dir
,
&
dentry
->
d_name
);
if
(
unlikely
(
error
))
goto
out_cleanup_inode
;
...
...
include/linux/ext3_fs.h
浏览文件 @
a002951c
...
...
@@ -884,7 +884,8 @@ extern int ext3fs_dirhash(const char *name, int len, struct
dx_hash_info
*
hinfo
);
/* ialloc.c */
extern
struct
inode
*
ext3_new_inode
(
handle_t
*
,
struct
inode
*
,
int
);
extern
struct
inode
*
ext3_new_inode
(
handle_t
*
,
struct
inode
*
,
const
struct
qstr
*
,
int
);
extern
void
ext3_free_inode
(
handle_t
*
,
struct
inode
*
);
extern
struct
inode
*
ext3_orphan_get
(
struct
super_block
*
,
unsigned
long
);
extern
unsigned
long
ext3_count_free_inodes
(
struct
super_block
*
);
...
...
include/linux/fs.h
浏览文件 @
a002951c
...
...
@@ -798,8 +798,7 @@ struct inode {
#endif
#ifdef CONFIG_IMA
/* protected by i_lock */
unsigned
int
i_readcount
;
/* struct files open RO */
atomic_t
i_readcount
;
/* struct files open RO */
#endif
atomic_t
i_writecount
;
#ifdef CONFIG_SECURITY
...
...
@@ -2200,6 +2199,26 @@ static inline void allow_write_access(struct file *file)
if
(
file
)
atomic_inc
(
&
file
->
f_path
.
dentry
->
d_inode
->
i_writecount
);
}
#ifdef CONFIG_IMA
static
inline
void
i_readcount_dec
(
struct
inode
*
inode
)
{
BUG_ON
(
!
atomic_read
(
&
inode
->
i_readcount
));
atomic_dec
(
&
inode
->
i_readcount
);
}
static
inline
void
i_readcount_inc
(
struct
inode
*
inode
)
{
atomic_inc
(
&
inode
->
i_readcount
);
}
#else
static
inline
void
i_readcount_dec
(
struct
inode
*
inode
)
{
return
;
}
static
inline
void
i_readcount_inc
(
struct
inode
*
inode
)
{
return
;
}
#endif
extern
int
do_pipe_flags
(
int
*
,
int
);
extern
struct
file
*
create_read_pipe
(
struct
file
*
f
,
int
flags
);
extern
struct
file
*
create_write_pipe
(
int
flags
);
...
...
include/linux/ima.h
浏览文件 @
a002951c
...
...
@@ -20,7 +20,6 @@ extern void ima_inode_free(struct inode *inode);
extern
int
ima_file_check
(
struct
file
*
file
,
int
mask
);
extern
void
ima_file_free
(
struct
file
*
file
);
extern
int
ima_file_mmap
(
struct
file
*
file
,
unsigned
long
prot
);
extern
void
ima_counts_get
(
struct
file
*
file
);
#else
static
inline
int
ima_bprm_check
(
struct
linux_binprm
*
bprm
)
...
...
@@ -53,10 +52,5 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
return
0
;
}
static
inline
void
ima_counts_get
(
struct
file
*
file
)
{
return
;
}
#endif
/* CONFIG_IMA_H */
#endif
/* _LINUX_IMA_H */
include/linux/key-type.h
浏览文件 @
a002951c
...
...
@@ -41,6 +41,9 @@ struct key_type {
*/
size_t
def_datalen
;
/* vet a description */
int
(
*
vet_description
)(
const
char
*
description
);
/* instantiate a key of this type
* - this method should call key_payload_reserve() to determine if the
* user's quota will hold the payload
...
...
@@ -102,11 +105,20 @@ extern int key_instantiate_and_link(struct key *key,
size_t
datalen
,
struct
key
*
keyring
,
struct
key
*
instkey
);
extern
int
key_
negate
_and_link
(
struct
key
*
key
,
extern
int
key_
reject
_and_link
(
struct
key
*
key
,
unsigned
timeout
,
unsigned
error
,
struct
key
*
keyring
,
struct
key
*
instkey
);
extern
void
complete_request_key
(
struct
key_construction
*
cons
,
int
error
);
static
inline
int
key_negate_and_link
(
struct
key
*
key
,
unsigned
timeout
,
struct
key
*
keyring
,
struct
key
*
instkey
)
{
return
key_reject_and_link
(
key
,
timeout
,
ENOKEY
,
keyring
,
instkey
);
}
#endif
/* CONFIG_KEYS */
#endif
/* _LINUX_KEY_TYPE_H */
include/linux/key.h
浏览文件 @
a002951c
...
...
@@ -170,6 +170,7 @@ struct key {
struct
list_head
link
;
unsigned
long
x
[
2
];
void
*
p
[
2
];
int
reject_error
;
}
type_data
;
/* key data
...
...
@@ -275,6 +276,10 @@ static inline key_serial_t key_serial(struct key *key)
return
key
?
key
->
serial
:
0
;
}
#define rcu_dereference_key(KEY) \
(rcu_dereference_protected((KEY)->payload.rcudata, \
rwsem_is_locked(&((struct key *)(KEY))->sem)))
#ifdef CONFIG_SYSCTL
extern
ctl_table
key_sysctls
[];
#endif
...
...
include/linux/keyctl.h
浏览文件 @
a002951c
...
...
@@ -53,5 +53,7 @@
#define KEYCTL_ASSUME_AUTHORITY 16
/* assume request_key() authorisation */
#define KEYCTL_GET_SECURITY 17
/* get key security label */
#define KEYCTL_SESSION_TO_PARENT 18
/* apply session keyring to parent process */
#define KEYCTL_REJECT 19
/* reject a partially constructed key */
#define KEYCTL_INSTANTIATE_IOV 20
/* instantiate a partially constructed key */
#endif
/* _LINUX_KEYCTL_H */
include/linux/reiserfs_xattr.h
浏览文件 @
a002951c
...
...
@@ -63,6 +63,7 @@ extern const struct xattr_handler reiserfs_xattr_trusted_handler;
extern
const
struct
xattr_handler
reiserfs_xattr_security_handler
;
#ifdef CONFIG_REISERFS_FS_SECURITY
int
reiserfs_security_init
(
struct
inode
*
dir
,
struct
inode
*
inode
,
const
struct
qstr
*
qstr
,
struct
reiserfs_security_handle
*
sec
);
int
reiserfs_security_write
(
struct
reiserfs_transaction_handle
*
th
,
struct
inode
*
inode
,
...
...
@@ -130,6 +131,7 @@ static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
#ifndef CONFIG_REISERFS_FS_SECURITY
static
inline
int
reiserfs_security_init
(
struct
inode
*
dir
,
struct
inode
*
inode
,
const
struct
qstr
*
qstr
,
struct
reiserfs_security_handle
*
sec
)
{
return
0
;
...
...
include/linux/security.h
浏览文件 @
a002951c
...
...
@@ -25,6 +25,7 @@
#include <linux/fs.h>
#include <linux/fsnotify.h>
#include <linux/binfmts.h>
#include <linux/dcache.h>
#include <linux/signal.h>
#include <linux/resource.h>
#include <linux/sem.h>
...
...
@@ -267,6 +268,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @orig the original mount data copied from userspace.
* @copy copied data which will be passed to the security module.
* Returns 0 if the copy was successful.
* @sb_remount:
* Extracts security system specifc mount options and verifys no changes
* are being made to those options.
* @sb superblock being remounted
* @data contains the filesystem-specific data.
* Return 0 if permission is granted.
* @sb_umount:
* Check permission before the @mnt file system is unmounted.
* @mnt contains the mounted file system.
...
...
@@ -315,6 +322,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* then it should return -EOPNOTSUPP to skip this processing.
* @inode contains the inode structure of the newly created inode.
* @dir contains the inode structure of the parent directory.
* @qstr contains the last path component of the new object
* @name will be set to the allocated name suffix (e.g. selinux).
* @value will be set to the allocated attribute value.
* @len will be set to the length of the value.
...
...
@@ -1257,12 +1265,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @cap contains the capability <include/linux/capability.h>.
* @audit: Whether to write an audit message or not
* Return 0 if the capability is granted for @tsk.
* @sysctl:
* Check permission before accessing the @table sysctl variable in the
* manner specified by @op.
* @table contains the ctl_table structure for the sysctl variable.
* @op contains the operation (001 = search, 002 = write, 004 = read).
* Return 0 if permission is granted.
* @syslog:
* Check permission before accessing the kernel message ring or changing
* logging to the console.
...
...
@@ -1383,7 +1385,6 @@ struct security_operations {
const
kernel_cap_t
*
permitted
);
int
(
*
capable
)
(
struct
task_struct
*
tsk
,
const
struct
cred
*
cred
,
int
cap
,
int
audit
);
int
(
*
sysctl
)
(
struct
ctl_table
*
table
,
int
op
);
int
(
*
quotactl
)
(
int
cmds
,
int
type
,
int
id
,
struct
super_block
*
sb
);
int
(
*
quota_on
)
(
struct
dentry
*
dentry
);
int
(
*
syslog
)
(
int
type
);
...
...
@@ -1399,6 +1400,7 @@ struct security_operations {
int
(
*
sb_alloc_security
)
(
struct
super_block
*
sb
);
void
(
*
sb_free_security
)
(
struct
super_block
*
sb
);
int
(
*
sb_copy_data
)
(
char
*
orig
,
char
*
copy
);
int
(
*
sb_remount
)
(
struct
super_block
*
sb
,
void
*
data
);
int
(
*
sb_kern_mount
)
(
struct
super_block
*
sb
,
int
flags
,
void
*
data
);
int
(
*
sb_show_options
)
(
struct
seq_file
*
m
,
struct
super_block
*
sb
);
int
(
*
sb_statfs
)
(
struct
dentry
*
dentry
);
...
...
@@ -1435,7 +1437,8 @@ struct security_operations {
int
(
*
inode_alloc_security
)
(
struct
inode
*
inode
);
void
(
*
inode_free_security
)
(
struct
inode
*
inode
);
int
(
*
inode_init_security
)
(
struct
inode
*
inode
,
struct
inode
*
dir
,
char
**
name
,
void
**
value
,
size_t
*
len
);
const
struct
qstr
*
qstr
,
char
**
name
,
void
**
value
,
size_t
*
len
);
int
(
*
inode_create
)
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
int
mode
);
int
(
*
inode_link
)
(
struct
dentry
*
old_dentry
,
...
...
@@ -1665,7 +1668,6 @@ int security_capset(struct cred *new, const struct cred *old,
int
security_capable
(
const
struct
cred
*
cred
,
int
cap
);
int
security_real_capable
(
struct
task_struct
*
tsk
,
int
cap
);
int
security_real_capable_noaudit
(
struct
task_struct
*
tsk
,
int
cap
);
int
security_sysctl
(
struct
ctl_table
*
table
,
int
op
);
int
security_quotactl
(
int
cmds
,
int
type
,
int
id
,
struct
super_block
*
sb
);
int
security_quota_on
(
struct
dentry
*
dentry
);
int
security_syslog
(
int
type
);
...
...
@@ -1681,6 +1683,7 @@ int security_bprm_secureexec(struct linux_binprm *bprm);
int
security_sb_alloc
(
struct
super_block
*
sb
);
void
security_sb_free
(
struct
super_block
*
sb
);
int
security_sb_copy_data
(
char
*
orig
,
char
*
copy
);
int
security_sb_remount
(
struct
super_block
*
sb
,
void
*
data
);
int
security_sb_kern_mount
(
struct
super_block
*
sb
,
int
flags
,
void
*
data
);
int
security_sb_show_options
(
struct
seq_file
*
m
,
struct
super_block
*
sb
);
int
security_sb_statfs
(
struct
dentry
*
dentry
);
...
...
@@ -1696,7 +1699,8 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
int
security_inode_alloc
(
struct
inode
*
inode
);
void
security_inode_free
(
struct
inode
*
inode
);
int
security_inode_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
char
**
name
,
void
**
value
,
size_t
*
len
);
const
struct
qstr
*
qstr
,
char
**
name
,
void
**
value
,
size_t
*
len
);
int
security_inode_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
int
mode
);
int
security_inode_link
(
struct
dentry
*
old_dentry
,
struct
inode
*
dir
,
struct
dentry
*
new_dentry
);
...
...
@@ -1883,11 +1887,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap)
return
ret
;
}
static
inline
int
security_sysctl
(
struct
ctl_table
*
table
,
int
op
)
{
return
0
;
}
static
inline
int
security_quotactl
(
int
cmds
,
int
type
,
int
id
,
struct
super_block
*
sb
)
{
...
...
@@ -1964,6 +1963,11 @@ static inline int security_sb_copy_data(char *orig, char *copy)
return
0
;
}
static
inline
int
security_sb_remount
(
struct
super_block
*
sb
,
void
*
data
)
{
return
0
;
}
static
inline
int
security_sb_kern_mount
(
struct
super_block
*
sb
,
int
flags
,
void
*
data
)
{
return
0
;
...
...
@@ -2023,6 +2027,7 @@ static inline void security_inode_free(struct inode *inode)
static
inline
int
security_inode_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
const
struct
qstr
*
qstr
,
char
**
name
,
void
**
value
,
size_t
*
len
)
...
...
include/linux/xattr.h
浏览文件 @
a002951c
...
...
@@ -42,11 +42,13 @@
#define XATTR_SMACK_IPOUT "SMACK64IPOUT"
#define XATTR_SMACK_EXEC "SMACK64EXEC"
#define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE"
#define XATTR_SMACK_MMAP "SMACK64MMAP"
#define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX
#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
#define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC
#define XATTR_NAME_SMACKTRANSMUTE XATTR_SECURITY_PREFIX XATTR_SMACK_TRANSMUTE
#define XATTR_NAME_SMACKMMAP XATTR_SECURITY_PREFIX XATTR_SMACK_MMAP
#define XATTR_CAPS_SUFFIX "capability"
#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
...
...
kernel/sysctl.c
浏览文件 @
a002951c
...
...
@@ -1690,13 +1690,8 @@ static int test_perm(int mode, int op)
int
sysctl_perm
(
struct
ctl_table_root
*
root
,
struct
ctl_table
*
table
,
int
op
)
{
int
error
;
int
mode
;
error
=
security_sysctl
(
table
,
op
&
(
MAY_READ
|
MAY_WRITE
|
MAY_EXEC
));
if
(
error
)
return
error
;
if
(
root
->
permissions
)
mode
=
root
->
permissions
(
root
,
current
->
nsproxy
,
table
);
else
...
...
mm/shmem.c
浏览文件 @
a002951c
...
...
@@ -1843,8 +1843,9 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
inode
=
shmem_get_inode
(
dir
->
i_sb
,
dir
,
mode
,
dev
,
VM_NORESERVE
);
if
(
inode
)
{
error
=
security_inode_init_security
(
inode
,
dir
,
NULL
,
NULL
,
NULL
);
error
=
security_inode_init_security
(
inode
,
dir
,
&
dentry
->
d_name
,
NULL
,
NULL
,
NULL
);
if
(
error
)
{
if
(
error
!=
-
EOPNOTSUPP
)
{
iput
(
inode
);
...
...
@@ -1983,8 +1984,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
if
(
!
inode
)
return
-
ENOSPC
;
error
=
security_inode_init_security
(
inode
,
dir
,
NULL
,
NULL
,
NULL
);
error
=
security_inode_init_security
(
inode
,
dir
,
&
dentry
->
d_name
,
NULL
,
NULL
,
NULL
);
if
(
error
)
{
if
(
error
!=
-
EOPNOTSUPP
)
{
iput
(
inode
);
...
...
net/rxrpc/ar-key.c
浏览文件 @
a002951c
...
...
@@ -25,6 +25,7 @@
#include <keys/user-type.h>
#include "ar-internal.h"
static
int
rxrpc_vet_description_s
(
const
char
*
);
static
int
rxrpc_instantiate
(
struct
key
*
,
const
void
*
,
size_t
);
static
int
rxrpc_instantiate_s
(
struct
key
*
,
const
void
*
,
size_t
);
static
void
rxrpc_destroy
(
struct
key
*
);
...
...
@@ -52,12 +53,30 @@ EXPORT_SYMBOL(key_type_rxrpc);
*/
struct
key_type
key_type_rxrpc_s
=
{
.
name
=
"rxrpc_s"
,
.
vet_description
=
rxrpc_vet_description_s
,
.
instantiate
=
rxrpc_instantiate_s
,
.
match
=
user_match
,
.
destroy
=
rxrpc_destroy_s
,
.
describe
=
rxrpc_describe
,
};
/*
* Vet the description for an RxRPC server key
*/
static
int
rxrpc_vet_description_s
(
const
char
*
desc
)
{
unsigned
long
num
;
char
*
p
;
num
=
simple_strtoul
(
desc
,
&
p
,
10
);
if
(
*
p
!=
':'
||
num
>
65535
)
return
-
EINVAL
;
num
=
simple_strtoul
(
p
+
1
,
&
p
,
10
);
if
(
*
p
||
num
<
1
||
num
>
255
)
return
-
EINVAL
;
return
0
;
}
/*
* parse an RxKAD type XDR format token
* - the caller guarantees we have at least 4 words
...
...
scripts/selinux/genheaders/genheaders.c
浏览文件 @
a002951c
...
...
@@ -43,6 +43,8 @@ int main(int argc, char *argv[])
int
i
,
j
,
k
;
int
isids_len
;
FILE
*
fout
;
const
char
*
needle
=
"SOCKET"
;
char
*
substr
;
progname
=
argv
[
0
];
...
...
@@ -88,6 +90,24 @@ int main(int argc, char *argv[])
fprintf
(
fout
,
"%2d
\n
"
,
i
);
}
fprintf
(
fout
,
"
\n
#define SECINITSID_NUM %d
\n
"
,
i
-
1
);
fprintf
(
fout
,
"
\n
static inline bool security_is_socket_class(u16 kern_tclass)
\n
"
);
fprintf
(
fout
,
"{
\n
"
);
fprintf
(
fout
,
"
\t
bool sock = false;
\n\n
"
);
fprintf
(
fout
,
"
\t
switch (kern_tclass) {
\n
"
);
for
(
i
=
0
;
secclass_map
[
i
].
name
;
i
++
)
{
struct
security_class_mapping
*
map
=
&
secclass_map
[
i
];
substr
=
strstr
(
map
->
name
,
needle
);
if
(
substr
&&
strcmp
(
substr
,
needle
)
==
0
)
fprintf
(
fout
,
"
\t
case SECCLASS_%s:
\n
"
,
map
->
name
);
}
fprintf
(
fout
,
"
\t\t
sock = true;
\n
"
);
fprintf
(
fout
,
"
\t\t
break;
\n
"
);
fprintf
(
fout
,
"
\t
default:
\n
"
);
fprintf
(
fout
,
"
\t\t
break;
\n
"
);
fprintf
(
fout
,
"
\t
}
\n\n
"
);
fprintf
(
fout
,
"
\t
return sock;
\n
"
);
fprintf
(
fout
,
"}
\n
"
);
fprintf
(
fout
,
"
\n
#endif
\n
"
);
fclose
(
fout
);
...
...
security/apparmor/Makefile
浏览文件 @
a002951c
...
...
@@ -6,19 +6,47 @@ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o
\
resource.o sid.o file.o
clean-files
:
capability_names.h af
_names.h
clean-files
:=
capability_names.h rlim
_names.h
# Build a lower case string table of capability names
# Transforms lines from
# #define CAP_DAC_OVERRIDE 1
# to
# [1] = "dac_override",
quiet_cmd_make-caps
=
GEN
$@
cmd_make-caps
=
echo
"static const char *capability_names[] = {"
>
$@
;
sed
-n
-e
"/CAP_FS_MASK/d"
-e
"s/^
\#
define[
\\
t]
\\
+CAP_
\\
([A-Z0-9_]
\\
+
\\
)[
\\
t]
\\
+
\\
([0-9]
\\
+
\\
)
\$
$/
[
\\
2] =
\"\\
1
\"
,/p"
$<
|
tr
A-Z a-z
>>
$@
;
echo
"};"
>>
$@
cmd_make-caps
=
echo
"static const char *capability_names[] = {"
>
$@
;
\
sed
$<
>>
$@
-r
-n
-e
'/CAP_FS_MASK/d'
\
-e
's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p'
;
\
echo
"};"
>>
$@
# Build a lower case string table of rlimit names.
# Transforms lines from
# #define RLIMIT_STACK 3 /* max stack size */
# to
# [RLIMIT_STACK] = "stack",
#
# and build a second integer table (with the second sed cmd), that maps
# RLIMIT defines to the order defined in asm-generic/resource.h Thi is
# required by policy load to map policy ordering of RLIMITs to internal
# ordering for architectures that redefine an RLIMIT.
# Transforms lines from
# #define RLIMIT_STACK 3 /* max stack size */
# to
# RLIMIT_STACK,
quiet_cmd_make-rlim
=
GEN
$@
cmd_make-rlim
=
echo
"static const char *rlim_names[] = {"
>
$@
;
sed
-n
--e
"/AF_MAX/d"
-e
"s/^
\#
\\
?define[
\\
t]
\\
+RLIMIT_
\\
([A-Z0-9_]
\\
+
\\
)[
\\
t]
\\
+
\\
([0-9]
\\
+
\\
)
\\
(.*
\\
)
\$
$/
[
\\
2] =
\"\\
1
\"
,/p"
$<
|
tr
A-Z a-z
>>
$@
;
echo
"};"
>>
$@
;
echo
"static const int rlim_map[] = {"
>>
$@
;
sed
-n
-e
"/AF_MAX/d"
-e
"s/^
\#
\\
?define[
\\
t]
\\
+
\\
(RLIMIT_[A-Z0-9_]
\\
+
\\
)[
\\
t]
\\
+
\\
([0-9]
\\
+
\\
)
\\
(.*
\\
)
\$
$/
\\
1,/p"
$<
>>
$@
;
echo
"};"
>>
$@
cmd_make-rlim
=
echo
"static const char *rlim_names[] = {"
>
$@
;
\
sed
$<
>>
$@
-r
-n
\
-e
's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p'
;
\
echo
"};"
>>
$@
;
\
echo
"static const int rlim_map[] = {"
>>
$@
;
\
sed
-r
-n
"s/^
\#
?define[
\t
]+(RLIMIT_[A-Z0-9_]+).*/
\1
,/p"
$<
>>
$@
;
\
echo
"};"
>>
$@
$(obj)/capability.o
:
$(obj)/capability_names.h
$(obj)/resource.o
:
$(obj)/rlim_names.h
$(obj)/capability_names.h
:
$(srctree)/include/linux/capability.h
$(
call
cmd,make-caps
)
$(obj)/af_names.h
:
$(srctree)/include/linux/socket.h
$(
call
cmd,make-af
)
$(obj)/rlim_names.h
:
$(srctree)/include/asm-generic/resource.h
$(
call
cmd,make-rlim
)
security/apparmor/lsm.c
浏览文件 @
a002951c
...
...
@@ -693,11 +693,9 @@ static struct kernel_param_ops param_ops_aalockpolicy = {
static
int
param_set_audit
(
const
char
*
val
,
struct
kernel_param
*
kp
);
static
int
param_get_audit
(
char
*
buffer
,
struct
kernel_param
*
kp
);
#define param_check_audit(name, p) __param_check(name, p, int)
static
int
param_set_mode
(
const
char
*
val
,
struct
kernel_param
*
kp
);
static
int
param_get_mode
(
char
*
buffer
,
struct
kernel_param
*
kp
);
#define param_check_mode(name, p) __param_check(name, p, int)
/* Flag values, also controllable via /sys/module/apparmor/parameters
* We define special types as we want to do additional mediation.
...
...
security/capability.c
浏览文件 @
a002951c
...
...
@@ -12,11 +12,6 @@
#include <linux/security.h>
static
int
cap_sysctl
(
ctl_table
*
table
,
int
op
)
{
return
0
;
}
static
int
cap_syslog
(
int
type
)
{
return
0
;
...
...
@@ -59,6 +54,11 @@ static int cap_sb_copy_data(char *orig, char *copy)
return
0
;
}
static
int
cap_sb_remount
(
struct
super_block
*
sb
,
void
*
data
)
{
return
0
;
}
static
int
cap_sb_kern_mount
(
struct
super_block
*
sb
,
int
flags
,
void
*
data
)
{
return
0
;
...
...
@@ -118,7 +118,8 @@ static void cap_inode_free_security(struct inode *inode)
}
static
int
cap_inode_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
char
**
name
,
void
**
value
,
size_t
*
len
)
const
struct
qstr
*
qstr
,
char
**
name
,
void
**
value
,
size_t
*
len
)
{
return
-
EOPNOTSUPP
;
}
...
...
@@ -880,7 +881,6 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null
(
ops
,
capable
);
set_to_cap_if_null
(
ops
,
quotactl
);
set_to_cap_if_null
(
ops
,
quota_on
);
set_to_cap_if_null
(
ops
,
sysctl
);
set_to_cap_if_null
(
ops
,
syslog
);
set_to_cap_if_null
(
ops
,
settime
);
set_to_cap_if_null
(
ops
,
vm_enough_memory
);
...
...
@@ -892,6 +892,7 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null
(
ops
,
sb_alloc_security
);
set_to_cap_if_null
(
ops
,
sb_free_security
);
set_to_cap_if_null
(
ops
,
sb_copy_data
);
set_to_cap_if_null
(
ops
,
sb_remount
);
set_to_cap_if_null
(
ops
,
sb_kern_mount
);
set_to_cap_if_null
(
ops
,
sb_show_options
);
set_to_cap_if_null
(
ops
,
sb_statfs
);
...
...
security/integrity/ima/ima.h
浏览文件 @
a002951c
...
...
@@ -110,8 +110,7 @@ struct ima_iint_cache {
};
/* LIM API function definitions */
int
ima_must_measure
(
struct
ima_iint_cache
*
iint
,
struct
inode
*
inode
,
int
mask
,
int
function
);
int
ima_must_measure
(
struct
inode
*
inode
,
int
mask
,
int
function
);
int
ima_collect_measurement
(
struct
ima_iint_cache
*
iint
,
struct
file
*
file
);
void
ima_store_measurement
(
struct
ima_iint_cache
*
iint
,
struct
file
*
file
,
const
unsigned
char
*
filename
);
...
...
security/integrity/ima/ima_api.c
浏览文件 @
a002951c
...
...
@@ -105,20 +105,13 @@ void ima_add_violation(struct inode *inode, const unsigned char *filename,
* mask: contains the permission mask
* fsmagic: hex value
*
* Must be called with iint->mutex held.
*
* Return 0 to measure. Return 1 if already measured.
* For matching a DONT_MEASURE policy, no policy, or other
* error, return an error code.
* Return 0 to measure. For matching a DONT_MEASURE policy, no policy,
* or other error, return an error code.
*/
int
ima_must_measure
(
struct
ima_iint_cache
*
iint
,
struct
inode
*
inode
,
int
mask
,
int
function
)
int
ima_must_measure
(
struct
inode
*
inode
,
int
mask
,
int
function
)
{
int
must_measure
;
if
(
iint
&&
iint
->
flags
&
IMA_MEASURED
)
return
1
;
must_measure
=
ima_match_policy
(
inode
,
function
,
mask
);
return
must_measure
?
0
:
-
EACCES
;
}
...
...
security/integrity/ima/ima_iint.c
浏览文件 @
a002951c
...
...
@@ -137,11 +137,6 @@ void ima_inode_free(struct inode *inode)
{
struct
ima_iint_cache
*
iint
;
if
(
inode
->
i_readcount
)
printk
(
KERN_INFO
"%s: readcount: %u
\n
"
,
__func__
,
inode
->
i_readcount
);
inode
->
i_readcount
=
0
;
if
(
!
IS_IMA
(
inode
))
return
;
...
...
security/integrity/ima/ima_main.c
浏览文件 @
a002951c
...
...
@@ -36,67 +36,17 @@ static int __init hash_setup(char *str)
}
__setup
(
"ima_hash="
,
hash_setup
);
struct
ima_imbalance
{
struct
hlist_node
node
;
unsigned
long
fsmagic
;
};
/*
* ima_limit_imbalance - emit one imbalance message per filesystem type
*
* Maintain list of filesystem types that do not measure files properly.
* Return false if unknown, true if known.
*/
static
bool
ima_limit_imbalance
(
struct
file
*
file
)
{
static
DEFINE_SPINLOCK
(
ima_imbalance_lock
);
static
HLIST_HEAD
(
ima_imbalance_list
);
struct
super_block
*
sb
=
file
->
f_dentry
->
d_sb
;
struct
ima_imbalance
*
entry
;
struct
hlist_node
*
node
;
bool
found
=
false
;
rcu_read_lock
();
hlist_for_each_entry_rcu
(
entry
,
node
,
&
ima_imbalance_list
,
node
)
{
if
(
entry
->
fsmagic
==
sb
->
s_magic
)
{
found
=
true
;
break
;
}
}
rcu_read_unlock
();
if
(
found
)
goto
out
;
entry
=
kmalloc
(
sizeof
(
*
entry
),
GFP_NOFS
);
if
(
!
entry
)
goto
out
;
entry
->
fsmagic
=
sb
->
s_magic
;
spin_lock
(
&
ima_imbalance_lock
);
/*
* we could have raced and something else might have added this fs
* to the list, but we don't really care
*/
hlist_add_head_rcu
(
&
entry
->
node
,
&
ima_imbalance_list
);
spin_unlock
(
&
ima_imbalance_lock
);
printk
(
KERN_INFO
"IMA: unmeasured files on fsmagic: %lX
\n
"
,
entry
->
fsmagic
);
out:
return
found
;
}
/*
* ima_
counts_get - increment file counts
* ima_
rdwr_violation_check
*
* Maintain read/write counters for all files, but only
* invalidate the PCR for measured files:
* Only invalidate the PCR for measured files:
* - Opening a file for write when already open for read,
* results in a time of measure, time of use (ToMToU) error.
* - Opening a file for read when already open for write,
* could result in a file measurement error.
*
*/
void
ima_counts_get
(
struct
file
*
file
)
static
void
ima_rdwr_violation_check
(
struct
file
*
file
)
{
struct
dentry
*
dentry
=
file
->
f_path
.
dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
...
...
@@ -104,32 +54,25 @@ void ima_counts_get(struct file *file)
int
rc
;
bool
send_tomtou
=
false
,
send_writers
=
false
;
if
(
!
S_ISREG
(
inode
->
i_mode
))
if
(
!
S_ISREG
(
inode
->
i_mode
)
||
!
ima_initialized
)
return
;
spin_lock
(
&
inode
->
i_lock
);
if
(
!
ima_initialized
)
goto
out
;
mutex_lock
(
&
inode
->
i_mutex
);
/* file metadata: permissions, xattr */
if
(
mode
&
FMODE_WRITE
)
{
if
(
inode
->
i_readcount
&&
IS_IMA
(
inode
))
if
(
atomic_read
(
&
inode
->
i_readcount
)
&&
IS_IMA
(
inode
))
send_tomtou
=
true
;
goto
out
;
}
rc
=
ima_must_measure
(
NULL
,
inode
,
MAY_READ
,
FILE_CHECK
);
rc
=
ima_must_measure
(
inode
,
MAY_READ
,
FILE_CHECK
);
if
(
rc
<
0
)
goto
out
;
if
(
atomic_read
(
&
inode
->
i_writecount
)
>
0
)
send_writers
=
true
;
out:
/* remember the vfs deals with i_writecount */
if
((
mode
&
(
FMODE_READ
|
FMODE_WRITE
))
==
FMODE_READ
)
inode
->
i_readcount
++
;
spin_unlock
(
&
inode
->
i_lock
);
mutex_unlock
(
&
inode
->
i_mutex
);
if
(
send_tomtou
)
ima_add_violation
(
inode
,
dentry
->
d_name
.
name
,
"invalid_pcr"
,
...
...
@@ -139,71 +82,25 @@ void ima_counts_get(struct file *file)
"open_writers"
);
}
/*
* Decrement ima counts
*/
static
void
ima_dec_counts
(
struct
inode
*
inode
,
struct
file
*
file
)
{
mode_t
mode
=
file
->
f_mode
;
assert_spin_locked
(
&
inode
->
i_lock
);
if
((
mode
&
(
FMODE_READ
|
FMODE_WRITE
))
==
FMODE_READ
)
{
if
(
unlikely
(
inode
->
i_readcount
==
0
))
{
if
(
!
ima_limit_imbalance
(
file
))
{
printk
(
KERN_INFO
"%s: open/free imbalance (r:%u)
\n
"
,
__func__
,
inode
->
i_readcount
);
dump_stack
();
}
return
;
}
inode
->
i_readcount
--
;
}
}
static
void
ima_check_last_writer
(
struct
ima_iint_cache
*
iint
,
struct
inode
*
inode
,
struct
file
*
file
)
{
mode_t
mode
=
file
->
f_mode
;
BUG_ON
(
!
mutex_is_locked
(
&
iint
->
mutex
));
assert_spin_locked
(
&
inode
->
i_lock
);
mutex_lock
(
&
iint
->
mutex
);
if
(
mode
&
FMODE_WRITE
&&
atomic_read
(
&
inode
->
i_writecount
)
==
1
&&
iint
->
version
!=
inode
->
i_version
)
iint
->
flags
&=
~
IMA_MEASURED
;
}
static
void
ima_file_free_iint
(
struct
ima_iint_cache
*
iint
,
struct
inode
*
inode
,
struct
file
*
file
)
{
mutex_lock
(
&
iint
->
mutex
);
spin_lock
(
&
inode
->
i_lock
);
ima_dec_counts
(
inode
,
file
);
ima_check_last_writer
(
iint
,
inode
,
file
);
spin_unlock
(
&
inode
->
i_lock
);
mutex_unlock
(
&
iint
->
mutex
);
}
static
void
ima_file_free_noiint
(
struct
inode
*
inode
,
struct
file
*
file
)
{
spin_lock
(
&
inode
->
i_lock
);
ima_dec_counts
(
inode
,
file
);
spin_unlock
(
&
inode
->
i_lock
);
}
/**
* ima_file_free - called on __fput()
* @file: pointer to file structure being freed
*
* Flag files that changed, based on i_version;
* and decrement the i_readcount.
* Flag files that changed, based on i_version
*/
void
ima_file_free
(
struct
file
*
file
)
{
...
...
@@ -214,12 +111,10 @@ void ima_file_free(struct file *file)
return
;
iint
=
ima_iint_find
(
inode
);
if
(
!
iint
)
return
;
if
(
iint
)
ima_file_free_iint
(
iint
,
inode
,
file
);
else
ima_file_free_noiint
(
inode
,
file
);
ima_check_last_writer
(
iint
,
inode
,
file
);
}
static
int
process_measurement
(
struct
file
*
file
,
const
unsigned
char
*
filename
,
...
...
@@ -232,7 +127,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
if
(
!
ima_initialized
||
!
S_ISREG
(
inode
->
i_mode
))
return
0
;
rc
=
ima_must_measure
(
NULL
,
inode
,
mask
,
function
);
rc
=
ima_must_measure
(
inode
,
mask
,
function
);
if
(
rc
!=
0
)
return
rc
;
retry:
...
...
@@ -246,7 +141,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
mutex_lock
(
&
iint
->
mutex
);
rc
=
i
ma_must_measure
(
iint
,
inode
,
mask
,
function
)
;
rc
=
i
int
->
flags
&
IMA_MEASURED
?
1
:
0
;
if
(
rc
!=
0
)
goto
out
;
...
...
@@ -317,6 +212,7 @@ int ima_file_check(struct file *file, int mask)
{
int
rc
;
ima_rdwr_violation_check
(
file
);
rc
=
process_measurement
(
file
,
file
->
f_dentry
->
d_name
.
name
,
mask
&
(
MAY_READ
|
MAY_WRITE
|
MAY_EXEC
),
FILE_CHECK
);
...
...
security/keys/compat.c
浏览文件 @
a002951c
...
...
@@ -12,8 +12,51 @@
#include <linux/syscalls.h>
#include <linux/keyctl.h>
#include <linux/compat.h>
#include <linux/slab.h>
#include "internal.h"
/*
* Instantiate a key with the specified compatibility multipart payload and
* link the key into the destination keyring if one is given.
*
* The caller must have the appropriate instantiation permit set for this to
* work (see keyctl_assume_authority). No other permissions are required.
*
* If successful, 0 will be returned.
*/
long
compat_keyctl_instantiate_key_iov
(
key_serial_t
id
,
const
struct
compat_iovec
__user
*
_payload_iov
,
unsigned
ioc
,
key_serial_t
ringid
)
{
struct
iovec
iovstack
[
UIO_FASTIOV
],
*
iov
=
iovstack
;
long
ret
;
if
(
_payload_iov
==
0
||
ioc
==
0
)
goto
no_payload
;
ret
=
compat_rw_copy_check_uvector
(
WRITE
,
_payload_iov
,
ioc
,
ARRAY_SIZE
(
iovstack
),
iovstack
,
&
iov
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
==
0
)
goto
no_payload_free
;
ret
=
keyctl_instantiate_key_common
(
id
,
iov
,
ioc
,
ret
,
ringid
);
if
(
iov
!=
iovstack
)
kfree
(
iov
);
return
ret
;
no_payload_free:
if
(
iov
!=
iovstack
)
kfree
(
iov
);
no_payload:
return
keyctl_instantiate_key_common
(
id
,
NULL
,
0
,
0
,
ringid
);
}
/*
* The key control system call, 32-bit compatibility version for 64-bit archs
*
...
...
@@ -85,6 +128,13 @@ asmlinkage long compat_sys_keyctl(u32 option,
case
KEYCTL_SESSION_TO_PARENT
:
return
keyctl_session_to_parent
();
case
KEYCTL_REJECT
:
return
keyctl_reject_key
(
arg2
,
arg3
,
arg4
,
arg5
);
case
KEYCTL_INSTANTIATE_IOV
:
return
compat_keyctl_instantiate_key_iov
(
arg2
,
compat_ptr
(
arg3
),
arg4
,
arg5
);
default:
return
-
EOPNOTSUPP
;
}
...
...
security/keys/encrypted.c
浏览文件 @
a002951c
...
...
@@ -765,8 +765,7 @@ static long encrypted_read(const struct key *key, char __user *buffer,
size_t
asciiblob_len
;
int
ret
;
epayload
=
rcu_dereference_protected
(
key
->
payload
.
data
,
rwsem_is_locked
(
&
((
struct
key
*
)
key
)
->
sem
));
epayload
=
rcu_dereference_key
(
key
);
/* returns the hex encoded iv, encrypted-data, and hmac as ascii */
asciiblob_len
=
epayload
->
datablob_len
+
ivsize
+
1
...
...
security/keys/internal.h
浏览文件 @
a002951c
...
...
@@ -214,6 +214,14 @@ extern long keyctl_assume_authority(key_serial_t);
extern
long
keyctl_get_security
(
key_serial_t
keyid
,
char
__user
*
buffer
,
size_t
buflen
);
extern
long
keyctl_session_to_parent
(
void
);
extern
long
keyctl_reject_key
(
key_serial_t
,
unsigned
,
unsigned
,
key_serial_t
);
extern
long
keyctl_instantiate_key_iov
(
key_serial_t
,
const
struct
iovec
__user
*
,
unsigned
,
key_serial_t
);
extern
long
keyctl_instantiate_key_common
(
key_serial_t
,
const
struct
iovec
__user
*
,
unsigned
,
size_t
,
key_serial_t
);
/*
* Debugging key validation
...
...
security/keys/key.c
浏览文件 @
a002951c
...
...
@@ -249,6 +249,14 @@ struct key *key_alloc(struct key_type *type, const char *desc,
if
(
!
desc
||
!*
desc
)
goto
error
;
if
(
type
->
vet_description
)
{
ret
=
type
->
vet_description
(
desc
);
if
(
ret
<
0
)
{
key
=
ERR_PTR
(
ret
);
goto
error
;
}
}
desclen
=
strlen
(
desc
)
+
1
;
quotalen
=
desclen
+
type
->
def_datalen
;
...
...
@@ -503,26 +511,29 @@ int key_instantiate_and_link(struct key *key,
EXPORT_SYMBOL
(
key_instantiate_and_link
);
/**
* key_
negate
_and_link - Negatively instantiate a key and link it into the keyring.
* key_
reject
_and_link - Negatively instantiate a key and link it into the keyring.
* @key: The key to instantiate.
* @timeout: The timeout on the negative key.
* @error: The error to return when the key is hit.
* @keyring: Keyring to create a link in on success (or NULL).
* @authkey: The authorisation token permitting instantiation.
*
* Negatively instantiate a key that's in the uninstantiated state and, if
* successful, set its timeout and
link it in to the destination keyring if on
e
*
is supplied. The key and any links to the key will be automatically garbage
* collected after the timeout expires.
* successful, set its timeout and
stored error and link it in to th
e
*
destination keyring if one is supplied. The key and any links to the key
*
will be automatically garbage
collected after the timeout expires.
*
* Negative keys are used to rate limit repeated request_key() calls by causing
* them to return -ENOKEY until the negative key expires.
* them to return the stored error code (typically ENOKEY) until the negative
* key expires.
*
* If successful, 0 is returned, the authorisation token is revoked and anyone
* waiting for the key is woken up. If the key was already instantiated,
* -EBUSY will be returned.
*/
int
key_
negate
_and_link
(
struct
key
*
key
,
int
key_
reject
_and_link
(
struct
key
*
key
,
unsigned
timeout
,
unsigned
error
,
struct
key
*
keyring
,
struct
key
*
authkey
)
{
...
...
@@ -548,6 +559,7 @@ int key_negate_and_link(struct key *key,
atomic_inc
(
&
key
->
user
->
nikeys
);
set_bit
(
KEY_FLAG_NEGATIVE
,
&
key
->
flags
);
set_bit
(
KEY_FLAG_INSTANTIATED
,
&
key
->
flags
);
key
->
type_data
.
reject_error
=
-
error
;
now
=
current_kernel_time
();
key
->
expiry
=
now
.
tv_sec
+
timeout
;
key_schedule_gc
(
key
->
expiry
+
key_gc_delay
);
...
...
@@ -577,8 +589,7 @@ int key_negate_and_link(struct key *key,
return
ret
==
0
?
link_ret
:
ret
;
}
EXPORT_SYMBOL
(
key_negate_and_link
);
EXPORT_SYMBOL
(
key_reject_and_link
);
/*
* Garbage collect keys in process context so that we don't have to disable
...
...
security/keys/keyctl.c
浏览文件 @
a002951c
...
...
@@ -912,6 +912,21 @@ static int keyctl_change_reqkey_auth(struct key *key)
return
commit_creds
(
new
);
}
/*
* Copy the iovec data from userspace
*/
static
long
copy_from_user_iovec
(
void
*
buffer
,
const
struct
iovec
*
iov
,
unsigned
ioc
)
{
for
(;
ioc
>
0
;
ioc
--
)
{
if
(
copy_from_user
(
buffer
,
iov
->
iov_base
,
iov
->
iov_len
)
!=
0
)
return
-
EFAULT
;
buffer
+=
iov
->
iov_len
;
iov
++
;
}
return
0
;
}
/*
* Instantiate a key with the specified payload and link the key into the
* destination keyring if one is given.
...
...
@@ -921,10 +936,11 @@ static int keyctl_change_reqkey_auth(struct key *key)
*
* If successful, 0 will be returned.
*/
long
keyctl_instantiate_key
(
key_serial_t
id
,
const
void
__user
*
_payload
,
size_t
plen
,
key_serial_t
ringid
)
long
keyctl_instantiate_key_common
(
key_serial_t
id
,
const
struct
iovec
*
payload_iov
,
unsigned
ioc
,
size_t
plen
,
key_serial_t
ringid
)
{
const
struct
cred
*
cred
=
current_cred
();
struct
request_key_auth
*
rka
;
...
...
@@ -953,7 +969,7 @@ long keyctl_instantiate_key(key_serial_t id,
/* pull the payload in if one was supplied */
payload
=
NULL
;
if
(
_payload
)
{
if
(
payload_iov
)
{
ret
=
-
ENOMEM
;
payload
=
kmalloc
(
plen
,
GFP_KERNEL
);
if
(
!
payload
)
{
...
...
@@ -965,8 +981,8 @@ long keyctl_instantiate_key(key_serial_t id,
goto
error
;
}
ret
=
-
EFAULT
;
if
(
copy_from_user
(
payload
,
_payload
,
plen
)
!=
0
)
ret
=
copy_from_user_iovec
(
payload
,
payload_iov
,
ioc
)
;
if
(
ret
<
0
)
goto
error2
;
}
...
...
@@ -996,6 +1012,72 @@ long keyctl_instantiate_key(key_serial_t id,
return
ret
;
}
/*
* Instantiate a key with the specified payload and link the key into the
* destination keyring if one is given.
*
* The caller must have the appropriate instantiation permit set for this to
* work (see keyctl_assume_authority). No other permissions are required.
*
* If successful, 0 will be returned.
*/
long
keyctl_instantiate_key
(
key_serial_t
id
,
const
void
__user
*
_payload
,
size_t
plen
,
key_serial_t
ringid
)
{
if
(
_payload
&&
plen
)
{
struct
iovec
iov
[
1
]
=
{
[
0
].
iov_base
=
(
void
__user
*
)
_payload
,
[
0
].
iov_len
=
plen
};
return
keyctl_instantiate_key_common
(
id
,
iov
,
1
,
plen
,
ringid
);
}
return
keyctl_instantiate_key_common
(
id
,
NULL
,
0
,
0
,
ringid
);
}
/*
* Instantiate a key with the specified multipart payload and link the key into
* the destination keyring if one is given.
*
* The caller must have the appropriate instantiation permit set for this to
* work (see keyctl_assume_authority). No other permissions are required.
*
* If successful, 0 will be returned.
*/
long
keyctl_instantiate_key_iov
(
key_serial_t
id
,
const
struct
iovec
__user
*
_payload_iov
,
unsigned
ioc
,
key_serial_t
ringid
)
{
struct
iovec
iovstack
[
UIO_FASTIOV
],
*
iov
=
iovstack
;
long
ret
;
if
(
_payload_iov
==
0
||
ioc
==
0
)
goto
no_payload
;
ret
=
rw_copy_check_uvector
(
WRITE
,
_payload_iov
,
ioc
,
ARRAY_SIZE
(
iovstack
),
iovstack
,
&
iov
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
==
0
)
goto
no_payload_free
;
ret
=
keyctl_instantiate_key_common
(
id
,
iov
,
ioc
,
ret
,
ringid
);
if
(
iov
!=
iovstack
)
kfree
(
iov
);
return
ret
;
no_payload_free:
if
(
iov
!=
iovstack
)
kfree
(
iov
);
no_payload:
return
keyctl_instantiate_key_common
(
id
,
NULL
,
0
,
0
,
ringid
);
}
/*
* Negatively instantiate the key with the given timeout (in seconds) and link
* the key into the destination keyring if one is given.
...
...
@@ -1012,13 +1094,43 @@ long keyctl_instantiate_key(key_serial_t id,
* If successful, 0 will be returned.
*/
long
keyctl_negate_key
(
key_serial_t
id
,
unsigned
timeout
,
key_serial_t
ringid
)
{
return
keyctl_reject_key
(
id
,
timeout
,
ENOKEY
,
ringid
);
}
/*
* Negatively instantiate the key with the given timeout (in seconds) and error
* code and link the key into the destination keyring if one is given.
*
* The caller must have the appropriate instantiation permit set for this to
* work (see keyctl_assume_authority). No other permissions are required.
*
* The key and any links to the key will be automatically garbage collected
* after the timeout expires.
*
* Negative keys are used to rate limit repeated request_key() calls by causing
* them to return the specified error code until the negative key expires.
*
* If successful, 0 will be returned.
*/
long
keyctl_reject_key
(
key_serial_t
id
,
unsigned
timeout
,
unsigned
error
,
key_serial_t
ringid
)
{
const
struct
cred
*
cred
=
current_cred
();
struct
request_key_auth
*
rka
;
struct
key
*
instkey
,
*
dest_keyring
;
long
ret
;
kenter
(
"%d,%u,%d"
,
id
,
timeout
,
ringid
);
kenter
(
"%d,%u,%u,%d"
,
id
,
timeout
,
error
,
ringid
);
/* must be a valid error code and mustn't be a kernel special */
if
(
error
<=
0
||
error
>=
MAX_ERRNO
||
error
==
ERESTARTSYS
||
error
==
ERESTARTNOINTR
||
error
==
ERESTARTNOHAND
||
error
==
ERESTART_RESTARTBLOCK
)
return
-
EINVAL
;
/* the appropriate instantiation authorisation key must have been
* assumed before calling this */
...
...
@@ -1038,7 +1150,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
goto
error
;
/* instantiate the key and link it into a keyring */
ret
=
key_
negate_and_link
(
rka
->
target_key
,
timeout
,
ret
=
key_
reject_and_link
(
rka
->
target_key
,
timeout
,
error
,
dest_keyring
,
instkey
);
key_put
(
dest_keyring
);
...
...
@@ -1492,6 +1604,19 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
case
KEYCTL_SESSION_TO_PARENT
:
return
keyctl_session_to_parent
();
case
KEYCTL_REJECT
:
return
keyctl_reject_key
((
key_serial_t
)
arg2
,
(
unsigned
)
arg3
,
(
unsigned
)
arg4
,
(
key_serial_t
)
arg5
);
case
KEYCTL_INSTANTIATE_IOV
:
return
keyctl_instantiate_key_iov
(
(
key_serial_t
)
arg2
,
(
const
struct
iovec
__user
*
)
arg3
,
(
unsigned
)
arg4
,
(
key_serial_t
)
arg5
);
default:
return
-
EOPNOTSUPP
;
}
...
...
security/keys/keyring.c
浏览文件 @
a002951c
...
...
@@ -352,7 +352,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
goto
error_2
;
if
(
key
->
expiry
&&
now
.
tv_sec
>=
key
->
expiry
)
goto
error_2
;
key_ref
=
ERR_PTR
(
-
ENOKEY
);
key_ref
=
ERR_PTR
(
key
->
type_data
.
reject_error
);
if
(
kflags
&
(
1
<<
KEY_FLAG_NEGATIVE
))
goto
error_2
;
goto
found
;
...
...
@@ -401,7 +401,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
/* we set a different error code if we pass a negative key */
if
(
kflags
&
(
1
<<
KEY_FLAG_NEGATIVE
))
{
err
=
-
ENOKEY
;
err
=
key
->
type_data
.
reject_error
;
continue
;
}
...
...
security/keys/request_key.c
浏览文件 @
a002951c
...
...
@@ -585,7 +585,7 @@ int wait_for_key_construction(struct key *key, bool intr)
if
(
ret
<
0
)
return
ret
;
if
(
test_bit
(
KEY_FLAG_NEGATIVE
,
&
key
->
flags
))
return
-
ENOKEY
;
return
key
->
type_data
.
reject_error
;
return
key_validate
(
key
);
}
EXPORT_SYMBOL
(
wait_for_key_construction
);
...
...
security/keys/trusted.c
浏览文件 @
a002951c
...
...
@@ -1076,8 +1076,7 @@ static long trusted_read(const struct key *key, char __user *buffer,
char
*
bufp
;
int
i
;
p
=
rcu_dereference_protected
(
key
->
payload
.
data
,
rwsem_is_locked
(
&
((
struct
key
*
)
key
)
->
sem
));
p
=
rcu_dereference_key
(
key
);
if
(
!
p
)
return
-
EINVAL
;
if
(
!
buffer
||
buflen
<=
0
)
...
...
security/keys/user_defined.c
浏览文件 @
a002951c
...
...
@@ -184,8 +184,7 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
struct
user_key_payload
*
upayload
;
long
ret
;
upayload
=
rcu_dereference_protected
(
key
->
payload
.
data
,
rwsem_is_locked
(
&
((
struct
key
*
)
key
)
->
sem
));
upayload
=
rcu_dereference_key
(
key
);
ret
=
upayload
->
datalen
;
/* we can return the data as is */
...
...
security/security.c
浏览文件 @
a002951c
...
...
@@ -181,11 +181,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap)
return
ret
;
}
int
security_sysctl
(
struct
ctl_table
*
table
,
int
op
)
{
return
security_ops
->
sysctl
(
table
,
op
);
}
int
security_quotactl
(
int
cmds
,
int
type
,
int
id
,
struct
super_block
*
sb
)
{
return
security_ops
->
quotactl
(
cmds
,
type
,
id
,
sb
);
...
...
@@ -271,6 +266,11 @@ int security_sb_copy_data(char *orig, char *copy)
}
EXPORT_SYMBOL
(
security_sb_copy_data
);
int
security_sb_remount
(
struct
super_block
*
sb
,
void
*
data
)
{
return
security_ops
->
sb_remount
(
sb
,
data
);
}
int
security_sb_kern_mount
(
struct
super_block
*
sb
,
int
flags
,
void
*
data
)
{
return
security_ops
->
sb_kern_mount
(
sb
,
flags
,
data
);
...
...
@@ -335,11 +335,13 @@ void security_inode_free(struct inode *inode)
}
int
security_inode_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
char
**
name
,
void
**
value
,
size_t
*
len
)
const
struct
qstr
*
qstr
,
char
**
name
,
void
**
value
,
size_t
*
len
)
{
if
(
unlikely
(
IS_PRIVATE
(
inode
)))
return
-
EOPNOTSUPP
;
return
security_ops
->
inode_init_security
(
inode
,
dir
,
name
,
value
,
len
);
return
security_ops
->
inode_init_security
(
inode
,
dir
,
qstr
,
name
,
value
,
len
);
}
EXPORT_SYMBOL
(
security_inode_init_security
);
...
...
@@ -359,6 +361,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
return
0
;
return
security_ops
->
path_mkdir
(
dir
,
dentry
,
mode
);
}
EXPORT_SYMBOL
(
security_path_mkdir
);
int
security_path_rmdir
(
struct
path
*
dir
,
struct
dentry
*
dentry
)
{
...
...
@@ -373,6 +376,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
return
0
;
return
security_ops
->
path_unlink
(
dir
,
dentry
);
}
EXPORT_SYMBOL
(
security_path_unlink
);
int
security_path_symlink
(
struct
path
*
dir
,
struct
dentry
*
dentry
,
const
char
*
old_name
)
...
...
@@ -399,6 +403,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
return
security_ops
->
path_rename
(
old_dir
,
old_dentry
,
new_dir
,
new_dentry
);
}
EXPORT_SYMBOL
(
security_path_rename
);
int
security_path_truncate
(
struct
path
*
path
)
{
...
...
security/selinux/hooks.c
浏览文件 @
a002951c
...
...
@@ -24,9 +24,11 @@
*/
#include <linux/init.h>
#include <linux/kd.h>
#include <linux/kernel.h>
#include <linux/tracehook.h>
#include <linux/errno.h>
#include <linux/ext2_fs.h>
#include <linux/sched.h>
#include <linux/security.h>
#include <linux/xattr.h>
...
...
@@ -36,14 +38,15 @@
#include <linux/mman.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/proc_fs.h>
#include <linux/swap.h>
#include <linux/spinlock.h>
#include <linux/syscalls.h>
#include <linux/dcache.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/proc_fs.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/tty.h>
...
...
@@ -70,7 +73,6 @@
#include <net/ipv6.h>
#include <linux/hugetlb.h>
#include <linux/personality.h>
#include <linux/sysctl.h>
#include <linux/audit.h>
#include <linux/string.h>
#include <linux/selinux.h>
...
...
@@ -1120,39 +1122,35 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
}
#ifdef CONFIG_PROC_FS
static
int
selinux_proc_get_sid
(
struct
proc_dir_entry
*
de
,
static
int
selinux_proc_get_sid
(
struct
dentry
*
dentry
,
u16
tclass
,
u32
*
sid
)
{
int
buflen
,
rc
;
char
*
buffer
,
*
path
,
*
end
;
int
rc
;
char
*
buffer
,
*
path
;
buffer
=
(
char
*
)
__get_free_page
(
GFP_KERNEL
);
if
(
!
buffer
)
return
-
ENOMEM
;
buflen
=
PAGE_SIZE
;
end
=
buffer
+
buflen
;
*--
end
=
'\0'
;
buflen
--
;
path
=
end
-
1
;
*
path
=
'/'
;
while
(
de
&&
de
!=
de
->
parent
)
{
buflen
-=
de
->
namelen
+
1
;
if
(
buflen
<
0
)
break
;
end
-=
de
->
namelen
;
memcpy
(
end
,
de
->
name
,
de
->
namelen
);
*--
end
=
'/'
;
path
=
end
;
de
=
de
->
parent
;
path
=
dentry_path_raw
(
dentry
,
buffer
,
PAGE_SIZE
);
if
(
IS_ERR
(
path
))
rc
=
PTR_ERR
(
path
);
else
{
/* each process gets a /proc/PID/ entry. Strip off the
* PID part to get a valid selinux labeling.
* e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
while
(
path
[
1
]
>=
'0'
&&
path
[
1
]
<=
'9'
)
{
path
[
1
]
=
'/'
;
path
++
;
}
rc
=
security_genfs_sid
(
"proc"
,
path
,
tclass
,
sid
);
}
rc
=
security_genfs_sid
(
"proc"
,
path
,
tclass
,
sid
);
free_page
((
unsigned
long
)
buffer
);
return
rc
;
}
#else
static
int
selinux_proc_get_sid
(
struct
proc_dir_entry
*
de
,
static
int
selinux_proc_get_sid
(
struct
dentry
*
dentry
,
u16
tclass
,
u32
*
sid
)
{
...
...
@@ -1300,10 +1298,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
/* Try to obtain a transition SID. */
isec
->
sclass
=
inode_mode_to_security_class
(
inode
->
i_mode
);
rc
=
security_transition_sid
(
isec
->
task_sid
,
sbsec
->
sid
,
isec
->
sclass
,
&
sid
);
rc
=
security_transition_sid
(
isec
->
task_sid
,
sbsec
->
sid
,
isec
->
sclass
,
NULL
,
&
sid
);
if
(
rc
)
goto
out_unlock
;
isec
->
sid
=
sid
;
...
...
@@ -1316,10 +1312,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
isec
->
sid
=
sbsec
->
sid
;
if
((
sbsec
->
flags
&
SE_SBPROC
)
&&
!
S_ISLNK
(
inode
->
i_mode
))
{
struct
proc_inode
*
proci
=
PROC_I
(
inode
);
if
(
proci
->
pde
)
{
if
(
opt_dentry
)
{
isec
->
sclass
=
inode_mode_to_security_class
(
inode
->
i_mode
);
rc
=
selinux_proc_get_sid
(
proci
->
pde
,
rc
=
selinux_proc_get_sid
(
opt_dentry
,
isec
->
sclass
,
&
sid
);
if
(
rc
)
...
...
@@ -1578,7 +1573,7 @@ static int may_create(struct inode *dir,
return
rc
;
if
(
!
newsid
||
!
(
sbsec
->
flags
&
SE_SBLABELSUPP
))
{
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
tclass
,
&
newsid
);
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
tclass
,
NULL
,
&
newsid
);
if
(
rc
)
return
rc
;
}
...
...
@@ -1862,82 +1857,6 @@ static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
return
task_has_capability
(
tsk
,
cred
,
cap
,
audit
);
}
static
int
selinux_sysctl_get_sid
(
ctl_table
*
table
,
u16
tclass
,
u32
*
sid
)
{
int
buflen
,
rc
;
char
*
buffer
,
*
path
,
*
end
;
rc
=
-
ENOMEM
;
buffer
=
(
char
*
)
__get_free_page
(
GFP_KERNEL
);
if
(
!
buffer
)
goto
out
;
buflen
=
PAGE_SIZE
;
end
=
buffer
+
buflen
;
*--
end
=
'\0'
;
buflen
--
;
path
=
end
-
1
;
*
path
=
'/'
;
while
(
table
)
{
const
char
*
name
=
table
->
procname
;
size_t
namelen
=
strlen
(
name
);
buflen
-=
namelen
+
1
;
if
(
buflen
<
0
)
goto
out_free
;
end
-=
namelen
;
memcpy
(
end
,
name
,
namelen
);
*--
end
=
'/'
;
path
=
end
;
table
=
table
->
parent
;
}
buflen
-=
4
;
if
(
buflen
<
0
)
goto
out_free
;
end
-=
4
;
memcpy
(
end
,
"/sys"
,
4
);
path
=
end
;
rc
=
security_genfs_sid
(
"proc"
,
path
,
tclass
,
sid
);
out_free:
free_page
((
unsigned
long
)
buffer
);
out:
return
rc
;
}
static
int
selinux_sysctl
(
ctl_table
*
table
,
int
op
)
{
int
error
=
0
;
u32
av
;
u32
tsid
,
sid
;
int
rc
;
sid
=
current_sid
();
rc
=
selinux_sysctl_get_sid
(
table
,
(
op
==
0001
)
?
SECCLASS_DIR
:
SECCLASS_FILE
,
&
tsid
);
if
(
rc
)
{
/* Default to the well-defined sysctl SID. */
tsid
=
SECINITSID_SYSCTL
;
}
/* The op values are "defined" in sysctl.c, thereby creating
* a bad coupling between this module and sysctl.c */
if
(
op
==
001
)
{
error
=
avc_has_perm
(
sid
,
tsid
,
SECCLASS_DIR
,
DIR__SEARCH
,
NULL
);
}
else
{
av
=
0
;
if
(
op
&
004
)
av
|=
FILE__READ
;
if
(
op
&
002
)
av
|=
FILE__WRITE
;
if
(
av
)
error
=
avc_has_perm
(
sid
,
tsid
,
SECCLASS_FILE
,
av
,
NULL
);
}
return
error
;
}
static
int
selinux_quotactl
(
int
cmds
,
int
type
,
int
id
,
struct
super_block
*
sb
)
{
const
struct
cred
*
cred
=
current_cred
();
...
...
@@ -2060,7 +1979,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
}
else
{
/* Check for a default transition on this program. */
rc
=
security_transition_sid
(
old_tsec
->
sid
,
isec
->
sid
,
SECCLASS_PROCESS
,
&
new_tsec
->
sid
);
SECCLASS_PROCESS
,
NULL
,
&
new_tsec
->
sid
);
if
(
rc
)
return
rc
;
}
...
...
@@ -2443,6 +2363,91 @@ static int selinux_sb_copy_data(char *orig, char *copy)
return
rc
;
}
static
int
selinux_sb_remount
(
struct
super_block
*
sb
,
void
*
data
)
{
int
rc
,
i
,
*
flags
;
struct
security_mnt_opts
opts
;
char
*
secdata
,
**
mount_options
;
struct
superblock_security_struct
*
sbsec
=
sb
->
s_security
;
if
(
!
(
sbsec
->
flags
&
SE_SBINITIALIZED
))
return
0
;
if
(
!
data
)
return
0
;
if
(
sb
->
s_type
->
fs_flags
&
FS_BINARY_MOUNTDATA
)
return
0
;
security_init_mnt_opts
(
&
opts
);
secdata
=
alloc_secdata
();
if
(
!
secdata
)
return
-
ENOMEM
;
rc
=
selinux_sb_copy_data
(
data
,
secdata
);
if
(
rc
)
goto
out_free_secdata
;
rc
=
selinux_parse_opts_str
(
secdata
,
&
opts
);
if
(
rc
)
goto
out_free_secdata
;
mount_options
=
opts
.
mnt_opts
;
flags
=
opts
.
mnt_opts_flags
;
for
(
i
=
0
;
i
<
opts
.
num_mnt_opts
;
i
++
)
{
u32
sid
;
size_t
len
;
if
(
flags
[
i
]
==
SE_SBLABELSUPP
)
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
);
goto
out_free_opts
;
}
rc
=
-
EINVAL
;
switch
(
flags
[
i
])
{
case
FSCONTEXT_MNT
:
if
(
bad_option
(
sbsec
,
FSCONTEXT_MNT
,
sbsec
->
sid
,
sid
))
goto
out_bad_option
;
break
;
case
CONTEXT_MNT
:
if
(
bad_option
(
sbsec
,
CONTEXT_MNT
,
sbsec
->
mntpoint_sid
,
sid
))
goto
out_bad_option
;
break
;
case
ROOTCONTEXT_MNT
:
{
struct
inode_security_struct
*
root_isec
;
root_isec
=
sb
->
s_root
->
d_inode
->
i_security
;
if
(
bad_option
(
sbsec
,
ROOTCONTEXT_MNT
,
root_isec
->
sid
,
sid
))
goto
out_bad_option
;
break
;
}
case
DEFCONTEXT_MNT
:
if
(
bad_option
(
sbsec
,
DEFCONTEXT_MNT
,
sbsec
->
def_sid
,
sid
))
goto
out_bad_option
;
break
;
default:
goto
out_free_opts
;
}
}
rc
=
0
;
out_free_opts:
security_free_mnt_opts
(
&
opts
);
out_free_secdata:
free_secdata
(
secdata
);
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
);
goto
out_free_opts
;
}
static
int
selinux_sb_kern_mount
(
struct
super_block
*
sb
,
int
flags
,
void
*
data
)
{
const
struct
cred
*
cred
=
current_cred
();
...
...
@@ -2509,8 +2514,8 @@ static void selinux_inode_free_security(struct inode *inode)
}
static
int
selinux_inode_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
c
har
**
name
,
void
**
valu
e
,
size_t
*
len
)
c
onst
struct
qstr
*
qstr
,
char
**
nam
e
,
void
**
value
,
size_t
*
len
)
{
const
struct
task_security_struct
*
tsec
=
current_security
();
struct
inode_security_struct
*
dsec
;
...
...
@@ -2531,7 +2536,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
else
if
(
!
newsid
||
!
(
sbsec
->
flags
&
SE_SBLABELSUPP
))
{
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
inode_mode_to_security_class
(
inode
->
i_mode
),
&
newsid
);
qstr
,
&
newsid
);
if
(
rc
)
{
printk
(
KERN_WARNING
"%s: "
"security_transition_sid failed, rc=%d (dev=%s "
...
...
@@ -2932,16 +2937,47 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
unsigned
long
arg
)
{
const
struct
cred
*
cred
=
current_cred
();
u32
av
=
0
;
int
error
=
0
;
if
(
_IOC_DIR
(
cmd
)
&
_IOC_WRITE
)
av
|=
FILE__WRITE
;
if
(
_IOC_DIR
(
cmd
)
&
_IOC_READ
)
av
|=
FILE__READ
;
if
(
!
av
)
av
=
FILE__IOCTL
;
switch
(
cmd
)
{
case
FIONREAD
:
/* fall through */
case
FIBMAP
:
/* fall through */
case
FIGETBSZ
:
/* fall through */
case
EXT2_IOC_GETFLAGS
:
/* fall through */
case
EXT2_IOC_GETVERSION
:
error
=
file_has_perm
(
cred
,
file
,
FILE__GETATTR
);
break
;
case
EXT2_IOC_SETFLAGS
:
/* fall through */
case
EXT2_IOC_SETVERSION
:
error
=
file_has_perm
(
cred
,
file
,
FILE__SETATTR
);
break
;
/* sys_ioctl() checks */
case
FIONBIO
:
/* fall through */
case
FIOASYNC
:
error
=
file_has_perm
(
cred
,
file
,
0
);
break
;
return
file_has_perm
(
cred
,
file
,
av
);
case
KDSKBENT
:
case
KDSKBSENT
:
error
=
task_has_capability
(
current
,
cred
,
CAP_SYS_TTY_CONFIG
,
SECURITY_CAP_AUDIT
);
break
;
/* default case assumes that the command will go
* to the file's ioctl() function.
*/
default:
error
=
file_has_perm
(
cred
,
file
,
FILE__IOCTL
);
}
return
error
;
}
static
int
default_noexec
;
...
...
@@ -3644,9 +3680,16 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
/* socket security operations */
static
u32
socket_sockcreate_sid
(
const
struct
task_security_struct
*
tsec
)
static
int
socket_sockcreate_sid
(
const
struct
task_security_struct
*
tsec
,
u16
secclass
,
u32
*
socksid
)
{
return
tsec
->
sockcreate_sid
?
:
tsec
->
sid
;
if
(
tsec
->
sockcreate_sid
>
SECSID_NULL
)
{
*
socksid
=
tsec
->
sockcreate_sid
;
return
0
;
}
return
security_transition_sid
(
tsec
->
sid
,
tsec
->
sid
,
secclass
,
NULL
,
socksid
);
}
static
int
sock_has_perm
(
struct
task_struct
*
task
,
struct
sock
*
sk
,
u32
perms
)
...
...
@@ -3670,12 +3713,16 @@ static int selinux_socket_create(int family, int type,
const
struct
task_security_struct
*
tsec
=
current_security
();
u32
newsid
;
u16
secclass
;
int
rc
;
if
(
kern
)
return
0
;
newsid
=
socket_sockcreate_sid
(
tsec
);
secclass
=
socket_type_to_security_class
(
family
,
type
,
protocol
);
rc
=
socket_sockcreate_sid
(
tsec
,
secclass
,
&
newsid
);
if
(
rc
)
return
rc
;
return
avc_has_perm
(
tsec
->
sid
,
newsid
,
secclass
,
SOCKET__CREATE
,
NULL
);
}
...
...
@@ -3687,12 +3734,16 @@ static int selinux_socket_post_create(struct socket *sock, int family,
struct
sk_security_struct
*
sksec
;
int
err
=
0
;
isec
->
sclass
=
socket_type_to_security_class
(
family
,
type
,
protocol
);
if
(
kern
)
isec
->
sid
=
SECINITSID_KERNEL
;
else
isec
->
sid
=
socket_sockcreate_sid
(
tsec
);
else
{
err
=
socket_sockcreate_sid
(
tsec
,
isec
->
sclass
,
&
(
isec
->
sid
));
if
(
err
)
return
err
;
}
isec
->
sclass
=
socket_type_to_security_class
(
family
,
type
,
protocol
);
isec
->
initialized
=
1
;
if
(
sock
->
sk
)
{
...
...
@@ -4002,7 +4053,6 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
{
int
err
=
0
;
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
u32
peer_sid
;
u32
sk_sid
=
sksec
->
sid
;
struct
common_audit_data
ad
;
char
*
addrp
;
...
...
@@ -4021,20 +4071,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
return
err
;
}
if
(
selinux_policycap_netpeer
)
{
err
=
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
);
if
(
err
)
return
err
;
err
=
avc_has_perm
(
sk_sid
,
peer_sid
,
SECCLASS_PEER
,
PEER__RECV
,
&
ad
);
if
(
err
)
selinux_netlbl_err
(
skb
,
err
,
0
);
}
else
{
err
=
selinux_netlbl_sock_rcv_skb
(
sksec
,
skb
,
family
,
&
ad
);
if
(
err
)
return
err
;
err
=
selinux_xfrm_sock_rcv_skb
(
sksec
->
sid
,
skb
,
&
ad
);
}
err
=
selinux_netlbl_sock_rcv_skb
(
sksec
,
skb
,
family
,
&
ad
);
if
(
err
)
return
err
;
err
=
selinux_xfrm_sock_rcv_skb
(
sksec
->
sid
,
skb
,
&
ad
);
return
err
;
}
...
...
@@ -4529,9 +4569,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
SECCLASS_PACKET
,
PACKET__SEND
,
&
ad
))
return
NF_DROP_ERR
(
-
ECONNREFUSED
);
if
(
selinux_policycap_netpeer
)
if
(
selinux_xfrm_postroute_last
(
sksec
->
sid
,
skb
,
&
ad
,
proto
))
return
NF_DROP_ERR
(
-
ECONNREFUSED
);
if
(
selinux_xfrm_postroute_last
(
sksec
->
sid
,
skb
,
&
ad
,
proto
))
return
NF_DROP_ERR
(
-
ECONNREFUSED
);
return
NF_ACCEPT
;
}
...
...
@@ -4574,27 +4613,14 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
* from the sending socket, otherwise use the kernel's sid */
sk
=
skb
->
sk
;
if
(
sk
==
NULL
)
{
switch
(
family
)
{
case
PF_INET
:
if
(
IPCB
(
skb
)
->
flags
&
IPSKB_FORWARDED
)
secmark_perm
=
PACKET__FORWARD_OUT
;
else
secmark_perm
=
PACKET__SEND
;
break
;
case
PF_INET6
:
if
(
IP6CB
(
skb
)
->
flags
&
IP6SKB_FORWARDED
)
secmark_perm
=
PACKET__FORWARD_OUT
;
else
secmark_perm
=
PACKET__SEND
;
break
;
default:
return
NF_DROP_ERR
(
-
ECONNREFUSED
);
}
if
(
secmark_perm
==
PACKET__FORWARD_OUT
)
{
if
(
skb
->
skb_iif
)
{
secmark_perm
=
PACKET__FORWARD_OUT
;
if
(
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
))
return
NF_DROP
;
}
else
}
else
{
secmark_perm
=
PACKET__SEND
;
peer_sid
=
SECINITSID_KERNEL
;
}
}
else
{
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
peer_sid
=
sksec
->
sid
;
...
...
@@ -4848,7 +4874,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
* message queue this message will be stored in
*/
rc
=
security_transition_sid
(
sid
,
isec
->
sid
,
SECCLASS_MSG
,
&
msec
->
sid
);
NULL
,
&
msec
->
sid
);
if
(
rc
)
return
rc
;
}
...
...
@@ -5402,7 +5428,6 @@ static struct security_operations selinux_ops = {
.
ptrace_traceme
=
selinux_ptrace_traceme
,
.
capget
=
selinux_capget
,
.
capset
=
selinux_capset
,
.
sysctl
=
selinux_sysctl
,
.
capable
=
selinux_capable
,
.
quotactl
=
selinux_quotactl
,
.
quota_on
=
selinux_quota_on
,
...
...
@@ -5420,6 +5445,7 @@ static struct security_operations selinux_ops = {
.
sb_alloc_security
=
selinux_sb_alloc_security
,
.
sb_free_security
=
selinux_sb_free_security
,
.
sb_copy_data
=
selinux_sb_copy_data
,
.
sb_remount
=
selinux_sb_remount
,
.
sb_kern_mount
=
selinux_sb_kern_mount
,
.
sb_show_options
=
selinux_sb_show_options
,
.
sb_statfs
=
selinux_sb_statfs
,
...
...
security/selinux/include/classmap.h
浏览文件 @
a002951c
...
...
@@ -12,6 +12,10 @@
#define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \
"write", "associate", "unix_read", "unix_write"
/*
* Note: The name for any socket class should be suffixed by "socket",
* and doesn't contain more than one substr of "socket".
*/
struct
security_class_mapping
secclass_map
[]
=
{
{
"security"
,
{
"compute_av"
,
"compute_create"
,
"compute_member"
,
...
...
@@ -132,8 +136,7 @@ struct security_class_mapping secclass_map[] = {
{
"appletalk_socket"
,
{
COMMON_SOCK_PERMS
,
NULL
}
},
{
"packet"
,
{
"send"
,
"recv"
,
"relabelto"
,
"flow_in"
,
"flow_out"
,
"forward_in"
,
"forward_out"
,
NULL
}
},
{
"send"
,
"recv"
,
"relabelto"
,
"forward_in"
,
"forward_out"
,
NULL
}
},
{
"key"
,
{
"view"
,
"read"
,
"write"
,
"search"
,
"link"
,
"setattr"
,
"create"
,
NULL
}
},
...
...
security/selinux/include/security.h
浏览文件 @
a002951c
...
...
@@ -8,6 +8,7 @@
#ifndef _SELINUX_SECURITY_H_
#define _SELINUX_SECURITY_H_
#include <linux/dcache.h>
#include <linux/magic.h>
#include <linux/types.h>
#include "flask.h"
...
...
@@ -28,13 +29,14 @@
#define POLICYDB_VERSION_POLCAP 22
#define POLICYDB_VERSION_PERMISSIVE 23
#define POLICYDB_VERSION_BOUNDARY 24
#define POLICYDB_VERSION_FILENAME_TRANS 25
/* 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_
BOUNDARY
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_
FILENAME_TRANS
#endif
/* Mask for just the mount related flags */
...
...
@@ -106,8 +108,8 @@ void security_compute_av(u32 ssid, u32 tsid,
void
security_compute_av_user
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
struct
av_decision
*
avd
);
int
security_transition_sid
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
*
out_sid
);
int
security_transition_sid
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
const
struct
qstr
*
qstr
,
u32
*
out_sid
);
int
security_transition_sid_user
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
*
out_sid
);
...
...
security/selinux/ss/avtab.h
浏览文件 @
a002951c
...
...
@@ -14,7 +14,7 @@
*
* Copyright (C) 2003 Tresys Technology, LLC
* This program is free software; you can redistribute it and/or modify
*
it under the terms of the GNU General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
...
...
@@ -27,16 +27,16 @@ struct avtab_key {
u16
source_type
;
/* source type */
u16
target_type
;
/* target type */
u16
target_class
;
/* target object class */
#define AVTAB_ALLOWED
1
#define AVTAB_AUDITALLOW
2
#define AVTAB_AUDITDENY
4
#define AVTAB_AV
(AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
#define AVTAB_TRANSITION
16
#define AVTAB_MEMBER
32
#define AVTAB_CHANGE
64
#define AVTAB_TYPE
(AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
#define AVTAB_ENABLED_OLD
0x80000000
/* reserved for used in cond_avtab */
#define AVTAB_ENABLED
0x8000
/* reserved for used in cond_avtab */
#define AVTAB_ALLOWED
0x000
1
#define AVTAB_AUDITALLOW
0x000
2
#define AVTAB_AUDITDENY
0x000
4
#define AVTAB_AV
(AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
#define AVTAB_TRANSITION
0x0010
#define AVTAB_MEMBER
0x0020
#define AVTAB_CHANGE
0x0040
#define AVTAB_TYPE
(AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
#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 */
};
...
...
@@ -86,7 +86,6 @@ void avtab_cache_destroy(void);
#define MAX_AVTAB_HASH_BITS 11
#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
#define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1)
#endif
/* _SS_AVTAB_H_ */
security/selinux/ss/ebitmap.h
浏览文件 @
a002951c
...
...
@@ -36,7 +36,6 @@ struct ebitmap {
};
#define ebitmap_length(e) ((e)->highbit)
#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
static
inline
unsigned
int
ebitmap_start_positive
(
struct
ebitmap
*
e
,
struct
ebitmap_node
**
n
)
...
...
security/selinux/ss/mls.c
浏览文件 @
a002951c
...
...
@@ -512,7 +512,8 @@ int mls_compute_sid(struct context *scontext,
struct
context
*
tcontext
,
u16
tclass
,
u32
specified
,
struct
context
*
newcontext
)
struct
context
*
newcontext
,
bool
sock
)
{
struct
range_trans
rtr
;
struct
mls_range
*
r
;
...
...
@@ -531,7 +532,7 @@ int mls_compute_sid(struct context *scontext,
return
mls_range_set
(
newcontext
,
r
);
/* Fallthrough */
case
AVTAB_CHANGE
:
if
(
tclass
==
policydb
.
process_class
)
if
(
(
tclass
==
policydb
.
process_class
)
||
(
sock
==
true
)
)
/* Use the process MLS attributes. */
return
mls_context_cpy
(
newcontext
,
scontext
);
else
...
...
security/selinux/ss/mls.h
浏览文件 @
a002951c
...
...
@@ -49,7 +49,8 @@ int mls_compute_sid(struct context *scontext,
struct
context
*
tcontext
,
u16
tclass
,
u32
specified
,
struct
context
*
newcontext
);
struct
context
*
newcontext
,
bool
sock
);
int
mls_setup_user_range
(
struct
context
*
fromcon
,
struct
user_datum
*
user
,
struct
context
*
usercon
);
...
...
security/selinux/ss/policydb.c
浏览文件 @
a002951c
...
...
@@ -123,6 +123,11 @@ static struct policydb_compat_info policydb_compat[] = {
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
{
.
version
=
POLICYDB_VERSION_FILENAME_TRANS
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
};
static
struct
policydb_compat_info
*
policydb_lookup_compat
(
int
version
)
...
...
@@ -704,6 +709,7 @@ void policydb_destroy(struct policydb *p)
int
i
;
struct
role_allow
*
ra
,
*
lra
=
NULL
;
struct
role_trans
*
tr
,
*
ltr
=
NULL
;
struct
filename_trans
*
ft
,
*
nft
;
for
(
i
=
0
;
i
<
SYM_NUM
;
i
++
)
{
cond_resched
();
...
...
@@ -781,6 +787,15 @@ void policydb_destroy(struct policydb *p)
}
flex_array_free
(
p
->
type_attr_map_array
);
}
ft
=
p
->
filename_trans
;
while
(
ft
)
{
nft
=
ft
->
next
;
kfree
(
ft
->
name
);
kfree
(
ft
);
ft
=
nft
;
}
ebitmap_destroy
(
&
p
->
policycaps
);
ebitmap_destroy
(
&
p
->
permissive_map
);
...
...
@@ -1788,6 +1803,76 @@ static int range_read(struct policydb *p, void *fp)
return
rc
;
}
static
int
filename_trans_read
(
struct
policydb
*
p
,
void
*
fp
)
{
struct
filename_trans
*
ft
,
*
last
;
u32
nel
,
len
;
char
*
name
;
__le32
buf
[
4
];
int
rc
,
i
;
if
(
p
->
policyvers
<
POLICYDB_VERSION_FILENAME_TRANS
)
return
0
;
rc
=
next_entry
(
buf
,
fp
,
sizeof
(
u32
));
if
(
rc
)
goto
out
;
nel
=
le32_to_cpu
(
buf
[
0
]);
printk
(
KERN_ERR
"%s: nel=%d
\n
"
,
__func__
,
nel
);
last
=
p
->
filename_trans
;
while
(
last
&&
last
->
next
)
last
=
last
->
next
;
for
(
i
=
0
;
i
<
nel
;
i
++
)
{
rc
=
-
ENOMEM
;
ft
=
kzalloc
(
sizeof
(
*
ft
),
GFP_KERNEL
);
if
(
!
ft
)
goto
out
;
/* add it to the tail of the list */
if
(
!
last
)
p
->
filename_trans
=
ft
;
else
last
->
next
=
ft
;
last
=
ft
;
/* length of the path component string */
rc
=
next_entry
(
buf
,
fp
,
sizeof
(
u32
));
if
(
rc
)
goto
out
;
len
=
le32_to_cpu
(
buf
[
0
]);
rc
=
-
ENOMEM
;
name
=
kmalloc
(
len
+
1
,
GFP_KERNEL
);
if
(
!
name
)
goto
out
;
ft
->
name
=
name
;
/* path component string */
rc
=
next_entry
(
name
,
fp
,
len
);
if
(
rc
)
goto
out
;
name
[
len
]
=
0
;
printk
(
KERN_ERR
"%s: ft=%p ft->name=%p ft->name=%s
\n
"
,
__func__
,
ft
,
ft
->
name
,
ft
->
name
);
rc
=
next_entry
(
buf
,
fp
,
sizeof
(
u32
)
*
4
);
if
(
rc
)
goto
out
;
ft
->
stype
=
le32_to_cpu
(
buf
[
0
]);
ft
->
ttype
=
le32_to_cpu
(
buf
[
1
]);
ft
->
tclass
=
le32_to_cpu
(
buf
[
2
]);
ft
->
otype
=
le32_to_cpu
(
buf
[
3
]);
}
rc
=
0
;
out:
return
rc
;
}
static
int
genfs_read
(
struct
policydb
*
p
,
void
*
fp
)
{
int
i
,
j
,
rc
;
...
...
@@ -2251,6 +2336,10 @@ int policydb_read(struct policydb *p, void *fp)
lra
=
ra
;
}
rc
=
filename_trans_read
(
p
,
fp
);
if
(
rc
)
goto
bad
;
rc
=
policydb_index
(
p
);
if
(
rc
)
goto
bad
;
...
...
@@ -3025,6 +3114,43 @@ static int range_write(struct policydb *p, void *fp)
return
0
;
}
static
int
filename_trans_write
(
struct
policydb
*
p
,
void
*
fp
)
{
struct
filename_trans
*
ft
;
u32
len
,
nel
=
0
;
__le32
buf
[
4
];
int
rc
;
for
(
ft
=
p
->
filename_trans
;
ft
;
ft
=
ft
->
next
)
nel
++
;
buf
[
0
]
=
cpu_to_le32
(
nel
);
rc
=
put_entry
(
buf
,
sizeof
(
u32
),
1
,
fp
);
if
(
rc
)
return
rc
;
for
(
ft
=
p
->
filename_trans
;
ft
;
ft
=
ft
->
next
)
{
len
=
strlen
(
ft
->
name
);
buf
[
0
]
=
cpu_to_le32
(
len
);
rc
=
put_entry
(
buf
,
sizeof
(
u32
),
1
,
fp
);
if
(
rc
)
return
rc
;
rc
=
put_entry
(
ft
->
name
,
sizeof
(
char
),
len
,
fp
);
if
(
rc
)
return
rc
;
buf
[
0
]
=
ft
->
stype
;
buf
[
1
]
=
ft
->
ttype
;
buf
[
2
]
=
ft
->
tclass
;
buf
[
3
]
=
ft
->
otype
;
rc
=
put_entry
(
buf
,
sizeof
(
u32
),
4
,
fp
);
if
(
rc
)
return
rc
;
}
return
0
;
}
/*
* Write the configuration data in a policy database
* structure to a policy database binary representation
...
...
@@ -3135,6 +3261,10 @@ int policydb_write(struct policydb *p, void *fp)
if
(
rc
)
return
rc
;
rc
=
filename_trans_write
(
p
,
fp
);
if
(
rc
)
return
rc
;
rc
=
ocontext_write
(
p
,
info
,
fp
);
if
(
rc
)
return
rc
;
...
...
security/selinux/ss/policydb.h
浏览文件 @
a002951c
...
...
@@ -77,6 +77,15 @@ struct role_trans {
struct
role_trans
*
next
;
};
struct
filename_trans
{
struct
filename_trans
*
next
;
u32
stype
;
/* current process */
u32
ttype
;
/* parent dir context */
u16
tclass
;
/* class of new object */
const
char
*
name
;
/* last path component */
u32
otype
;
/* expected of new object */
};
struct
role_allow
{
u32
role
;
/* current role */
u32
new_role
;
/* new role */
...
...
@@ -217,6 +226,9 @@ struct policydb {
/* role transitions */
struct
role_trans
*
role_tr
;
/* file transitions with the last path component */
struct
filename_trans
*
filename_trans
;
/* bools indexed by (value - 1) */
struct
cond_bool_datum
**
bool_val_to_struct
;
/* type enforcement conditional access vectors and transitions */
...
...
@@ -302,7 +314,7 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
return
0
;
}
static
inline
int
put_entry
(
void
*
buf
,
size_t
bytes
,
int
num
,
struct
policy_file
*
fp
)
static
inline
int
put_entry
(
const
void
*
buf
,
size_t
bytes
,
int
num
,
struct
policy_file
*
fp
)
{
size_t
len
=
bytes
*
num
;
...
...
security/selinux/ss/services.c
浏览文件 @
a002951c
...
...
@@ -201,6 +201,21 @@ static u16 unmap_class(u16 tclass)
return
tclass
;
}
/*
* Get kernel value for class from its policy value
*/
static
u16
map_class
(
u16
pol_value
)
{
u16
i
;
for
(
i
=
1
;
i
<
current_mapping_size
;
i
++
)
{
if
(
current_mapping
[
i
].
value
==
pol_value
)
return
i
;
}
return
pol_value
;
}
static
void
map_decision
(
u16
tclass
,
struct
av_decision
*
avd
,
int
allow_unknown
)
{
...
...
@@ -1343,10 +1358,27 @@ static int compute_sid_handle_invalid_context(
return
-
EACCES
;
}
static
void
filename_compute_type
(
struct
policydb
*
p
,
struct
context
*
newcontext
,
u32
scon
,
u32
tcon
,
u16
tclass
,
const
struct
qstr
*
qstr
)
{
struct
filename_trans
*
ft
;
for
(
ft
=
p
->
filename_trans
;
ft
;
ft
=
ft
->
next
)
{
if
(
ft
->
stype
==
scon
&&
ft
->
ttype
==
tcon
&&
ft
->
tclass
==
tclass
&&
!
strcmp
(
ft
->
name
,
qstr
->
name
))
{
newcontext
->
type
=
ft
->
otype
;
return
;
}
}
}
static
int
security_compute_sid
(
u32
ssid
,
u32
tsid
,
u16
orig_tclass
,
u32
specified
,
const
struct
qstr
*
qstr
,
u32
*
out_sid
,
bool
kern
)
{
...
...
@@ -1357,6 +1389,7 @@ static int security_compute_sid(u32 ssid,
struct
avtab_node
*
node
;
u16
tclass
;
int
rc
=
0
;
bool
sock
;
if
(
!
ss_initialized
)
{
switch
(
orig_tclass
)
{
...
...
@@ -1374,10 +1407,13 @@ static int security_compute_sid(u32 ssid,
read_lock
(
&
policy_rwlock
);
if
(
kern
)
if
(
kern
)
{
tclass
=
unmap_class
(
orig_tclass
);
else
sock
=
security_is_socket_class
(
orig_tclass
);
}
else
{
tclass
=
orig_tclass
;
sock
=
security_is_socket_class
(
map_class
(
tclass
));
}
scontext
=
sidtab_search
(
&
sidtab
,
ssid
);
if
(
!
scontext
)
{
...
...
@@ -1408,7 +1444,7 @@ static int security_compute_sid(u32 ssid,
}
/* Set the role and type to default values. */
if
(
tclass
==
policydb
.
process_class
)
{
if
(
(
tclass
==
policydb
.
process_class
)
||
(
sock
==
true
)
)
{
/* Use the current role and type of process. */
newcontext
.
role
=
scontext
->
role
;
newcontext
.
type
=
scontext
->
type
;
...
...
@@ -1442,6 +1478,11 @@ static int security_compute_sid(u32 ssid,
newcontext
.
type
=
avdatum
->
data
;
}
/* if we have a qstr this is a file trans check so check those rules */
if
(
qstr
)
filename_compute_type
(
&
policydb
,
&
newcontext
,
scontext
->
type
,
tcontext
->
type
,
tclass
,
qstr
);
/* Check for class-specific changes. */
if
(
tclass
==
policydb
.
process_class
)
{
if
(
specified
&
AVTAB_TRANSITION
)
{
...
...
@@ -1460,7 +1501,8 @@ static int security_compute_sid(u32 ssid,
/* Set the MLS attributes.
This is done last because it may allocate memory. */
rc
=
mls_compute_sid
(
scontext
,
tcontext
,
tclass
,
specified
,
&
newcontext
);
rc
=
mls_compute_sid
(
scontext
,
tcontext
,
tclass
,
specified
,
&
newcontext
,
sock
);
if
(
rc
)
goto
out_unlock
;
...
...
@@ -1495,22 +1537,17 @@ static int security_compute_sid(u32 ssid,
* if insufficient memory is available, or %0 if the new SID was
* computed successfully.
*/
int
security_transition_sid
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
*
out_sid
)
int
security_transition_sid
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
const
struct
qstr
*
qstr
,
u32
*
out_sid
)
{
return
security_compute_sid
(
ssid
,
tsid
,
tclass
,
AVTAB_TRANSITION
,
out_sid
,
true
);
qstr
,
out_sid
,
true
);
}
int
security_transition_sid_user
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
*
out_sid
)
int
security_transition_sid_user
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
*
out_sid
)
{
return
security_compute_sid
(
ssid
,
tsid
,
tclass
,
AVTAB_TRANSITION
,
out_sid
,
false
);
NULL
,
out_sid
,
false
);
}
/**
...
...
@@ -1531,8 +1568,8 @@ int security_member_sid(u32 ssid,
u16
tclass
,
u32
*
out_sid
)
{
return
security_compute_sid
(
ssid
,
tsid
,
tclass
,
AVTAB_MEMBER
,
out_sid
,
false
);
return
security_compute_sid
(
ssid
,
tsid
,
tclass
,
AVTAB_MEMBER
,
NULL
,
out_sid
,
false
);
}
/**
...
...
@@ -1553,8 +1590,8 @@ int security_change_sid(u32 ssid,
u16
tclass
,
u32
*
out_sid
)
{
return
security_compute_sid
(
ssid
,
tsid
,
tclass
,
AVTAB_CHANGE
,
out_sid
,
false
);
return
security_compute_sid
(
ssid
,
tsid
,
tclass
,
AVTAB_CHANGE
,
NULL
,
out_sid
,
false
);
}
/* Clone the SID into the new SID table. */
...
...
security/selinux/xfrm.c
浏览文件 @
a002951c
...
...
@@ -208,7 +208,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
if
(
!
uctx
)
goto
not_from_user
;
if
(
uctx
->
ctx_
doi
!=
XFRM_SC_ALG_SELINUX
)
if
(
uctx
->
ctx_
alg
!=
XFRM_SC_ALG_SELINUX
)
return
-
EINVAL
;
str_len
=
uctx
->
ctx_len
;
...
...
security/smack/smack.h
浏览文件 @
a002951c
...
...
@@ -52,13 +52,16 @@ struct socket_smack {
struct
inode_smack
{
char
*
smk_inode
;
/* label of the fso */
char
*
smk_task
;
/* label of the task */
char
*
smk_mmap
;
/* label of the mmap domain */
struct
mutex
smk_lock
;
/* initialization lock */
int
smk_flags
;
/* smack inode flags */
};
struct
task_smack
{
char
*
smk_task
;
/* label used for access control */
char
*
smk_forked
;
/* label when forked */
char
*
smk_task
;
/* label for access control */
char
*
smk_forked
;
/* label when forked */
struct
list_head
smk_rules
;
/* per task access rules */
struct
mutex
smk_rules_lock
;
/* lock for the rules */
};
#define SMK_INODE_INSTANT 0x01
/* inode is instantiated */
...
...
@@ -151,12 +154,6 @@ struct smack_known {
*/
#define SMACK_MAGIC 0x43415d53
/* "SMAC" */
/*
* A limit on the number of entries in the lists
* makes some of the list administration easier.
*/
#define SMACK_LIST_MAX 10000
/*
* CIPSO defaults.
*/
...
...
@@ -174,9 +171,7 @@ struct smack_known {
/*
* Just to make the common cases easier to deal with
*/
#define MAY_ANY (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
#define MAY_ANYREAD (MAY_READ | MAY_EXEC)
#define MAY_ANYWRITE (MAY_WRITE | MAY_APPEND)
#define MAY_READWRITE (MAY_READ | MAY_WRITE)
#define MAY_NOT 0
...
...
@@ -202,7 +197,7 @@ struct inode_smack *new_inode_smack(char *);
/*
* These functions are in smack_access.c
*/
int
smk_access_entry
(
char
*
,
char
*
);
int
smk_access_entry
(
char
*
,
char
*
,
struct
list_head
*
);
int
smk_access
(
char
*
,
char
*
,
int
,
struct
smk_audit_info
*
);
int
smk_curacc
(
char
*
,
u32
,
struct
smk_audit_info
*
);
int
smack_to_cipso
(
const
char
*
,
struct
smack_cipso
*
);
...
...
security/smack/smack_access.c
浏览文件 @
a002951c
...
...
@@ -70,10 +70,11 @@ int log_policy = SMACK_AUDIT_DENIED;
* smk_access_entry - look up matching access rule
* @subject_label: a pointer to the subject's Smack label
* @object_label: a pointer to the object's Smack label
* @rule_list: the list of rules to search
*
* This function looks up the subject/object pair in the
* access rule list and returns
pointer to the matching rule if found,
*
NULL otherwise
.
* access rule list and returns
the access mode. If no
*
entry is found returns -ENOENT
.
*
* NOTE:
* Even though Smack labels are usually shared on smack_list
...
...
@@ -85,13 +86,13 @@ int log_policy = SMACK_AUDIT_DENIED;
* will be on the list, so checking the pointers may be a worthwhile
* optimization.
*/
int
smk_access_entry
(
char
*
subject_label
,
char
*
object_label
)
int
smk_access_entry
(
char
*
subject_label
,
char
*
object_label
,
struct
list_head
*
rule_list
)
{
u32
may
=
MAY_NO
T
;
int
may
=
-
ENOEN
T
;
struct
smack_rule
*
srp
;
rcu_read_lock
();
list_for_each_entry_rcu
(
srp
,
&
smack_rule_list
,
list
)
{
list_for_each_entry_rcu
(
srp
,
rule_list
,
list
)
{
if
(
srp
->
smk_subject
==
subject_label
||
strcmp
(
srp
->
smk_subject
,
subject_label
)
==
0
)
{
if
(
srp
->
smk_object
==
object_label
||
...
...
@@ -101,7 +102,6 @@ int smk_access_entry(char *subject_label, char *object_label)
}
}
}
rcu_read_unlock
();
return
may
;
}
...
...
@@ -129,7 +129,7 @@ int smk_access_entry(char *subject_label, char *object_label)
int
smk_access
(
char
*
subject_label
,
char
*
object_label
,
int
request
,
struct
smk_audit_info
*
a
)
{
u32
may
=
MAY_NOT
;
int
may
=
MAY_NOT
;
int
rc
=
0
;
/*
...
...
@@ -181,13 +181,14 @@ int smk_access(char *subject_label, char *object_label, int request,
* Beyond here an explicit relationship is required.
* If the requested access is contained in the available
* access (e.g. read is included in readwrite) it's
* good.
*/
may
=
smk_access_entry
(
subject_label
,
object_label
);
/*
* This is a bit map operation.
* good. A negative response from smk_access_entry()
* indicates there is no entry for this pair.
*/
if
((
request
&
may
)
==
request
)
rcu_read_lock
();
may
=
smk_access_entry
(
subject_label
,
object_label
,
&
smack_rule_list
);
rcu_read_unlock
();
if
(
may
>
0
&&
(
request
&
may
)
==
request
)
goto
out_audit
;
rc
=
-
EACCES
;
...
...
@@ -212,12 +213,27 @@ int smk_access(char *subject_label, char *object_label, int request,
*/
int
smk_curacc
(
char
*
obj_label
,
u32
mode
,
struct
smk_audit_info
*
a
)
{
struct
task_smack
*
tsp
=
current_security
();
char
*
sp
=
smk_of_task
(
tsp
);
int
may
;
int
rc
;
char
*
sp
=
smk_of_current
();
/*
* Check the global rule list
*/
rc
=
smk_access
(
sp
,
obj_label
,
mode
,
NULL
);
if
(
rc
==
0
)
goto
out_audit
;
if
(
rc
==
0
)
{
/*
* If there is an entry in the task's rule list
* it can further restrict access.
*/
may
=
smk_access_entry
(
sp
,
obj_label
,
&
tsp
->
smk_rules
);
if
(
may
<
0
)
goto
out_audit
;
if
((
mode
&
may
)
==
mode
)
goto
out_audit
;
rc
=
-
EACCES
;
}
/*
* Return if a specific label has been designated as the
...
...
@@ -228,7 +244,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
goto
out_audit
;
if
(
capable
(
CAP_MAC_OVERRIDE
))
r
eturn
0
;
r
c
=
0
;
out_audit:
#ifdef CONFIG_AUDIT
...
...
security/smack/smack_lsm.c
浏览文件 @
a002951c
...
...
@@ -33,6 +33,7 @@
#include <net/cipso_ipv4.h>
#include <linux/audit.h>
#include <linux/magic.h>
#include <linux/dcache.h>
#include "smack.h"
#define task_security(task) (task_cred_xxx((task), security))
...
...
@@ -84,6 +85,56 @@ struct inode_smack *new_inode_smack(char *smack)
return
isp
;
}
/**
* new_task_smack - allocate a task security blob
* @smack: a pointer to the Smack label to use in the blob
*
* Returns the new blob or NULL if there's no memory available
*/
static
struct
task_smack
*
new_task_smack
(
char
*
task
,
char
*
forked
,
gfp_t
gfp
)
{
struct
task_smack
*
tsp
;
tsp
=
kzalloc
(
sizeof
(
struct
task_smack
),
gfp
);
if
(
tsp
==
NULL
)
return
NULL
;
tsp
->
smk_task
=
task
;
tsp
->
smk_forked
=
forked
;
INIT_LIST_HEAD
(
&
tsp
->
smk_rules
);
mutex_init
(
&
tsp
->
smk_rules_lock
);
return
tsp
;
}
/**
* smk_copy_rules - copy a rule set
* @nhead - new rules header pointer
* @ohead - old rules header pointer
*
* Returns 0 on success, -ENOMEM on error
*/
static
int
smk_copy_rules
(
struct
list_head
*
nhead
,
struct
list_head
*
ohead
,
gfp_t
gfp
)
{
struct
smack_rule
*
nrp
;
struct
smack_rule
*
orp
;
int
rc
=
0
;
INIT_LIST_HEAD
(
nhead
);
list_for_each_entry_rcu
(
orp
,
ohead
,
list
)
{
nrp
=
kzalloc
(
sizeof
(
struct
smack_rule
),
gfp
);
if
(
nrp
==
NULL
)
{
rc
=
-
ENOMEM
;
break
;
}
*
nrp
=
*
orp
;
list_add_rcu
(
&
nrp
->
list
,
nhead
);
}
return
rc
;
}
/*
* LSM hooks.
* We he, that is fun!
...
...
@@ -102,23 +153,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
{
int
rc
;
struct
smk_audit_info
ad
;
char
*
sp
,
*
tsp
;
char
*
tsp
;
rc
=
cap_ptrace_access_check
(
ctp
,
mode
);
if
(
rc
!=
0
)
return
rc
;
sp
=
smk_of_current
();
tsp
=
smk_of_task
(
task_security
(
ctp
));
smk_ad_init
(
&
ad
,
__func__
,
LSM_AUDIT_DATA_TASK
);
smk_ad_setfield_u_tsk
(
&
ad
,
ctp
);
/* we won't log here, because rc can be overriden */
rc
=
smk_access
(
sp
,
tsp
,
MAY_READWRITE
,
NULL
);
if
(
rc
!=
0
&&
capable
(
CAP_MAC_OVERRIDE
))
rc
=
0
;
smack_log
(
sp
,
tsp
,
MAY_READWRITE
,
rc
,
&
ad
);
rc
=
smk_curacc
(
tsp
,
MAY_READWRITE
,
&
ad
);
return
rc
;
}
...
...
@@ -134,23 +179,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
{
int
rc
;
struct
smk_audit_info
ad
;
char
*
sp
,
*
tsp
;
char
*
tsp
;
rc
=
cap_ptrace_traceme
(
ptp
);
if
(
rc
!=
0
)
return
rc
;
tsp
=
smk_of_task
(
task_security
(
ptp
));
smk_ad_init
(
&
ad
,
__func__
,
LSM_AUDIT_DATA_TASK
);
smk_ad_setfield_u_tsk
(
&
ad
,
ptp
);
sp
=
smk_of_current
();
tsp
=
smk_of_task
(
task_security
(
ptp
));
/* we won't log here, because rc can be overriden */
rc
=
smk_access
(
tsp
,
sp
,
MAY_READWRITE
,
NULL
);
if
(
rc
!=
0
&&
has_capability
(
ptp
,
CAP_MAC_OVERRIDE
))
rc
=
0
;
smack_log
(
tsp
,
sp
,
MAY_READWRITE
,
rc
,
&
ad
);
rc
=
smk_curacc
(
tsp
,
MAY_READWRITE
,
&
ad
);
return
rc
;
}
...
...
@@ -463,6 +502,7 @@ static void smack_inode_free_security(struct inode *inode)
* smack_inode_init_security - copy out the smack from an inode
* @inode: the inode
* @dir: unused
* @qstr: unused
* @name: where to put the attribute name
* @value: where to put the attribute value
* @len: where to put the length of the attribute
...
...
@@ -470,11 +510,12 @@ static void smack_inode_free_security(struct inode *inode)
* Returns 0 if it all works out, -ENOMEM if there's no memory
*/
static
int
smack_inode_init_security
(
struct
inode
*
inode
,
struct
inode
*
dir
,
char
**
name
,
void
**
value
,
size_t
*
len
)
const
struct
qstr
*
qstr
,
char
**
name
,
void
**
value
,
size_t
*
len
)
{
char
*
isp
=
smk_of_inode
(
inode
);
char
*
dsp
=
smk_of_inode
(
dir
);
u32
may
;
int
may
;
if
(
name
)
{
*
name
=
kstrdup
(
XATTR_SMACK_SUFFIX
,
GFP_KERNEL
);
...
...
@@ -483,14 +524,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
}
if
(
value
)
{
may
=
smk_access_entry
(
smk_of_current
(),
dsp
);
rcu_read_lock
();
may
=
smk_access_entry
(
smk_of_current
(),
dsp
,
&
smack_rule_list
);
rcu_read_unlock
();
/*
* If the access rule allows transmutation and
* the directory requests transmutation then
* by all means transmute.
*/
if
(((
may
&
MAY_TRANSMUTE
)
!=
0
)
&&
smk_inode_transmutable
(
dir
))
if
(
may
>
0
&&
((
may
&
MAY_TRANSMUTE
)
!=
0
)
&&
smk_inode_transmutable
(
dir
))
isp
=
dsp
;
*
value
=
kstrdup
(
isp
,
GFP_KERNEL
);
...
...
@@ -716,7 +760,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
if
(
strcmp
(
name
,
XATTR_NAME_SMACK
)
==
0
||
strcmp
(
name
,
XATTR_NAME_SMACKIPIN
)
==
0
||
strcmp
(
name
,
XATTR_NAME_SMACKIPOUT
)
==
0
||
strcmp
(
name
,
XATTR_NAME_SMACKEXEC
)
==
0
)
{
strcmp
(
name
,
XATTR_NAME_SMACKEXEC
)
==
0
||
strcmp
(
name
,
XATTR_NAME_SMACKMMAP
)
==
0
)
{
if
(
!
capable
(
CAP_MAC_ADMIN
))
rc
=
-
EPERM
;
/*
...
...
@@ -773,6 +818,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
isp
->
smk_task
=
nsp
;
else
isp
->
smk_task
=
smack_known_invalid
.
smk_known
;
}
else
if
(
strcmp
(
name
,
XATTR_NAME_SMACKMMAP
)
==
0
)
{
nsp
=
smk_import
(
value
,
size
);
if
(
nsp
!=
NULL
)
isp
->
smk_mmap
=
nsp
;
else
isp
->
smk_mmap
=
smack_known_invalid
.
smk_known
;
}
else
if
(
strcmp
(
name
,
XATTR_NAME_SMACKTRANSMUTE
)
==
0
)
isp
->
smk_flags
|=
SMK_INODE_TRANSMUTE
;
...
...
@@ -815,7 +866,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
strcmp
(
name
,
XATTR_NAME_SMACKIPIN
)
==
0
||
strcmp
(
name
,
XATTR_NAME_SMACKIPOUT
)
==
0
||
strcmp
(
name
,
XATTR_NAME_SMACKEXEC
)
==
0
||
strcmp
(
name
,
XATTR_NAME_SMACKTRANSMUTE
)
==
0
)
{
strcmp
(
name
,
XATTR_NAME_SMACKTRANSMUTE
)
==
0
||
strcmp
(
name
,
XATTR_NAME_SMACKMMAP
))
{
if
(
!
capable
(
CAP_MAC_ADMIN
))
rc
=
-
EPERM
;
}
else
...
...
@@ -829,6 +881,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
if
(
rc
==
0
)
{
isp
=
dentry
->
d_inode
->
i_security
;
isp
->
smk_task
=
NULL
;
isp
->
smk_mmap
=
NULL
;
}
return
rc
;
...
...
@@ -1059,6 +1112,126 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
return
rc
;
}
/**
* smack_file_mmap :
* Check permissions for a mmap operation. The @file may be NULL, e.g.
* if mapping anonymous memory.
* @file contains the file structure for file to map (may be NULL).
* @reqprot contains the protection requested by the application.
* @prot contains the protection that will be applied by the kernel.
* @flags contains the operational flags.
* Return 0 if permission is granted.
*/
static
int
smack_file_mmap
(
struct
file
*
file
,
unsigned
long
reqprot
,
unsigned
long
prot
,
unsigned
long
flags
,
unsigned
long
addr
,
unsigned
long
addr_only
)
{
struct
smack_rule
*
srp
;
struct
task_smack
*
tsp
;
char
*
sp
;
char
*
msmack
;
char
*
osmack
;
struct
inode_smack
*
isp
;
struct
dentry
*
dp
;
int
may
;
int
mmay
;
int
tmay
;
int
rc
;
/* do DAC check on address space usage */
rc
=
cap_file_mmap
(
file
,
reqprot
,
prot
,
flags
,
addr
,
addr_only
);
if
(
rc
||
addr_only
)
return
rc
;
if
(
file
==
NULL
||
file
->
f_dentry
==
NULL
)
return
0
;
dp
=
file
->
f_dentry
;
if
(
dp
->
d_inode
==
NULL
)
return
0
;
isp
=
dp
->
d_inode
->
i_security
;
if
(
isp
->
smk_mmap
==
NULL
)
return
0
;
msmack
=
isp
->
smk_mmap
;
tsp
=
current_security
();
sp
=
smk_of_current
();
rc
=
0
;
rcu_read_lock
();
/*
* For each Smack rule associated with the subject
* label verify that the SMACK64MMAP also has access
* to that rule's object label.
*
* Because neither of the labels comes
* from the networking code it is sufficient
* to compare pointers.
*/
list_for_each_entry_rcu
(
srp
,
&
smack_rule_list
,
list
)
{
if
(
srp
->
smk_subject
!=
sp
)
continue
;
osmack
=
srp
->
smk_object
;
/*
* Matching labels always allows access.
*/
if
(
msmack
==
osmack
)
continue
;
/*
* If there is a matching local rule take
* that into account as well.
*/
may
=
smk_access_entry
(
srp
->
smk_subject
,
osmack
,
&
tsp
->
smk_rules
);
if
(
may
==
-
ENOENT
)
may
=
srp
->
smk_access
;
else
may
&=
srp
->
smk_access
;
/*
* If may is zero the SMACK64MMAP subject can't
* possibly have less access.
*/
if
(
may
==
0
)
continue
;
/*
* Fetch the global list entry.
* If there isn't one a SMACK64MMAP subject
* can't have as much access as current.
*/
mmay
=
smk_access_entry
(
msmack
,
osmack
,
&
smack_rule_list
);
if
(
mmay
==
-
ENOENT
)
{
rc
=
-
EACCES
;
break
;
}
/*
* If there is a local entry it modifies the
* potential access, too.
*/
tmay
=
smk_access_entry
(
msmack
,
osmack
,
&
tsp
->
smk_rules
);
if
(
tmay
!=
-
ENOENT
)
mmay
&=
tmay
;
/*
* If there is any access available to current that is
* not available to a SMACK64MMAP subject
* deny access.
*/
if
((
may
|
mmay
)
!=
mmay
)
{
rc
=
-
EACCES
;
break
;
}
}
rcu_read_unlock
();
return
rc
;
}
/**
* smack_file_set_fowner - set the file security blob value
* @file: object in question
...
...
@@ -1095,6 +1268,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
* struct fown_struct is never outside the context of a struct file
*/
file
=
container_of
(
fown
,
struct
file
,
f_owner
);
/* we don't log here as rc can be overriden */
rc
=
smk_access
(
file
->
f_security
,
tsp
,
MAY_WRITE
,
NULL
);
if
(
rc
!=
0
&&
has_capability
(
tsk
,
CAP_MAC_OVERRIDE
))
...
...
@@ -1145,9 +1319,14 @@ static int smack_file_receive(struct file *file)
*/
static
int
smack_cred_alloc_blank
(
struct
cred
*
cred
,
gfp_t
gfp
)
{
cred
->
security
=
kzalloc
(
sizeof
(
struct
task_smack
),
gfp
);
if
(
cred
->
security
==
NULL
)
struct
task_smack
*
tsp
;
tsp
=
new_task_smack
(
NULL
,
NULL
,
gfp
);
if
(
tsp
==
NULL
)
return
-
ENOMEM
;
cred
->
security
=
tsp
;
return
0
;
}
...
...
@@ -1156,13 +1335,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
* smack_cred_free - "free" task-level security credentials
* @cred: the credentials in question
*
* Smack isn't using copies of blobs. Everyone
* points to an immutable list. The blobs never go away.
* There is no leak here.
*/
static
void
smack_cred_free
(
struct
cred
*
cred
)
{
kfree
(
cred
->
security
);
struct
task_smack
*
tsp
=
cred
->
security
;
struct
smack_rule
*
rp
;
struct
list_head
*
l
;
struct
list_head
*
n
;
if
(
tsp
==
NULL
)
return
;
cred
->
security
=
NULL
;
list_for_each_safe
(
l
,
n
,
&
tsp
->
smk_rules
)
{
rp
=
list_entry
(
l
,
struct
smack_rule
,
list
);
list_del
(
&
rp
->
list
);
kfree
(
rp
);
}
kfree
(
tsp
);
}
/**
...
...
@@ -1178,13 +1368,16 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
{
struct
task_smack
*
old_tsp
=
old
->
security
;
struct
task_smack
*
new_tsp
;
int
rc
;
new_tsp
=
kzalloc
(
sizeof
(
struct
task_smack
)
,
gfp
);
new_tsp
=
new_task_smack
(
old_tsp
->
smk_task
,
old_tsp
->
smk_task
,
gfp
);
if
(
new_tsp
==
NULL
)
return
-
ENOMEM
;
new_tsp
->
smk_task
=
old_tsp
->
smk_task
;
new_tsp
->
smk_forked
=
old_tsp
->
smk_task
;
rc
=
smk_copy_rules
(
&
new_tsp
->
smk_rules
,
&
old_tsp
->
smk_rules
,
gfp
);
if
(
rc
!=
0
)
return
rc
;
new
->
security
=
new_tsp
;
return
0
;
}
...
...
@@ -1203,6 +1396,11 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old)
new_tsp
->
smk_task
=
old_tsp
->
smk_task
;
new_tsp
->
smk_forked
=
old_tsp
->
smk_task
;
mutex_init
(
&
new_tsp
->
smk_rules_lock
);
INIT_LIST_HEAD
(
&
new_tsp
->
smk_rules
);
/* cbs copy rule list */
}
/**
...
...
@@ -2419,6 +2617,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
}
}
isp
->
smk_task
=
smk_fetch
(
XATTR_NAME_SMACKEXEC
,
inode
,
dp
);
isp
->
smk_mmap
=
smk_fetch
(
XATTR_NAME_SMACKMMAP
,
inode
,
dp
);
dput
(
dp
);
break
;
...
...
@@ -2478,6 +2677,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
static
int
smack_setprocattr
(
struct
task_struct
*
p
,
char
*
name
,
void
*
value
,
size_t
size
)
{
int
rc
;
struct
task_smack
*
tsp
;
struct
task_smack
*
oldtsp
;
struct
cred
*
new
;
...
...
@@ -2513,13 +2713,16 @@ static int smack_setprocattr(struct task_struct *p, char *name,
new
=
prepare_creds
();
if
(
new
==
NULL
)
return
-
ENOMEM
;
tsp
=
kzalloc
(
sizeof
(
struct
task_smack
),
GFP_KERNEL
);
tsp
=
new_task_smack
(
newsmack
,
oldtsp
->
smk_forked
,
GFP_KERNEL
);
if
(
tsp
==
NULL
)
{
kfree
(
new
);
return
-
ENOMEM
;
}
tsp
->
smk_task
=
newsmack
;
tsp
->
smk_forked
=
oldtsp
->
smk_forked
;
rc
=
smk_copy_rules
(
&
tsp
->
smk_rules
,
&
oldtsp
->
smk_rules
,
GFP_KERNEL
);
if
(
rc
!=
0
)
return
rc
;
new
->
security
=
tsp
;
commit_creds
(
new
);
return
size
;
...
...
@@ -3221,6 +3424,7 @@ struct security_operations smack_ops = {
.
file_ioctl
=
smack_file_ioctl
,
.
file_lock
=
smack_file_lock
,
.
file_fcntl
=
smack_file_fcntl
,
.
file_mmap
=
smack_file_mmap
,
.
file_set_fowner
=
smack_file_set_fowner
,
.
file_send_sigiotask
=
smack_file_send_sigiotask
,
.
file_receive
=
smack_file_receive
,
...
...
@@ -3334,23 +3538,20 @@ static __init int smack_init(void)
struct
cred
*
cred
;
struct
task_smack
*
tsp
;
tsp
=
kzalloc
(
sizeof
(
struct
task_smack
),
GFP_KERNEL
);
if
(
!
security_module_enable
(
&
smack_ops
))
return
0
;
tsp
=
new_task_smack
(
smack_known_floor
.
smk_known
,
smack_known_floor
.
smk_known
,
GFP_KERNEL
);
if
(
tsp
==
NULL
)
return
-
ENOMEM
;
if
(
!
security_module_enable
(
&
smack_ops
))
{
kfree
(
tsp
);
return
0
;
}
printk
(
KERN_INFO
"Smack: Initializing.
\n
"
);
/*
* Set the security state for the initial task.
*/
cred
=
(
struct
cred
*
)
current
->
cred
;
tsp
->
smk_forked
=
smack_known_floor
.
smk_known
;
tsp
->
smk_task
=
smack_known_floor
.
smk_known
;
cred
->
security
=
tsp
;
/* initialize the smack_know_list */
...
...
security/smack/smackfs.c
浏览文件 @
a002951c
...
...
@@ -43,6 +43,7 @@ enum smk_inos {
SMK_NETLBLADDR
=
8
,
/* single label hosts */
SMK_ONLYCAP
=
9
,
/* the only "capable" label */
SMK_LOGGING
=
10
,
/* logging */
SMK_LOAD_SELF
=
11
,
/* task specific rules */
};
/*
...
...
@@ -135,104 +136,30 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
#define SMK_NETLBLADDRMIN 9
#define SMK_NETLBLADDRMAX 42
/*
* Seq_file read operations for /smack/load
*/
static
void
*
load_seq_start
(
struct
seq_file
*
s
,
loff_t
*
pos
)
{
if
(
*
pos
==
SEQ_READ_FINISHED
)
return
NULL
;
if
(
list_empty
(
&
smack_rule_list
))
return
NULL
;
return
smack_rule_list
.
next
;
}
static
void
*
load_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
)
{
struct
list_head
*
list
=
v
;
if
(
list_is_last
(
list
,
&
smack_rule_list
))
{
*
pos
=
SEQ_READ_FINISHED
;
return
NULL
;
}
return
list
->
next
;
}
static
int
load_seq_show
(
struct
seq_file
*
s
,
void
*
v
)
{
struct
list_head
*
list
=
v
;
struct
smack_rule
*
srp
=
list_entry
(
list
,
struct
smack_rule
,
list
);
seq_printf
(
s
,
"%s %s"
,
(
char
*
)
srp
->
smk_subject
,
(
char
*
)
srp
->
smk_object
);
seq_putc
(
s
,
' '
);
if
(
srp
->
smk_access
&
MAY_READ
)
seq_putc
(
s
,
'r'
);
if
(
srp
->
smk_access
&
MAY_WRITE
)
seq_putc
(
s
,
'w'
);
if
(
srp
->
smk_access
&
MAY_EXEC
)
seq_putc
(
s
,
'x'
);
if
(
srp
->
smk_access
&
MAY_APPEND
)
seq_putc
(
s
,
'a'
);
if
(
srp
->
smk_access
&
MAY_TRANSMUTE
)
seq_putc
(
s
,
't'
);
if
(
srp
->
smk_access
==
0
)
seq_putc
(
s
,
'-'
);
seq_putc
(
s
,
'\n'
);
return
0
;
}
static
void
load_seq_stop
(
struct
seq_file
*
s
,
void
*
v
)
{
/* No-op */
}
static
const
struct
seq_operations
load_seq_ops
=
{
.
start
=
load_seq_start
,
.
next
=
load_seq_next
,
.
show
=
load_seq_show
,
.
stop
=
load_seq_stop
,
};
/**
* smk_open_load - open() for /smack/load
* @inode: inode structure representing file
* @file: "load" file pointer
*
* For reading, use load_seq_* seq_file reading operations.
*/
static
int
smk_open_load
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
load_seq_ops
);
}
/**
* smk_set_access - add a rule to the rule list
* @srp: the new rule to add
* @rule_list: the list of rules
* @rule_lock: the rule list lock
*
* Looks through the current subject/object/access list for
* the subject/object pair and replaces the access that was
* there. If the pair isn't found add it with the specified
* access.
*
* Returns 1 if a rule was found to exist already, 0 if it is new
* Returns 0 if nothing goes wrong or -ENOMEM if it fails
* during the allocation of the new pair to add.
*/
static
int
smk_set_access
(
struct
smack_rule
*
srp
)
static
int
smk_set_access
(
struct
smack_rule
*
srp
,
struct
list_head
*
rule_list
,
struct
mutex
*
rule_lock
)
{
struct
smack_rule
*
sp
;
int
ret
=
0
;
int
found
;
mutex_lock
(
&
smack_list_lock
);
int
found
=
0
;
found
=
0
;
list_for_each_entry_rcu
(
sp
,
&
smack_rule_list
,
list
)
{
mutex_lock
(
rule_lock
);
list_for_each_entry_rcu
(
sp
,
rule_list
,
list
)
{
if
(
sp
->
smk_subject
==
srp
->
smk_subject
&&
sp
->
smk_object
==
srp
->
smk_object
)
{
found
=
1
;
...
...
@@ -241,19 +168,21 @@ static int smk_set_access(struct smack_rule *srp)
}
}
if
(
found
==
0
)
list_add_rcu
(
&
srp
->
list
,
&
smack_
rule_list
);
list_add_rcu
(
&
srp
->
list
,
rule_list
);
mutex_unlock
(
&
smack_list
_lock
);
mutex_unlock
(
rule
_lock
);
return
ret
;
return
found
;
}
/**
* smk_write_load
- write() for
/smack/load
* smk_write_load
_list - write() for any
/smack/load
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start - must be 0
* @rule_list: the list of rules to write to
* @rule_lock: lock for the rule list
*
* Get one smack access rule from above.
* The format is exactly:
...
...
@@ -263,21 +192,19 @@ static int smk_set_access(struct smack_rule *srp)
*
* writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
*/
static
ssize_t
smk_write_load
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
smk_write_load_list
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
,
struct
list_head
*
rule_list
,
struct
mutex
*
rule_lock
)
{
struct
smack_rule
*
rule
;
char
*
data
;
int
rc
=
-
EINVAL
;
/*
* Must have privilege.
* No partial writes.
* Enough data must be present.
*/
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
if
(
*
ppos
!=
0
)
return
-
EINVAL
;
/*
...
...
@@ -372,11 +299,13 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
goto
out_free_rule
;
}
rc
=
smk_set_access
(
rule
);
if
(
!
rc
)
rc
=
count
;
goto
out
;
rc
=
count
;
/*
* smk_set_access returns true if there was already a rule
* for the subject/object pair, and false if it was new.
*/
if
(
!
smk_set_access
(
rule
,
rule_list
,
rule_lock
))
goto
out
;
out_free_rule:
kfree
(
rule
);
...
...
@@ -385,6 +314,108 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
return
rc
;
}
/*
* Seq_file read operations for /smack/load
*/
static
void
*
load_seq_start
(
struct
seq_file
*
s
,
loff_t
*
pos
)
{
if
(
*
pos
==
SEQ_READ_FINISHED
)
return
NULL
;
if
(
list_empty
(
&
smack_rule_list
))
return
NULL
;
return
smack_rule_list
.
next
;
}
static
void
*
load_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
)
{
struct
list_head
*
list
=
v
;
if
(
list_is_last
(
list
,
&
smack_rule_list
))
{
*
pos
=
SEQ_READ_FINISHED
;
return
NULL
;
}
return
list
->
next
;
}
static
int
load_seq_show
(
struct
seq_file
*
s
,
void
*
v
)
{
struct
list_head
*
list
=
v
;
struct
smack_rule
*
srp
=
list_entry
(
list
,
struct
smack_rule
,
list
);
seq_printf
(
s
,
"%s %s"
,
(
char
*
)
srp
->
smk_subject
,
(
char
*
)
srp
->
smk_object
);
seq_putc
(
s
,
' '
);
if
(
srp
->
smk_access
&
MAY_READ
)
seq_putc
(
s
,
'r'
);
if
(
srp
->
smk_access
&
MAY_WRITE
)
seq_putc
(
s
,
'w'
);
if
(
srp
->
smk_access
&
MAY_EXEC
)
seq_putc
(
s
,
'x'
);
if
(
srp
->
smk_access
&
MAY_APPEND
)
seq_putc
(
s
,
'a'
);
if
(
srp
->
smk_access
&
MAY_TRANSMUTE
)
seq_putc
(
s
,
't'
);
if
(
srp
->
smk_access
==
0
)
seq_putc
(
s
,
'-'
);
seq_putc
(
s
,
'\n'
);
return
0
;
}
static
void
load_seq_stop
(
struct
seq_file
*
s
,
void
*
v
)
{
/* No-op */
}
static
const
struct
seq_operations
load_seq_ops
=
{
.
start
=
load_seq_start
,
.
next
=
load_seq_next
,
.
show
=
load_seq_show
,
.
stop
=
load_seq_stop
,
};
/**
* smk_open_load - open() for /smack/load
* @inode: inode structure representing file
* @file: "load" file pointer
*
* For reading, use load_seq_* seq_file reading operations.
*/
static
int
smk_open_load
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
load_seq_ops
);
}
/**
* smk_write_load - write() for /smack/load
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start - must be 0
*
*/
static
ssize_t
smk_write_load
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
/*
* Must have privilege.
* No partial writes.
* Enough data must be present.
*/
if
(
!
capable
(
CAP_MAC_ADMIN
))
return
-
EPERM
;
return
smk_write_load_list
(
file
,
buf
,
count
,
ppos
,
&
smack_rule_list
,
&
smack_list_lock
);
}
static
const
struct
file_operations
smk_load_ops
=
{
.
open
=
smk_open_load
,
.
read
=
seq_read
,
...
...
@@ -1288,6 +1319,112 @@ static const struct file_operations smk_logging_ops = {
.
write
=
smk_write_logging
,
.
llseek
=
default_llseek
,
};
/*
* Seq_file read operations for /smack/load-self
*/
static
void
*
load_self_seq_start
(
struct
seq_file
*
s
,
loff_t
*
pos
)
{
struct
task_smack
*
tsp
=
current_security
();
if
(
*
pos
==
SEQ_READ_FINISHED
)
return
NULL
;
if
(
list_empty
(
&
tsp
->
smk_rules
))
return
NULL
;
return
tsp
->
smk_rules
.
next
;
}
static
void
*
load_self_seq_next
(
struct
seq_file
*
s
,
void
*
v
,
loff_t
*
pos
)
{
struct
task_smack
*
tsp
=
current_security
();
struct
list_head
*
list
=
v
;
if
(
list_is_last
(
list
,
&
tsp
->
smk_rules
))
{
*
pos
=
SEQ_READ_FINISHED
;
return
NULL
;
}
return
list
->
next
;
}
static
int
load_self_seq_show
(
struct
seq_file
*
s
,
void
*
v
)
{
struct
list_head
*
list
=
v
;
struct
smack_rule
*
srp
=
list_entry
(
list
,
struct
smack_rule
,
list
);
seq_printf
(
s
,
"%s %s"
,
(
char
*
)
srp
->
smk_subject
,
(
char
*
)
srp
->
smk_object
);
seq_putc
(
s
,
' '
);
if
(
srp
->
smk_access
&
MAY_READ
)
seq_putc
(
s
,
'r'
);
if
(
srp
->
smk_access
&
MAY_WRITE
)
seq_putc
(
s
,
'w'
);
if
(
srp
->
smk_access
&
MAY_EXEC
)
seq_putc
(
s
,
'x'
);
if
(
srp
->
smk_access
&
MAY_APPEND
)
seq_putc
(
s
,
'a'
);
if
(
srp
->
smk_access
&
MAY_TRANSMUTE
)
seq_putc
(
s
,
't'
);
if
(
srp
->
smk_access
==
0
)
seq_putc
(
s
,
'-'
);
seq_putc
(
s
,
'\n'
);
return
0
;
}
static
void
load_self_seq_stop
(
struct
seq_file
*
s
,
void
*
v
)
{
/* No-op */
}
static
const
struct
seq_operations
load_self_seq_ops
=
{
.
start
=
load_self_seq_start
,
.
next
=
load_self_seq_next
,
.
show
=
load_self_seq_show
,
.
stop
=
load_self_seq_stop
,
};
/**
* smk_open_load_self - open() for /smack/load-self
* @inode: inode structure representing file
* @file: "load" file pointer
*
* For reading, use load_seq_* seq_file reading operations.
*/
static
int
smk_open_load_self
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
load_self_seq_ops
);
}
/**
* smk_write_load_self - write() for /smack/load-self
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start - must be 0
*
*/
static
ssize_t
smk_write_load_self
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
task_smack
*
tsp
=
current_security
();
return
smk_write_load_list
(
file
,
buf
,
count
,
ppos
,
&
tsp
->
smk_rules
,
&
tsp
->
smk_rules_lock
);
}
static
const
struct
file_operations
smk_load_self_ops
=
{
.
open
=
smk_open_load_self
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
write
=
smk_write_load_self
,
.
release
=
seq_release
,
};
/**
* smk_fill_super - fill the /smackfs superblock
* @sb: the empty superblock
...
...
@@ -1304,23 +1441,26 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
struct
inode
*
root_inode
;
static
struct
tree_descr
smack_files
[]
=
{
[
SMK_LOAD
]
=
{
"load"
,
&
smk_load_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_CIPSO
]
=
{
"cipso"
,
&
smk_cipso_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_DOI
]
=
{
"doi"
,
&
smk_doi_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_DIRECT
]
=
{
"direct"
,
&
smk_direct_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_AMBIENT
]
=
{
"ambient"
,
&
smk_ambient_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_NETLBLADDR
]
=
{
"netlabel"
,
&
smk_netlbladdr_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_ONLYCAP
]
=
{
"onlycap"
,
&
smk_onlycap_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_LOGGING
]
=
{
"logging"
,
&
smk_logging_ops
,
S_IRUGO
|
S_IWUSR
},
/* last one */
{
""
}
[
SMK_LOAD
]
=
{
"load"
,
&
smk_load_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_CIPSO
]
=
{
"cipso"
,
&
smk_cipso_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_DOI
]
=
{
"doi"
,
&
smk_doi_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_DIRECT
]
=
{
"direct"
,
&
smk_direct_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_AMBIENT
]
=
{
"ambient"
,
&
smk_ambient_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_NETLBLADDR
]
=
{
"netlabel"
,
&
smk_netlbladdr_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_ONLYCAP
]
=
{
"onlycap"
,
&
smk_onlycap_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_LOGGING
]
=
{
"logging"
,
&
smk_logging_ops
,
S_IRUGO
|
S_IWUSR
},
[
SMK_LOAD_SELF
]
=
{
"load-self"
,
&
smk_load_self_ops
,
S_IRUGO
|
S_IWUGO
},
/* last one */
{
""
}
};
rc
=
simple_fill_super
(
sb
,
SMACK_MAGIC
,
smack_files
);
...
...
security/tomoyo/file.c
浏览文件 @
a002951c
...
...
@@ -927,7 +927,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
struct
path
*
path
,
const
int
flag
)
{
const
u8
acc_mode
=
ACC_MODE
(
flag
);
int
error
=
-
ENOMEM
;
int
error
=
0
;
struct
tomoyo_path_info
buf
;
struct
tomoyo_request_info
r
;
int
idx
;
...
...
@@ -938,9 +938,6 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
buf
.
name
=
NULL
;
r
.
mode
=
TOMOYO_CONFIG_DISABLED
;
idx
=
tomoyo_read_lock
();
if
(
!
tomoyo_get_realpath
(
&
buf
,
path
))
goto
out
;
error
=
0
;
/*
* If the filename is specified by "deny_rewrite" keyword,
* we need to check "allow_rewrite" permission when the filename is not
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录