Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
ff2bb047
Commit
ff2bb047
authored
May 22, 2012
by
James Morris
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.infradead.org/users/eparis/selinux
into next
Per pull request, for 3.5.
parents
cffee16e
c737f828
Changes
33
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
422 additions
and
350 deletions
+422
-350
fs/open.c
fs/open.c
+1
-1
include/linux/lsm_audit.h
include/linux/lsm_audit.h
+0
-6
include/linux/security.h
include/linux/security.h
+5
-8
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_policy.c
+1
-0
security/apparmor/audit.c
security/apparmor/audit.c
+9
-2
security/apparmor/capability.c
security/apparmor/capability.c
+2
-2
security/apparmor/file.c
security/apparmor/file.c
+1
-1
security/apparmor/include/audit.h
security/apparmor/include/audit.h
+1
-0
security/apparmor/ipc.c
security/apparmor/ipc.c
+1
-1
security/apparmor/lib.c
security/apparmor/lib.c
+1
-1
security/apparmor/lsm.c
security/apparmor/lsm.c
+3
-3
security/apparmor/policy.c
security/apparmor/policy.c
+1
-1
security/apparmor/policy_unpack.c
security/apparmor/policy_unpack.c
+1
-1
security/apparmor/resource.c
security/apparmor/resource.c
+1
-1
security/capability.c
security/capability.c
+2
-2
security/lsm_audit.c
security/lsm_audit.c
+9
-6
security/security.c
security/security.c
+2
-2
security/selinux/avc.c
security/selinux/avc.c
+24
-106
security/selinux/hooks.c
security/selinux/hooks.c
+118
-140
security/selinux/include/avc.h
security/selinux/include/avc.h
+77
-23
security/selinux/include/security.h
security/selinux/include/security.h
+3
-1
security/selinux/netif.c
security/selinux/netif.c
+2
-4
security/selinux/netnode.c
security/selinux/netnode.c
+2
-4
security/selinux/netport.c
security/selinux/netport.c
+2
-4
security/selinux/selinuxfs.c
security/selinux/selinuxfs.c
+4
-7
security/selinux/ss/context.h
security/selinux/ss/context.h
+20
-0
security/selinux/ss/mls.c
security/selinux/ss/mls.c
+24
-0
security/selinux/ss/policydb.c
security/selinux/ss/policydb.c
+44
-0
security/selinux/ss/policydb.h
security/selinux/ss/policydb.h
+14
-0
security/selinux/ss/services.c
security/selinux/ss/services.c
+40
-16
security/smack/smack.h
security/smack/smack.h
+1
-1
security/smack/smack_lsm.c
security/smack/smack_lsm.c
+3
-3
security/tomoyo/tomoyo.c
security/tomoyo/tomoyo.c
+3
-3
No files found.
fs/open.c
View file @
ff2bb047
...
...
@@ -681,7 +681,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
f
->
f_op
=
fops_get
(
inode
->
i_fop
);
error
=
security_
dentry
_open
(
f
,
cred
);
error
=
security_
file
_open
(
f
,
cred
);
if
(
error
)
goto
cleanup_all
;
...
...
include/linux/lsm_audit.h
View file @
ff2bb047
...
...
@@ -53,7 +53,6 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_KMOD 8
#define LSM_AUDIT_DATA_INODE 9
#define LSM_AUDIT_DATA_DENTRY 10
struct
task_struct
*
tsk
;
union
{
struct
path
path
;
struct
dentry
*
dentry
;
...
...
@@ -93,11 +92,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
int
ipv6_skb_to_auditdata
(
struct
sk_buff
*
skb
,
struct
common_audit_data
*
ad
,
u8
*
proto
);
/* Initialize an LSM audit data structure. */
#define COMMON_AUDIT_DATA_INIT(_d, _t) \
{ memset((_d), 0, sizeof(struct common_audit_data)); \
(_d)->type = LSM_AUDIT_DATA_##_t; }
void
common_lsm_audit
(
struct
common_audit_data
*
a
,
void
(
*
pre_audit
)(
struct
audit_buffer
*
,
void
*
),
void
(
*
post_audit
)(
struct
audit_buffer
*
,
void
*
));
...
...
include/linux/security.h
View file @
ff2bb047
...
...
@@ -640,10 +640,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* to receive an open file descriptor via socket IPC.
* @file contains the file structure being received.
* Return 0 if permission is granted.
*
* Security hook for dentry
*
* @dentry_open
* @file_open
* Save open-time permission checking state for later use upon
* file_permission, and recheck access if anything has changed
* since inode_permission.
...
...
@@ -1498,7 +1495,7 @@ struct security_operations {
int
(
*
file_send_sigiotask
)
(
struct
task_struct
*
tsk
,
struct
fown_struct
*
fown
,
int
sig
);
int
(
*
file_receive
)
(
struct
file
*
file
);
int
(
*
dentry
_open
)
(
struct
file
*
file
,
const
struct
cred
*
cred
);
int
(
*
file
_open
)
(
struct
file
*
file
,
const
struct
cred
*
cred
);
int
(
*
task_create
)
(
unsigned
long
clone_flags
);
void
(
*
task_free
)
(
struct
task_struct
*
task
);
...
...
@@ -1757,7 +1754,7 @@ int security_file_set_fowner(struct file *file);
int
security_file_send_sigiotask
(
struct
task_struct
*
tsk
,
struct
fown_struct
*
fown
,
int
sig
);
int
security_file_receive
(
struct
file
*
file
);
int
security_
dentry
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
);
int
security_
file
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
);
int
security_task_create
(
unsigned
long
clone_flags
);
void
security_task_free
(
struct
task_struct
*
task
);
int
security_cred_alloc_blank
(
struct
cred
*
cred
,
gfp_t
gfp
);
...
...
@@ -2228,8 +2225,8 @@ static inline int security_file_receive(struct file *file)
return
0
;
}
static
inline
int
security_
dentry
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
static
inline
int
security_
file
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
{
return
0
;
}
...
...
net/xfrm/xfrm_policy.c
View file @
ff2bb047
...
...
@@ -26,6 +26,7 @@
#include <linux/cache.h>
#include <linux/audit.h>
#include <net/dst.h>
#include <net/flow.h>
#include <net/xfrm.h>
#include <net/ip.h>
#ifdef CONFIG_XFRM_STATISTICS
...
...
security/apparmor/audit.c
View file @
ff2bb047
...
...
@@ -111,7 +111,7 @@ static const char *const aa_audit_type[] = {
static
void
audit_pre
(
struct
audit_buffer
*
ab
,
void
*
ca
)
{
struct
common_audit_data
*
sa
=
ca
;
struct
task_struct
*
tsk
=
sa
->
tsk
?
sa
->
tsk
:
current
;
struct
task_struct
*
tsk
=
sa
->
aad
->
tsk
?
sa
->
aad
->
tsk
:
current
;
if
(
aa_g_audit_header
)
{
audit_log_format
(
ab
,
"apparmor="
);
...
...
@@ -149,6 +149,12 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
audit_log_format
(
ab
,
" name="
);
audit_log_untrustedstring
(
ab
,
sa
->
aad
->
name
);
}
if
(
sa
->
aad
->
tsk
)
{
audit_log_format
(
ab
,
" pid=%d comm="
,
tsk
->
pid
);
audit_log_untrustedstring
(
ab
,
tsk
->
comm
);
}
}
/**
...
...
@@ -205,7 +211,8 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
aa_audit_msg
(
type
,
sa
,
cb
);
if
(
sa
->
aad
->
type
==
AUDIT_APPARMOR_KILL
)
(
void
)
send_sig_info
(
SIGKILL
,
NULL
,
sa
->
tsk
?
sa
->
tsk
:
current
);
(
void
)
send_sig_info
(
SIGKILL
,
NULL
,
sa
->
aad
->
tsk
?
sa
->
aad
->
tsk
:
current
);
if
(
sa
->
aad
->
type
==
AUDIT_APPARMOR_ALLOWED
)
return
complain_error
(
sa
->
aad
->
error
);
...
...
security/apparmor/capability.c
View file @
ff2bb047
...
...
@@ -65,10 +65,10 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task,
int
type
=
AUDIT_APPARMOR_AUTO
;
struct
common_audit_data
sa
;
struct
apparmor_audit_data
aad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
sa
,
CAP
)
;
sa
.
type
=
LSM_AUDIT_DATA_CAP
;
sa
.
aad
=
&
aad
;
sa
.
tsk
=
task
;
sa
.
u
.
cap
=
cap
;
sa
.
aad
->
tsk
=
task
;
sa
.
aad
->
op
=
OP_CAPABLE
;
sa
.
aad
->
error
=
error
;
...
...
security/apparmor/file.c
View file @
ff2bb047
...
...
@@ -108,7 +108,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
int
type
=
AUDIT_APPARMOR_AUTO
;
struct
common_audit_data
sa
;
struct
apparmor_audit_data
aad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
sa
,
NONE
)
;
sa
.
type
=
LSM_AUDIT_DATA_NONE
;
sa
.
aad
=
&
aad
;
aad
.
op
=
op
,
aad
.
fs
.
request
=
request
;
...
...
security/apparmor/include/audit.h
View file @
ff2bb047
...
...
@@ -110,6 +110,7 @@ struct apparmor_audit_data {
void
*
profile
;
const
char
*
name
;
const
char
*
info
;
struct
task_struct
*
tsk
;
union
{
void
*
target
;
struct
{
...
...
security/apparmor/ipc.c
View file @
ff2bb047
...
...
@@ -42,7 +42,7 @@ static int aa_audit_ptrace(struct aa_profile *profile,
{
struct
common_audit_data
sa
;
struct
apparmor_audit_data
aad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
sa
,
NONE
)
;
sa
.
type
=
LSM_AUDIT_DATA_NONE
;
sa
.
aad
=
&
aad
;
aad
.
op
=
OP_PTRACE
;
aad
.
target
=
target
;
...
...
security/apparmor/lib.c
View file @
ff2bb047
...
...
@@ -66,7 +66,7 @@ void aa_info_message(const char *str)
if
(
audit_enabled
)
{
struct
common_audit_data
sa
;
struct
apparmor_audit_data
aad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
sa
,
NONE
)
;
sa
.
type
=
LSM_AUDIT_DATA_NONE
;
sa
.
aad
=
&
aad
;
aad
.
info
=
str
;
aa_audit_msg
(
AUDIT_APPARMOR_STATUS
,
&
sa
,
NULL
);
...
...
security/apparmor/lsm.c
View file @
ff2bb047
...
...
@@ -373,7 +373,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
AA_MAY_META_READ
);
}
static
int
apparmor_
dentry
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
static
int
apparmor_
file
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
{
struct
aa_file_cxt
*
fcxt
=
file
->
f_security
;
struct
aa_profile
*
profile
;
...
...
@@ -589,7 +589,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
}
else
{
struct
common_audit_data
sa
;
struct
apparmor_audit_data
aad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
sa
,
NONE
)
;
sa
.
type
=
LSM_AUDIT_DATA_NONE
;
sa
.
aad
=
&
aad
;
aad
.
op
=
OP_SETPROCATTR
;
aad
.
info
=
name
;
...
...
@@ -640,9 +640,9 @@ static struct security_operations apparmor_ops = {
.
path_chmod
=
apparmor_path_chmod
,
.
path_chown
=
apparmor_path_chown
,
.
path_truncate
=
apparmor_path_truncate
,
.
dentry_open
=
apparmor_dentry_open
,
.
inode_getattr
=
apparmor_inode_getattr
,
.
file_open
=
apparmor_file_open
,
.
file_permission
=
apparmor_file_permission
,
.
file_alloc_security
=
apparmor_file_alloc_security
,
.
file_free_security
=
apparmor_file_free_security
,
...
...
security/apparmor/policy.c
View file @
ff2bb047
...
...
@@ -969,7 +969,7 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
{
struct
common_audit_data
sa
;
struct
apparmor_audit_data
aad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
sa
,
NONE
)
;
sa
.
type
=
LSM_AUDIT_DATA_NONE
;
sa
.
aad
=
&
aad
;
aad
.
op
=
op
;
aad
.
name
=
name
;
...
...
security/apparmor/policy_unpack.c
View file @
ff2bb047
...
...
@@ -95,7 +95,7 @@ static int audit_iface(struct aa_profile *new, const char *name,
struct
aa_profile
*
profile
=
__aa_current_profile
();
struct
common_audit_data
sa
;
struct
apparmor_audit_data
aad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
sa
,
NONE
)
;
sa
.
type
=
LSM_AUDIT_DATA_NONE
;
sa
.
aad
=
&
aad
;
if
(
e
)
aad
.
iface
.
pos
=
e
->
pos
-
e
->
start
;
...
...
security/apparmor/resource.c
View file @
ff2bb047
...
...
@@ -52,7 +52,7 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource,
struct
common_audit_data
sa
;
struct
apparmor_audit_data
aad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
sa
,
NONE
)
;
sa
.
type
=
LSM_AUDIT_DATA_NONE
;
sa
.
aad
=
&
aad
;
aad
.
op
=
OP_SETRLIMIT
,
aad
.
rlim
.
rlim
=
resource
;
...
...
security/capability.c
View file @
ff2bb047
...
...
@@ -348,7 +348,7 @@ static int cap_file_receive(struct file *file)
return
0
;
}
static
int
cap_
dentry
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
static
int
cap_
file
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
{
return
0
;
}
...
...
@@ -956,7 +956,7 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null
(
ops
,
file_set_fowner
);
set_to_cap_if_null
(
ops
,
file_send_sigiotask
);
set_to_cap_if_null
(
ops
,
file_receive
);
set_to_cap_if_null
(
ops
,
dentry
_open
);
set_to_cap_if_null
(
ops
,
file
_open
);
set_to_cap_if_null
(
ops
,
task_create
);
set_to_cap_if_null
(
ops
,
task_free
);
set_to_cap_if_null
(
ops
,
cred_alloc_blank
);
...
...
security/lsm_audit.c
View file @
ff2bb047
...
...
@@ -213,12 +213,15 @@ static void dump_common_audit_data(struct audit_buffer *ab,
{
struct
task_struct
*
tsk
=
current
;
if
(
a
->
tsk
)
tsk
=
a
->
tsk
;
if
(
tsk
&&
tsk
->
pid
)
{
audit_log_format
(
ab
,
" pid=%d comm="
,
tsk
->
pid
);
audit_log_untrustedstring
(
ab
,
tsk
->
comm
);
}
/*
* To keep stack sizes in check force programers to notice if they
* start making this union too large! See struct lsm_network_audit
* as an example of how to deal with large data.
*/
BUILD_BUG_ON
(
sizeof
(
a
->
u
)
>
sizeof
(
void
*
)
*
2
);
audit_log_format
(
ab
,
" pid=%d comm="
,
tsk
->
pid
);
audit_log_untrustedstring
(
ab
,
tsk
->
comm
);
switch
(
a
->
type
)
{
case
LSM_AUDIT_DATA_NONE
:
...
...
security/security.c
View file @
ff2bb047
...
...
@@ -701,11 +701,11 @@ int security_file_receive(struct file *file)
return
security_ops
->
file_receive
(
file
);
}
int
security_
dentry
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
int
security_
file
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
{
int
ret
;
ret
=
security_ops
->
dentry
_open
(
file
,
cred
);
ret
=
security_ops
->
file
_open
(
file
,
cred
);
if
(
ret
)
return
ret
;
...
...
security/selinux/avc.c
View file @
ff2bb047
...
...
@@ -65,14 +65,8 @@ struct avc_cache {
};
struct
avc_callback_node
{
int
(
*
callback
)
(
u32
event
,
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
perms
,
u32
*
out_retained
);
int
(
*
callback
)
(
u32
event
);
u32
events
;
u32
ssid
;
u32
tsid
;
u16
tclass
;
u32
perms
;
struct
avc_callback_node
*
next
;
};
...
...
@@ -436,9 +430,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
{
struct
common_audit_data
*
ad
=
a
;
audit_log_format
(
ab
,
"avc: %s "
,
ad
->
selinux_audit_data
->
slad
->
denied
?
"denied"
:
"granted"
);
avc_dump_av
(
ab
,
ad
->
selinux_audit_data
->
slad
->
tclass
,
ad
->
selinux_audit_data
->
slad
->
audited
);
ad
->
selinux_audit_data
->
denied
?
"denied"
:
"granted"
);
avc_dump_av
(
ab
,
ad
->
selinux_audit_data
->
tclass
,
ad
->
selinux_audit_data
->
audited
);
audit_log_format
(
ab
,
" for "
);
}
...
...
@@ -452,25 +446,23 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
{
struct
common_audit_data
*
ad
=
a
;
audit_log_format
(
ab
,
" "
);
avc_dump_query
(
ab
,
ad
->
selinux_audit_data
->
s
lad
->
s
sid
,
ad
->
selinux_audit_data
->
slad
->
tsid
,
ad
->
selinux_audit_data
->
slad
->
tclass
);
avc_dump_query
(
ab
,
ad
->
selinux_audit_data
->
ssid
,
ad
->
selinux_audit_data
->
tsid
,
ad
->
selinux_audit_data
->
tclass
);
}
/* This is the slow part of avc audit with big stack footprint */
static
noinline
int
slow_avc_audit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
noinline
int
slow_avc_audit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
u32
audited
,
u32
denied
,
struct
common_audit_data
*
a
,
unsigned
flags
)
{
struct
common_audit_data
stack_data
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
selinux_late_audit_data
slad
;
struct
selinux_audit_data
sad
;
if
(
!
a
)
{
a
=
&
stack_data
;
COMMON_AUDIT_DATA_INIT
(
a
,
NONE
);
a
->
selinux_audit_data
=
&
sad
;
a
->
type
=
LSM_AUDIT_DATA_NONE
;
}
/*
...
...
@@ -484,104 +476,34 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
(
flags
&
MAY_NOT_BLOCK
))
return
-
ECHILD
;
slad
.
tclass
=
tclass
;
slad
.
requested
=
requested
;
slad
.
ssid
=
ssid
;
slad
.
tsid
=
tsid
;
slad
.
audited
=
audited
;
slad
.
denied
=
denied
;
sad
.
tclass
=
tclass
;
sad
.
requested
=
requested
;
sad
.
ssid
=
ssid
;
sad
.
tsid
=
tsid
;
sad
.
audited
=
audited
;
sad
.
denied
=
denied
;
a
->
selinux_audit_data
=
&
sad
;
a
->
selinux_audit_data
->
slad
=
&
slad
;
common_lsm_audit
(
a
,
avc_audit_pre_callback
,
avc_audit_post_callback
);
return
0
;
}
/**
* avc_audit - Audit the granting or denial of permissions.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions
* @avd: access vector decisions
* @result: result from avc_has_perm_noaudit
* @a: auxiliary audit data
* @flags: VFS walk flags
*
* Audit the granting or denial of permissions in accordance
* with the policy. This function is typically called by
* avc_has_perm() after a permission check, but can also be
* called directly by callers who use avc_has_perm_noaudit()
* in order to separate the permission check from the auditing.
* For example, this separation is useful when the permission check must
* be performed under a lock, to allow the lock to be released
* before calling the auditing code.
*/
inline
int
avc_audit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
struct
av_decision
*
avd
,
int
result
,
struct
common_audit_data
*
a
,
unsigned
flags
)
{
u32
denied
,
audited
;
denied
=
requested
&
~
avd
->
allowed
;
if
(
unlikely
(
denied
))
{
audited
=
denied
&
avd
->
auditdeny
;
/*
* a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in
* this field means that ANY denials should NOT be audited if
* the policy contains an explicit dontaudit rule for that
* permission. Take notice that this is unrelated to the
* actual permissions that were denied. As an example lets
* assume:
*
* denied == READ
* avd.auditdeny & ACCESS == 0 (not set means explicit rule)
* selinux_audit_data->auditdeny & ACCESS == 1
*
* We will NOT audit the denial even though the denied
* permission was READ and the auditdeny checks were for
* ACCESS
*/
if
(
a
&&
a
->
selinux_audit_data
->
auditdeny
&&
!
(
a
->
selinux_audit_data
->
auditdeny
&
avd
->
auditdeny
))
audited
=
0
;
}
else
if
(
result
)
audited
=
denied
=
requested
;
else
audited
=
requested
&
avd
->
auditallow
;
if
(
likely
(
!
audited
))
return
0
;
return
slow_avc_audit
(
ssid
,
tsid
,
tclass
,
requested
,
audited
,
denied
,
a
,
flags
);
}
/**
* avc_add_callback - Register a callback for security events.
* @callback: callback function
* @events: security events
* @ssid: source security identifier or %SECSID_WILD
* @tsid: target security identifier or %SECSID_WILD
* @tclass: target security class
* @perms: permissions
*
* Register a callback function for events in the set @events
* related to the SID pair (@ssid, @tsid)
* and the permissions @perms, interpreting
* @perms based on @tclass. Returns %0 on success or
* -%ENOMEM if insufficient memory exists to add the callback.
* Register a callback function for events in the set @events.
* Returns %0 on success or -%ENOMEM if insufficient memory
* exists to add the callback.
*/
int
avc_add_callback
(
int
(
*
callback
)(
u32
event
,
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
perms
,
u32
*
out_retained
),
u32
events
,
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
perms
)
int
__init
avc_add_callback
(
int
(
*
callback
)(
u32
event
),
u32
events
)
{
struct
avc_callback_node
*
c
;
int
rc
=
0
;
c
=
kmalloc
(
sizeof
(
*
c
),
GFP_
ATOMIC
);
c
=
kmalloc
(
sizeof
(
*
c
),
GFP_
KERNEL
);
if
(
!
c
)
{
rc
=
-
ENOMEM
;
goto
out
;
...
...
@@ -589,9 +511,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
c
->
callback
=
callback
;
c
->
events
=
events
;
c
->
ssid
=
ssid
;
c
->
tsid
=
tsid
;
c
->
perms
=
perms
;
c
->
next
=
avc_callbacks
;
avc_callbacks
=
c
;
out:
...
...
@@ -731,8 +650,7 @@ int avc_ss_reset(u32 seqno)
for
(
c
=
avc_callbacks
;
c
;
c
=
c
->
next
)
{
if
(
c
->
events
&
AVC_CALLBACK_RESET
)
{
tmprc
=
c
->
callback
(
AVC_CALLBACK_RESET
,
0
,
0
,
0
,
0
,
NULL
);
tmprc
=
c
->
callback
(
AVC_CALLBACK_RESET
);
/* save the first error encountered for the return
value and continue processing the callbacks */
if
(
!
rc
)
...
...
security/selinux/hooks.c
View file @
ff2bb047
...
...
@@ -1420,16 +1420,13 @@ static int cred_has_capability(const struct cred *cred,
int
cap
,
int
audit
)
{
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
av_decision
avd
;
u16
sclass
;
u32
sid
=
cred_sid
(
cred
);
u32
av
=
CAP_TO_MASK
(
cap
);
int
rc
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
CAP
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
tsk
=
current
;
ad
.
type
=
LSM_AUDIT_DATA_CAP
;
ad
.
u
.
cap
=
cap
;
switch
(
CAP_TO_INDEX
(
cap
))
{
...
...
@@ -1488,20 +1485,6 @@ static int inode_has_perm(const struct cred *cred,
return
avc_has_perm_flags
(
sid
,
isec
->
sid
,
isec
->
sclass
,
perms
,
adp
,
flags
);
}
static
int
inode_has_perm_noadp
(
const
struct
cred
*
cred
,
struct
inode
*
inode
,
u32
perms
,
unsigned
flags
)
{
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
ad
,
INODE
);
ad
.
u
.
inode
=
inode
;
ad
.
selinux_audit_data
=
&
sad
;
return
inode_has_perm
(
cred
,
inode
,
perms
,
&
ad
,
flags
);
}
/* Same as inode_has_perm, but pass explicit audit data containing
the dentry to help the auditing code to more easily generate the
pathname if needed. */
...
...
@@ -1511,11 +1494,9 @@ static inline int dentry_has_perm(const struct cred *cred,
{
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
ad
,
DENTRY
)
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
dentry
;
ad
.
selinux_audit_data
=
&
sad
;
return
inode_has_perm
(
cred
,
inode
,
av
,
&
ad
,
0
);
}
...
...
@@ -1528,11 +1509,9 @@ static inline int path_has_perm(const struct cred *cred,
{
struct
inode
*
inode
=
path
->
dentry
->
d_inode
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
ad
,
PATH
)
;
ad
.
type
=
LSM_AUDIT_DATA_PATH
;
ad
.
u
.
path
=
*
path
;
ad
.
selinux_audit_data
=
&
sad
;
return
inode_has_perm
(
cred
,
inode
,
av
,
&
ad
,
0
);
}
...
...
@@ -1551,13 +1530,11 @@ static int file_has_perm(const struct cred *cred,
struct
file_security_struct
*
fsec
=
file
->
f_security
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
cred_sid
(
cred
);
int
rc
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
PATH
)
;
ad
.
type
=
LSM_AUDIT_DATA_PATH
;
ad
.
u
.
path
=
file
->
f_path
;
ad
.
selinux_audit_data
=
&
sad
;
if
(
sid
!=
fsec
->
sid
)
{
rc
=
avc_has_perm
(
sid
,
fsec
->
sid
,
...
...
@@ -1587,7 +1564,6 @@ static int may_create(struct inode *dir,
struct
superblock_security_struct
*
sbsec
;
u32
sid
,
newsid
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
int
rc
;
dsec
=
dir
->
i_security
;
...
...
@@ -1596,9 +1572,8 @@ static int may_create(struct inode *dir,
sid
=
tsec
->
sid
;
newsid
=
tsec
->
create_sid
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
DENTRY
)
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
dentry
;
ad
.
selinux_audit_data
=
&
sad
;
rc
=
avc_has_perm
(
sid
,
dsec
->
sid
,
SECCLASS_DIR
,
DIR__ADD_NAME
|
DIR__SEARCH
,
...
...
@@ -1643,7 +1618,6 @@ static int may_link(struct inode *dir,
{
struct
inode_security_struct
*
dsec
,
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
u32
av
;
int
rc
;
...
...
@@ -1651,9 +1625,8 @@ static int may_link(struct inode *dir,
dsec
=
dir
->
i_security
;
isec
=
dentry
->
d_inode
->
i_security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
DENTRY
)
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
dentry
;
ad
.
selinux_audit_data
=
&
sad
;
av
=
DIR__SEARCH
;
av
|=
(
kind
?
DIR__REMOVE_NAME
:
DIR__ADD_NAME
);
...
...
@@ -1688,7 +1661,6 @@ static inline int may_rename(struct inode *old_dir,
{
struct
inode_security_struct
*
old_dsec
,
*
new_dsec
,
*
old_isec
,
*
new_isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
u32
av
;
int
old_is_dir
,
new_is_dir
;
...
...
@@ -1699,8 +1671,7 @@ static inline int may_rename(struct inode *old_dir,
old_is_dir
=
S_ISDIR
(
old_dentry
->
d_inode
->
i_mode
);
new_dsec
=
new_dir
->
i_security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
DENTRY
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
old_dentry
;
rc
=
avc_has_perm
(
sid
,
old_dsec
->
sid
,
SECCLASS_DIR
,
...
...
@@ -1986,7 +1957,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
struct
task_security_struct
*
new_tsec
;
struct
inode_security_struct
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
inode
*
inode
=
bprm
->
file
->
f_path
.
dentry
->
d_inode
;
int
rc
;
...
...
@@ -2032,8 +2002,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
return
rc
;
}
COMMON_AUDIT_DATA_INIT
(
&
ad
,
PATH
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_PATH
;
ad
.
u
.
path
=
bprm
->
file
->
f_path
;
if
((
bprm
->
file
->
f_path
.
mnt
->
mnt_flags
&
MNT_NOSUID
)
||
...
...
@@ -2123,8 +2092,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
static
inline
void
flush_unauthorized_files
(
const
struct
cred
*
cred
,
struct
files_struct
*
files
)
{
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
file
*
file
,
*
devnull
=
NULL
;
struct
tty_struct
*
tty
;
struct
fdtable
*
fdt
;
...
...
@@ -2136,21 +2103,17 @@ static inline void flush_unauthorized_files(const struct cred *cred,
spin_lock
(
&
tty_files_lock
);
if
(
!
list_empty
(
&
tty
->
tty_files
))
{
struct
tty_file_private
*
file_priv
;
struct
inode
*
inode
;
/* Revalidate access to controlling tty.
Use
inode_has_perm on the tty inode
directly rather
Use
path_has_perm on the tty path
directly rather
than using file_has_perm, as this particular open
file may belong to another process and we are only
interested in the inode-based check here. */
file_priv
=
list_first_entry
(
&
tty
->
tty_files
,
struct
tty_file_private
,
list
);
file
=
file_priv
->
file
;
inode
=
file
->
f_path
.
dentry
->
d_inode
;
if
(
inode_has_perm_noadp
(
cred
,
inode
,
FILE__READ
|
FILE__WRITE
,
0
))
{
if
(
path_has_perm
(
cred
,
&
file
->
f_path
,
FILE__READ
|
FILE__WRITE
))
drop_tty
=
1
;
}
}
spin_unlock
(
&
tty_files_lock
);
tty_kref_put
(
tty
);
...
...
@@ -2160,10 +2123,6 @@ static inline void flush_unauthorized_files(const struct cred *cred,
no_tty
();
/* Revalidate access to inherited open files. */
COMMON_AUDIT_DATA_INIT
(
&
ad
,
INODE
);
ad
.
selinux_audit_data
=
&
sad
;
spin_lock
(
&
files
->
file_lock
);
for
(;;)
{
unsigned
long
set
,
i
;
...
...
@@ -2500,7 +2459,6 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
{
const
struct
cred
*
cred
=
current_cred
();
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
int
rc
;
rc
=
superblock_doinit
(
sb
,
data
);
...
...
@@ -2511,8 +2469,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
if
(
flags
&
MS_KERNMOUNT
)
return
0
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
DENTRY
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
sb
->
s_root
;
return
superblock_has_perm
(
cred
,
sb
,
FILESYSTEM__MOUNT
,
&
ad
);
}
...
...
@@ -2521,10 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry)
{
const
struct
cred
*
cred
=
current_cred
();
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
ad
,
DENTRY
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
dentry
->
d_sb
->
s_root
;
return
superblock_has_perm
(
cred
,
dentry
->
d_sb
,
FILESYSTEM__GETATTR
,
&
ad
);
}
...
...
@@ -2684,14 +2639,35 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
return
dentry_has_perm
(
cred
,
dentry
,
FILE__READ
);
}
static
noinline
int
audit_inode_permission
(
struct
inode
*
inode
,
u32
perms
,
u32
audited
,
u32
denied
,
unsigned
flags
)
{
struct
common_audit_data
ad
;
struct
inode_security_struct
*
isec
=
inode
->
i_security
;
int
rc
;
ad
.
type
=
LSM_AUDIT_DATA_INODE
;
ad
.
u
.
inode
=
inode
;
rc
=
slow_avc_audit
(
current_sid
(),
isec
->
sid
,
isec
->
sclass
,
perms
,
audited
,
denied
,
&
ad
,
flags
);
if
(
rc
)
return
rc
;
return
0
;
}
static
int
selinux_inode_permission
(
struct
inode
*
inode
,
int
mask
)
{
const
struct
cred
*
cred
=
current_cred
();
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
perms
;
bool
from_access
;
unsigned
flags
=
mask
&
MAY_NOT_BLOCK
;
struct
inode_security_struct
*
isec
;
u32
sid
;
struct
av_decision
avd
;
int
rc
,
rc2
;
u32
audited
,
denied
;
from_access
=
mask
&
MAY_ACCESS
;
mask
&=
(
MAY_READ
|
MAY_WRITE
|
MAY_EXEC
|
MAY_APPEND
);
...
...
@@ -2700,22 +2676,34 @@ static int selinux_inode_permission(struct inode *inode, int mask)
if
(
!
mask
)
return
0
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
INODE
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
u
.
inode
=
inode
;
validate_creds
(
cred
);
if
(
from_access
)
ad
.
selinux_audit_data
->
auditdeny
|=
FILE__AUDIT_ACCESS
;
if
(
unlikely
(
IS_PRIVATE
(
inode
))
)
return
0
;
perms
=
file_mask_to_av
(
inode
->
i_mode
,
mask
);
return
inode_has_perm
(
cred
,
inode
,
perms
,
&
ad
,
flags
);
sid
=
cred_sid
(
cred
);
isec
=
inode
->
i_security
;
rc
=
avc_has_perm_noaudit
(
sid
,
isec
->
sid
,
isec
->
sclass
,
perms
,
0
,
&
avd
);
audited
=
avc_audit_required
(
perms
,
&
avd
,
rc
,
from_access
?
FILE__AUDIT_ACCESS
:
0
,
&
denied
);
if
(
likely
(
!
audited
))
return
rc
;
rc2
=
audit_inode_permission
(
inode
,
perms
,
audited
,
denied
,
flags
);
if
(
rc2
)
return
rc2
;
return
rc
;
}
static
int
selinux_inode_setattr
(
struct
dentry
*
dentry
,
struct
iattr
*
iattr
)
{
const
struct
cred
*
cred
=
current_cred
();
unsigned
int
ia_valid
=
iattr
->
ia_valid
;
__u32
av
=
FILE__WRITE
;
/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
if
(
ia_valid
&
ATTR_FORCE
)
{
...
...
@@ -2729,7 +2717,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
ATTR_ATIME_SET
|
ATTR_MTIME_SET
|
ATTR_TIMES_SET
))
return
dentry_has_perm
(
cred
,
dentry
,
FILE__SETATTR
);
return
dentry_has_perm
(
cred
,
dentry
,
FILE__WRITE
);
if
(
ia_valid
&
ATTR_SIZE
)
av
|=
FILE__OPEN
;
return
dentry_has_perm
(
cred
,
dentry
,
av
);
}
static
int
selinux_inode_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
)
...
...
@@ -2771,7 +2762,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
struct
inode_security_struct
*
isec
=
inode
->
i_security
;
struct
superblock_security_struct
*
sbsec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
newsid
,
sid
=
current_sid
();
int
rc
=
0
;
...
...
@@ -2785,8 +2775,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
if
(
!
inode_owner_or_capable
(
inode
))
return
-
EPERM
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
DENTRY
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
dentry
;
rc
=
avc_has_perm
(
sid
,
isec
->
sid
,
isec
->
sclass
,
...
...
@@ -2796,8 +2785,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
rc
=
security_context_to_sid
(
value
,
size
,
&
newsid
);
if
(
rc
==
-
EINVAL
)
{
if
(
!
capable
(
CAP_MAC_ADMIN
))
if
(
!
capable
(
CAP_MAC_ADMIN
))
{
struct
audit_buffer
*
ab
;
size_t
audit_size
;
const
char
*
str
;
/* We strip a nul only if it is at the end, otherwise the
* context contains a nul and we should audit that */
str
=
value
;
if
(
str
[
size
-
1
]
==
'\0'
)
audit_size
=
size
-
1
;
else
audit_size
=
size
;
ab
=
audit_log_start
(
current
->
audit_context
,
GFP_ATOMIC
,
AUDIT_SELINUX_ERR
);
audit_log_format
(
ab
,
"op=setxattr invalid_context="
);
audit_log_n_untrustedstring
(
ab
,
value
,
audit_size
);
audit_log_end
(
ab
);
return
rc
;
}
rc
=
security_context_to_sid_force
(
value
,
size
,
&
newsid
);
}
if
(
rc
)
...
...
@@ -2977,7 +2983,7 @@ static int selinux_file_permission(struct file *file, int mask)
if
(
sid
==
fsec
->
sid
&&
fsec
->
isid
==
isec
->
sid
&&
fsec
->
pseqno
==
avc_policy_seqno
())
/* No change since
dentry
_open check. */
/* No change since
file
_open check. */
return
0
;
return
selinux_revalidate_file_permission
(
file
,
mask
);
...
...
@@ -3236,15 +3242,13 @@ static int selinux_file_receive(struct file *file)
return
file_has_perm
(
cred
,
file
,
file_to_av
(
file
));
}
static
int
selinux_
dentry
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
static
int
selinux_
file
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
{
struct
file_security_struct
*
fsec
;
struct
inode
*
inode
;
struct
inode_security_struct
*
isec
;
inode
=
file
->
f_path
.
dentry
->
d_inode
;
fsec
=
file
->
f_security
;
isec
=
inode
->
i_security
;
isec
=
file
->
f_path
.
dentry
->
d_
inode
->
i_security
;
/*
* Save inode label and policy sequence number
* at open-time so that selinux_file_permission
...
...
@@ -3262,7 +3266,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
* new inode label or new policy.
* This check is not redundant - do not remove.
*/
return
inode_has_perm_noadp
(
cred
,
inode
,
open_file_to_av
(
file
),
0
);
return
path_has_perm
(
cred
,
&
file
->
f_path
,
open_file_to_av
(
file
)
);
}
/* task security operations */
...
...
@@ -3381,12 +3385,10 @@ static int selinux_kernel_module_request(char *kmod_name)
{
u32
sid
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
sid
=
task_sid
(
current
);
COMMON_AUDIT_DATA_INIT
(
&
ad
,
KMOD
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_KMOD
;
ad
.
u
.
kmod_name
=
kmod_name
;
return
avc_has_perm
(
sid
,
SECINITSID_KERNEL
,
SECCLASS_SYSTEM
,
...
...
@@ -3759,15 +3761,13 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
{
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
u32
tsid
=
task_sid
(
task
);
if
(
sksec
->
sid
==
SECINITSID_KERNEL
)
return
0
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
sk
=
sk
;
...
...
@@ -3847,7 +3847,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
char
*
addrp
;
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
struct
sockaddr_in
*
addr4
=
NULL
;
struct
sockaddr_in6
*
addr6
=
NULL
;
...
...
@@ -3874,8 +3873,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
snum
,
&
sid
);
if
(
err
)
goto
out
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
sport
=
htons
(
snum
);
ad
.
u
.
net
->
family
=
family
;
...
...
@@ -3909,8 +3907,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if
(
err
)
goto
out
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
sport
=
htons
(
snum
);
ad
.
u
.
net
->
family
=
family
;
...
...
@@ -3945,7 +3942,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
if
(
sksec
->
sclass
==
SECCLASS_TCP_SOCKET
||
sksec
->
sclass
==
SECCLASS_DCCP_SOCKET
)
{
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
struct
sockaddr_in
*
addr4
=
NULL
;
struct
sockaddr_in6
*
addr6
=
NULL
;
...
...
@@ -3971,8 +3967,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
perm
=
(
sksec
->
sclass
==
SECCLASS_TCP_SOCKET
)
?
TCP_SOCKET__NAME_CONNECT
:
DCCP_SOCKET__NAME_CONNECT
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
dport
=
htons
(
snum
);
ad
.
u
.
net
->
family
=
sk
->
sk_family
;
...
...
@@ -4064,12 +4059,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
struct
sk_security_struct
*
sksec_other
=
other
->
sk_security
;
struct
sk_security_struct
*
sksec_new
=
newsk
->
sk_security
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
int
err
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
sk
=
other
;
...
...
@@ -4098,11 +4091,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,
struct
sk_security_struct
*
ssec
=
sock
->
sk
->
sk_security
;
struct
sk_security_struct
*
osec
=
other
->
sk
->
sk_security
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
sk
=
other
->
sk
;
...
...
@@ -4140,12 +4131,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
struct
sk_security_struct
*
sksec
=
sk
->
sk_security
;
u32
sk_sid
=
sksec
->
sid
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
char
*
addrp
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
netif
=
skb
->
skb_iif
;
ad
.
u
.
net
->
family
=
family
;
...
...
@@ -4175,7 +4164,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
u16
family
=
sk
->
sk_family
;
u32
sk_sid
=
sksec
->
sid
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
char
*
addrp
;
u8
secmark_active
;
...
...
@@ -4200,8 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if
(
!
secmark_active
&&
!
peerlbl_active
)
return
0
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
netif
=
skb
->
skb_iif
;
ad
.
u
.
net
->
family
=
family
;
...
...
@@ -4539,7 +4526,6 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
char
*
addrp
;
u32
peer_sid
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
u8
secmark_active
;
u8
netlbl_active
;
...
...
@@ -4557,8 +4543,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
if
(
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_sid
)
!=
0
)
return
NF_DROP
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
netif
=
ifindex
;
ad
.
u
.
net
->
family
=
family
;
...
...
@@ -4648,7 +4633,6 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
struct
sock
*
sk
=
skb
->
sk
;
struct
sk_security_struct
*
sksec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
char
*
addrp
;
u8
proto
;
...
...
@@ -4657,8 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
return
NF_ACCEPT
;
sksec
=
sk
->
sk_security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
netif
=
ifindex
;
ad
.
u
.
net
->
family
=
family
;
...
...
@@ -4683,7 +4666,6 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
u32
peer_sid
;
struct
sock
*
sk
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
struct
lsm_network_audit
net
=
{
0
,};
char
*
addrp
;
u8
secmark_active
;
...
...
@@ -4730,8 +4712,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
secmark_perm
=
PACKET__SEND
;
}
COMMON_AUDIT_DATA_INIT
(
&
ad
,
NET
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_NET
;
ad
.
u
.
net
=
&
net
;
ad
.
u
.
net
->
netif
=
ifindex
;
ad
.
u
.
net
->
family
=
family
;
...
...
@@ -4849,13 +4830,11 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
{
struct
ipc_security_struct
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
isec
=
ipc_perms
->
security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
ipc_perms
->
key
;
return
avc_has_perm
(
sid
,
isec
->
sid
,
isec
->
sclass
,
perms
,
&
ad
);
...
...
@@ -4876,7 +4855,6 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
{
struct
ipc_security_struct
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
int
rc
;
...
...
@@ -4886,8 +4864,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
isec
=
msq
->
q_perm
.
security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
msq
->
q_perm
.
key
;
rc
=
avc_has_perm
(
sid
,
isec
->
sid
,
SECCLASS_MSGQ
,
...
...
@@ -4908,13 +4885,11 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
{
struct
ipc_security_struct
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
isec
=
msq
->
q_perm
.
security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
msq
->
q_perm
.
key
;
return
avc_has_perm
(
sid
,
isec
->
sid
,
SECCLASS_MSGQ
,
...
...
@@ -4954,7 +4929,6 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
struct
ipc_security_struct
*
isec
;
struct
msg_security_struct
*
msec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
int
rc
;
...
...
@@ -4975,8 +4949,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
return
rc
;
}
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
msq
->
q_perm
.
key
;
/* Can this process write to the queue? */
...
...
@@ -5001,15 +4974,13 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct
ipc_security_struct
*
isec
;
struct
msg_security_struct
*
msec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
task_sid
(
target
);
int
rc
;
isec
=
msq
->
q_perm
.
security
;
msec
=
msg
->
security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
msq
->
q_perm
.
key
;
rc
=
avc_has_perm
(
sid
,
isec
->
sid
,
...
...
@@ -5025,7 +4996,6 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
{
struct
ipc_security_struct
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
int
rc
;
...
...
@@ -5035,8 +5005,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
isec
=
shp
->
shm_perm
.
security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
shp
->
shm_perm
.
key
;
rc
=
avc_has_perm
(
sid
,
isec
->
sid
,
SECCLASS_SHM
,
...
...
@@ -5057,13 +5026,11 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
{
struct
ipc_security_struct
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
isec
=
shp
->
shm_perm
.
security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
shp
->
shm_perm
.
key
;
return
avc_has_perm
(
sid
,
isec
->
sid
,
SECCLASS_SHM
,
...
...
@@ -5121,7 +5088,6 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
{
struct
ipc_security_struct
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
int
rc
;
...
...
@@ -5131,8 +5097,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
isec
=
sma
->
sem_perm
.
security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
sma
->
sem_perm
.
key
;
rc
=
avc_has_perm
(
sid
,
isec
->
sid
,
SECCLASS_SEM
,
...
...
@@ -5153,13 +5118,11 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
{
struct
ipc_security_struct
*
isec
;
struct
common_audit_data
ad
;
struct
selinux_audit_data
sad
=
{
0
,};
u32
sid
=
current_sid
();
isec
=
sma
->
sem_perm
.
security
;
COMMON_AUDIT_DATA_INIT
(
&
ad
,
IPC
);
ad
.
selinux_audit_data
=
&
sad
;
ad
.
type
=
LSM_AUDIT_DATA_IPC
;
ad
.
u
.
ipc_id
=
sma
->
sem_perm
.
key
;
return
avc_has_perm
(
sid
,
isec
->
sid
,
SECCLASS_SEM
,
...
...
@@ -5339,8 +5302,23 @@ static int selinux_setprocattr(struct task_struct *p,
}
error
=
security_context_to_sid
(
value
,
size
,
&
sid
);
if
(
error
==
-
EINVAL
&&
!
strcmp
(
name
,
"fscreate"
))
{
if
(
!
capable
(
CAP_MAC_ADMIN
))
if
(
!
capable
(
CAP_MAC_ADMIN
))
{
struct
audit_buffer
*
ab
;
size_t
audit_size
;
/* We strip a nul only if it is at the end, otherwise the
* context contains a nul and we should audit that */
if
(
str
[
size
-
1
]
==
'\0'
)
audit_size
=
size
-
1
;
else
audit_size
=
size
;
ab
=
audit_log_start
(
current
->
audit_context
,
GFP_ATOMIC
,
AUDIT_SELINUX_ERR
);
audit_log_format
(
ab
,
"op=fscreate invalid_context="
);
audit_log_n_untrustedstring
(
ab
,
value
,
audit_size
);
audit_log_end
(
ab
);
return
error
;
}
error
=
security_context_to_sid_force
(
value
,
size
,
&
sid
);
}
...
...
@@ -5600,7 +5578,7 @@ static struct security_operations selinux_ops = {
.
file_send_sigiotask
=
selinux_file_send_sigiotask
,
.
file_receive
=
selinux_file_receive
,
.
dentry_open
=
selinux_dentry
_open
,
.
file_open
=
selinux_file
_open
,
.
task_create
=
selinux_task_create
,
.
cred_alloc_blank
=
selinux_cred_alloc_blank
,
...
...
security/selinux/include/avc.h
View file @
ff2bb047
...
...
@@ -49,7 +49,7 @@ struct avc_cache_stats {
/*
* We only need this data after we have decided to send an audit message.
*/
struct
selinux_
late_
audit_data
{
struct
selinux_audit_data
{
u32
ssid
;
u32
tsid
;
u16
tclass
;
...
...
@@ -59,29 +59,87 @@ struct selinux_late_audit_data {
int
result
;
};
/*
* We collect this at the beginning or during an selinux security operation
*/
struct
selinux_audit_data
{
/*
* auditdeny is a bit tricky and unintuitive. See the
* comments in avc.c for it's meaning and usage.
*/
u32
auditdeny
;
struct
selinux_late_audit_data
*
slad
;
};
/*
* AVC operations
*/
void
__init
avc_init
(
void
);
int
avc_audit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
struct
av_decision
*
avd
,
int
result
,
struct
common_audit_data
*
a
,
unsigned
flags
);
static
inline
u32
avc_audit_required
(
u32
requested
,
struct
av_decision
*
avd
,
int
result
,
u32
auditdeny
,
u32
*
deniedp
)
{
u32
denied
,
audited
;
denied
=
requested
&
~
avd
->
allowed
;
if
(
unlikely
(
denied
))
{
audited
=
denied
&
avd
->
auditdeny
;
/*
* auditdeny is TRICKY! Setting a bit in
* this field means that ANY denials should NOT be audited if
* the policy contains an explicit dontaudit rule for that
* permission. Take notice that this is unrelated to the
* actual permissions that were denied. As an example lets
* assume:
*
* denied == READ
* avd.auditdeny & ACCESS == 0 (not set means explicit rule)
* auditdeny & ACCESS == 1
*
* We will NOT audit the denial even though the denied
* permission was READ and the auditdeny checks were for
* ACCESS
*/
if
(
auditdeny
&&
!
(
auditdeny
&
avd
->
auditdeny
))
audited
=
0
;
}
else
if
(
result
)
audited
=
denied
=
requested
;
else
audited
=
requested
&
avd
->
auditallow
;
*
deniedp
=
denied
;
return
audited
;
}
int
slow_avc_audit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
u32
audited
,
u32
denied
,
struct
common_audit_data
*
a
,
unsigned
flags
);
/**
* avc_audit - Audit the granting or denial of permissions.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions
* @avd: access vector decisions
* @result: result from avc_has_perm_noaudit
* @a: auxiliary audit data
* @flags: VFS walk flags
*
* Audit the granting or denial of permissions in accordance
* with the policy. This function is typically called by
* avc_has_perm() after a permission check, but can also be
* called directly by callers who use avc_has_perm_noaudit()
* in order to separate the permission check from the auditing.
* For example, this separation is useful when the permission check must
* be performed under a lock, to allow the lock to be released
* before calling the auditing code.
*/
static
inline
int
avc_audit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
struct
av_decision
*
avd
,
int
result
,
struct
common_audit_data
*
a
,
unsigned
flags
)
{
u32
audited
,
denied
;
audited
=
avc_audit_required
(
requested
,
avd
,
result
,
0
,
&
denied
);
if
(
likely
(
!
audited
))
return
0
;
return
slow_avc_audit
(
ssid
,
tsid
,
tclass
,
requested
,
audited
,
denied
,
a
,
flags
);
}
#define AVC_STRICT 1
/* Ignore permissive mode. */
int
avc_has_perm_noaudit
(
u32
ssid
,
u32
tsid
,
...
...
@@ -112,11 +170,7 @@ u32 avc_policy_seqno(void);
#define AVC_CALLBACK_AUDITDENY_ENABLE 64
#define AVC_CALLBACK_AUDITDENY_DISABLE 128
int
avc_add_callback
(
int
(
*
callback
)(
u32
event
,
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
perms
,
u32
*
out_retained
),
u32
events
,
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
perms
);
int
avc_add_callback
(
int
(
*
callback
)(
u32
event
),
u32
events
);
/* Exported to selinuxfs */
int
avc_get_hash_stats
(
char
*
page
);
...
...
security/selinux/include/security.h
View file @
ff2bb047
...
...
@@ -31,13 +31,15 @@
#define POLICYDB_VERSION_BOUNDARY 24
#define POLICYDB_VERSION_FILENAME_TRANS 25
#define POLICYDB_VERSION_ROLETRANS 26
#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
#define POLICYDB_VERSION_DEFAULT_TYPE 28
/* 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_
ROLETRANS
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_
DEFAULT_TYPE
#endif
/* Mask for just the mount related flags */
...
...
security/selinux/netif.c
View file @
ff2bb047
...
...
@@ -252,8 +252,7 @@ static void sel_netif_flush(void)
spin_unlock_bh
(
&
sel_netif_lock
);
}
static
int
sel_netif_avc_callback
(
u32
event
,
u32
ssid
,
u32
tsid
,
u16
class
,
u32
perms
,
u32
*
retained
)
static
int
sel_netif_avc_callback
(
u32
event
)
{
if
(
event
==
AVC_CALLBACK_RESET
)
{
sel_netif_flush
();
...
...
@@ -292,8 +291,7 @@ static __init int sel_netif_init(void)
register_netdevice_notifier
(
&
sel_netif_netdev_notifier
);
err
=
avc_add_callback
(
sel_netif_avc_callback
,
AVC_CALLBACK_RESET
,
SECSID_NULL
,
SECSID_NULL
,
SECCLASS_NULL
,
0
);
err
=
avc_add_callback
(
sel_netif_avc_callback
,
AVC_CALLBACK_RESET
);
if
(
err
)
panic
(
"avc_add_callback() failed, error %d
\n
"
,
err
);
...
...
security/selinux/netnode.c
View file @
ff2bb047
...
...
@@ -297,8 +297,7 @@ static void sel_netnode_flush(void)
spin_unlock_bh
(
&
sel_netnode_lock
);
}
static
int
sel_netnode_avc_callback
(
u32
event
,
u32
ssid
,
u32
tsid
,
u16
class
,
u32
perms
,
u32
*
retained
)
static
int
sel_netnode_avc_callback
(
u32
event
)
{
if
(
event
==
AVC_CALLBACK_RESET
)
{
sel_netnode_flush
();
...
...
@@ -320,8 +319,7 @@ static __init int sel_netnode_init(void)
sel_netnode_hash
[
iter
].
size
=
0
;
}
ret
=
avc_add_callback
(
sel_netnode_avc_callback
,
AVC_CALLBACK_RESET
,
SECSID_NULL
,
SECSID_NULL
,
SECCLASS_NULL
,
0
);
ret
=
avc_add_callback
(
sel_netnode_avc_callback
,
AVC_CALLBACK_RESET
);
if
(
ret
!=
0
)
panic
(
"avc_add_callback() failed, error %d
\n
"
,
ret
);
...
...
security/selinux/netport.c
View file @
ff2bb047
...
...
@@ -234,8 +234,7 @@ static void sel_netport_flush(void)
spin_unlock_bh
(
&
sel_netport_lock
);
}
static
int
sel_netport_avc_callback
(
u32
event
,
u32
ssid
,
u32
tsid
,
u16
class
,
u32
perms
,
u32
*
retained
)
static
int
sel_netport_avc_callback
(
u32
event
)
{
if
(
event
==
AVC_CALLBACK_RESET
)
{
sel_netport_flush
();
...
...
@@ -257,8 +256,7 @@ static __init int sel_netport_init(void)
sel_netport_hash
[
iter
].
size
=
0
;
}
ret
=
avc_add_callback
(
sel_netport_avc_callback
,
AVC_CALLBACK_RESET
,
SECSID_NULL
,
SECSID_NULL
,
SECCLASS_NULL
,
0
);
ret
=
avc_add_callback
(
sel_netport_avc_callback
,
AVC_CALLBACK_RESET
);
if
(
ret
!=
0
)
panic
(
"avc_add_callback() failed, error %d
\n
"
,
ret
);
...
...
security/selinux/selinuxfs.c
View file @
ff2bb047
...
...
@@ -496,6 +496,7 @@ static const struct file_operations sel_policy_ops = {
.
read
=
sel_read_policy
,
.
mmap
=
sel_mmap_policy
,
.
release
=
sel_release_policy
,
.
llseek
=
generic_file_llseek
,
};
static
ssize_t
sel_write_load
(
struct
file
*
file
,
const
char
__user
*
buf
,
...
...
@@ -1232,6 +1233,7 @@ static int sel_make_bools(void)
kfree
(
bool_pending_names
[
i
]);
kfree
(
bool_pending_names
);
kfree
(
bool_pending_values
);
bool_num
=
0
;
bool_pending_names
=
NULL
;
bool_pending_values
=
NULL
;
...
...
@@ -1532,11 +1534,6 @@ static int sel_make_initcon_files(struct dentry *dir)
return
0
;
}
static
inline
unsigned
int
sel_div
(
unsigned
long
a
,
unsigned
long
b
)
{
return
a
/
b
-
(
a
%
b
<
0
);
}
static
inline
unsigned
long
sel_class_to_ino
(
u16
class
)
{
return
(
class
*
(
SEL_VEC_MAX
+
1
))
|
SEL_CLASS_INO_OFFSET
;
...
...
@@ -1544,7 +1541,7 @@ static inline unsigned long sel_class_to_ino(u16 class)
static
inline
u16
sel_ino_to_class
(
unsigned
long
ino
)
{
return
sel_div
(
ino
&
SEL_INO_MASK
,
SEL_VEC_MAX
+
1
);
return
(
ino
&
SEL_INO_MASK
)
/
(
SEL_VEC_MAX
+
1
);
}
static
inline
unsigned
long
sel_perm_to_ino
(
u16
class
,
u32
perm
)
...
...
@@ -1831,7 +1828,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
[
SEL_REJECT_UNKNOWN
]
=
{
"reject_unknown"
,
&
sel_handle_unknown_ops
,
S_IRUGO
},
[
SEL_DENY_UNKNOWN
]
=
{
"deny_unknown"
,
&
sel_handle_unknown_ops
,
S_IRUGO
},
[
SEL_STATUS
]
=
{
"status"
,
&
sel_handle_status_ops
,
S_IRUGO
},
[
SEL_POLICY
]
=
{
"policy"
,
&
sel_policy_ops
,
S_IRU
SR
},
[
SEL_POLICY
]
=
{
"policy"
,
&
sel_policy_ops
,
S_IRU
GO
},
/* last one */
{
""
}
};
ret
=
simple_fill_super
(
sb
,
SELINUX_MAGIC
,
selinux_files
);
...
...
security/selinux/ss/context.h
View file @
ff2bb047
...
...
@@ -74,6 +74,26 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src)
return
rc
;
}
/*
* Sets both levels in the MLS range of 'dst' to the high level of 'src'.
*/
static
inline
int
mls_context_cpy_high
(
struct
context
*
dst
,
struct
context
*
src
)
{
int
rc
;
dst
->
range
.
level
[
0
].
sens
=
src
->
range
.
level
[
1
].
sens
;
rc
=
ebitmap_cpy
(
&
dst
->
range
.
level
[
0
].
cat
,
&
src
->
range
.
level
[
1
].
cat
);
if
(
rc
)
goto
out
;
dst
->
range
.
level
[
1
].
sens
=
src
->
range
.
level
[
1
].
sens
;
rc
=
ebitmap_cpy
(
&
dst
->
range
.
level
[
1
].
cat
,
&
src
->
range
.
level
[
1
].
cat
);
if
(
rc
)
ebitmap_destroy
(
&
dst
->
range
.
level
[
0
].
cat
);
out:
return
rc
;
}
static
inline
int
mls_context_cmp
(
struct
context
*
c1
,
struct
context
*
c2
)
{
return
((
c1
->
range
.
level
[
0
].
sens
==
c2
->
range
.
level
[
0
].
sens
)
&&
...
...
security/selinux/ss/mls.c
View file @
ff2bb047
...
...
@@ -517,6 +517,8 @@ int mls_compute_sid(struct context *scontext,
{
struct
range_trans
rtr
;
struct
mls_range
*
r
;
struct
class_datum
*
cladatum
;
int
default_range
=
0
;
if
(
!
policydb
.
mls_enabled
)
return
0
;
...
...
@@ -530,6 +532,28 @@ int mls_compute_sid(struct context *scontext,
r
=
hashtab_search
(
policydb
.
range_tr
,
&
rtr
);
if
(
r
)
return
mls_range_set
(
newcontext
,
r
);
if
(
tclass
&&
tclass
<=
policydb
.
p_classes
.
nprim
)
{
cladatum
=
policydb
.
class_val_to_struct
[
tclass
-
1
];
if
(
cladatum
)
default_range
=
cladatum
->
default_range
;
}
switch
(
default_range
)
{
case
DEFAULT_SOURCE_LOW
:
return
mls_context_cpy_low
(
newcontext
,
scontext
);
case
DEFAULT_SOURCE_HIGH
:
return
mls_context_cpy_high
(
newcontext
,
scontext
);
case
DEFAULT_SOURCE_LOW_HIGH
:
return
mls_context_cpy
(
newcontext
,
scontext
);
case
DEFAULT_TARGET_LOW
:
return
mls_context_cpy_low
(
newcontext
,
tcontext
);
case
DEFAULT_TARGET_HIGH
:
return
mls_context_cpy_high
(
newcontext
,
tcontext
);
case
DEFAULT_TARGET_LOW_HIGH
:
return
mls_context_cpy
(
newcontext
,
tcontext
);
}
/* Fallthrough */
case
AVTAB_CHANGE
:
if
((
tclass
==
policydb
.
process_class
)
||
(
sock
==
true
))
...
...
security/selinux/ss/policydb.c
View file @
ff2bb047
...
...
@@ -133,6 +133,16 @@ static struct policydb_compat_info policydb_compat[] = {
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
{
.
version
=
POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
{
.
version
=
POLICYDB_VERSION_DEFAULT_TYPE
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
};
static
struct
policydb_compat_info
*
policydb_lookup_compat
(
int
version
)
...
...
@@ -1306,6 +1316,23 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
goto
bad
;
}
if
(
p
->
policyvers
>=
POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
)
{
rc
=
next_entry
(
buf
,
fp
,
sizeof
(
u32
)
*
3
);
if
(
rc
)
goto
bad
;
cladatum
->
default_user
=
le32_to_cpu
(
buf
[
0
]);
cladatum
->
default_role
=
le32_to_cpu
(
buf
[
1
]);
cladatum
->
default_range
=
le32_to_cpu
(
buf
[
2
]);
}
if
(
p
->
policyvers
>=
POLICYDB_VERSION_DEFAULT_TYPE
)
{
rc
=
next_entry
(
buf
,
fp
,
sizeof
(
u32
)
*
1
);
if
(
rc
)
goto
bad
;
cladatum
->
default_type
=
le32_to_cpu
(
buf
[
0
]);
}
rc
=
hashtab_insert
(
h
,
key
,
cladatum
);
if
(
rc
)
goto
bad
;
...
...
@@ -2832,6 +2859,23 @@ static int class_write(void *vkey, void *datum, void *ptr)
if
(
rc
)
return
rc
;
if
(
p
->
policyvers
>=
POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
)
{
buf
[
0
]
=
cpu_to_le32
(
cladatum
->
default_user
);
buf
[
1
]
=
cpu_to_le32
(
cladatum
->
default_role
);
buf
[
2
]
=
cpu_to_le32
(
cladatum
->
default_range
);
rc
=
put_entry
(
buf
,
sizeof
(
uint32_t
),
3
,
fp
);
if
(
rc
)
return
rc
;
}
if
(
p
->
policyvers
>=
POLICYDB_VERSION_DEFAULT_TYPE
)
{
buf
[
0
]
=
cpu_to_le32
(
cladatum
->
default_type
);
rc
=
put_entry
(
buf
,
sizeof
(
uint32_t
),
1
,
fp
);
if
(
rc
)
return
rc
;
}
return
0
;
}
...
...
security/selinux/ss/policydb.h
View file @
ff2bb047
...
...
@@ -60,6 +60,20 @@ struct class_datum {
struct
symtab
permissions
;
/* class-specific permission symbol table */
struct
constraint_node
*
constraints
;
/* constraints on class permissions */
struct
constraint_node
*
validatetrans
;
/* special transition rules */
/* Options how a new object user, role, and type should be decided */
#define DEFAULT_SOURCE 1
#define DEFAULT_TARGET 2
char
default_user
;
char
default_role
;
char
default_type
;
/* Options how a new object range should be decided */
#define DEFAULT_SOURCE_LOW 1
#define DEFAULT_SOURCE_HIGH 2
#define DEFAULT_SOURCE_LOW_HIGH 3
#define DEFAULT_TARGET_LOW 4
#define DEFAULT_TARGET_HIGH 5
#define DEFAULT_TARGET_LOW_HIGH 6
char
default_range
;
};
/* Role attributes */
...
...
security/selinux/ss/services.c
View file @
ff2bb047
...
...
@@ -1018,9 +1018,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
if
(
context
->
len
)
{
*
scontext_len
=
context
->
len
;
*
scontext
=
kstrdup
(
context
->
str
,
GFP_ATOMIC
);
if
(
!
(
*
scontext
))
return
-
ENOMEM
;
if
(
scontext
)
{
*
scontext
=
kstrdup
(
context
->
str
,
GFP_ATOMIC
);
if
(
!
(
*
scontext
))
return
-
ENOMEM
;
}
return
0
;
}
...
...
@@ -1389,6 +1391,7 @@ static int security_compute_sid(u32 ssid,
u32
*
out_sid
,
bool
kern
)
{
struct
class_datum
*
cladatum
=
NULL
;
struct
context
*
scontext
=
NULL
,
*
tcontext
=
NULL
,
newcontext
;
struct
role_trans
*
roletr
=
NULL
;
struct
avtab_key
avkey
;
...
...
@@ -1437,12 +1440,20 @@ static int security_compute_sid(u32 ssid,
goto
out_unlock
;
}
if
(
tclass
&&
tclass
<=
policydb
.
p_classes
.
nprim
)
cladatum
=
policydb
.
class_val_to_struct
[
tclass
-
1
];
/* Set the user identity. */
switch
(
specified
)
{
case
AVTAB_TRANSITION
:
case
AVTAB_CHANGE
:
/* Use the process user identity. */
newcontext
.
user
=
scontext
->
user
;
if
(
cladatum
&&
cladatum
->
default_user
==
DEFAULT_TARGET
)
{
newcontext
.
user
=
tcontext
->
user
;
}
else
{
/* notice this gets both DEFAULT_SOURCE and unset */
/* Use the process user identity. */
newcontext
.
user
=
scontext
->
user
;
}
break
;
case
AVTAB_MEMBER
:
/* Use the related object owner. */
...
...
@@ -1450,16 +1461,31 @@ static int security_compute_sid(u32 ssid,
break
;
}
/* Set the role and type to default values. */
if
((
tclass
==
policydb
.
process_class
)
||
(
sock
==
true
))
{
/* Use the current role and type of process. */
/* Set the role to default values. */
if
(
cladatum
&&
cladatum
->
default_role
==
DEFAULT_SOURCE
)
{
newcontext
.
role
=
scontext
->
role
;
newcontext
.
type
=
scontext
->
type
;
}
else
if
(
cladatum
&&
cladatum
->
default_role
==
DEFAULT_TARGET
)
{
newcontext
.
role
=
tcontext
->
role
;
}
else
{
/* Use the well-defined object role. */
newcontext
.
role
=
OBJECT_R_VAL
;
/* Use the type of the related object. */
if
((
tclass
==
policydb
.
process_class
)
||
(
sock
==
true
))
newcontext
.
role
=
scontext
->
role
;
else
newcontext
.
role
=
OBJECT_R_VAL
;
}
/* Set the type to default values. */
if
(
cladatum
&&
cladatum
->
default_type
==
DEFAULT_SOURCE
)
{
newcontext
.
type
=
scontext
->
type
;
}
else
if
(
cladatum
&&
cladatum
->
default_type
==
DEFAULT_TARGET
)
{
newcontext
.
type
=
tcontext
->
type
;
}
else
{
if
((
tclass
==
policydb
.
process_class
)
||
(
sock
==
true
))
{
/* Use the type of process. */
newcontext
.
type
=
scontext
->
type
;
}
else
{
/* Use the type of the related object. */
newcontext
.
type
=
tcontext
->
type
;
}
}
/* Look for a type transition/member/change rule. */
...
...
@@ -3018,8 +3044,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
static
int
(
*
aurule_callback
)(
void
)
=
audit_update_lsm_rules
;
static
int
aurule_avc_callback
(
u32
event
,
u32
ssid
,
u32
tsid
,
u16
class
,
u32
perms
,
u32
*
retained
)
static
int
aurule_avc_callback
(
u32
event
)
{
int
err
=
0
;
...
...
@@ -3032,8 +3057,7 @@ static int __init aurule_init(void)
{
int
err
;
err
=
avc_add_callback
(
aurule_avc_callback
,
AVC_CALLBACK_RESET
,
SECSID_NULL
,
SECSID_NULL
,
SECCLASS_NULL
,
0
);
err
=
avc_add_callback
(
aurule_avc_callback
,
AVC_CALLBACK_RESET
);
if
(
err
)
panic
(
"avc_add_callback() failed, error %d
\n
"
,
err
);
...
...
security/smack/smack.h
View file @
ff2bb047
...
...
@@ -304,7 +304,7 @@ void smack_log(char *subject_label, char *object_label,
static
inline
void
smk_ad_init
(
struct
smk_audit_info
*
a
,
const
char
*
func
,
char
type
)
{
memset
(
a
,
0
,
sizeof
(
*
a
));
memset
(
&
a
->
sad
,
0
,
sizeof
(
a
->
sad
));
a
->
a
.
type
=
type
;
a
->
a
.
smack_audit_data
=
&
a
->
sad
;
a
->
a
.
smack_audit_data
->
function
=
func
;
...
...
security/smack/smack_lsm.c
View file @
ff2bb047
...
...
@@ -1359,7 +1359,7 @@ static int smack_file_receive(struct file *file)
}
/**
* smack_
dentry
_open - Smack dentry open processing
* smack_
file
_open - Smack dentry open processing
* @file: the object
* @cred: unused
*
...
...
@@ -1367,7 +1367,7 @@ static int smack_file_receive(struct file *file)
*
* Returns 0
*/
static
int
smack_
dentry
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
static
int
smack_
file
_open
(
struct
file
*
file
,
const
struct
cred
*
cred
)
{
struct
inode_smack
*
isp
=
file
->
f_path
.
dentry
->
d_inode
->
i_security
;
...
...
@@ -3487,7 +3487,7 @@ struct security_operations smack_ops = {
.
file_send_sigiotask
=
smack_file_send_sigiotask
,
.
file_receive
=
smack_file_receive
,
.
dentry_open
=
smack_dentry
_open
,
.
file_open
=
smack_file
_open
,
.
cred_alloc_blank
=
smack_cred_alloc_blank
,
.
cred_free
=
smack_cred_free
,
...
...
security/tomoyo/tomoyo.c
View file @
ff2bb047
...
...
@@ -319,14 +319,14 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
}
/**
* tomoyo_
dentry_open - Target for security_dentry
_open().
* tomoyo_
file_open - Target for security_file
_open().
*
* @f: Pointer to "struct file".
* @cred: Pointer to "struct cred".
*
* Returns 0 on success, negative value otherwise.
*/
static
int
tomoyo_
dentry
_open
(
struct
file
*
f
,
const
struct
cred
*
cred
)
static
int
tomoyo_
file
_open
(
struct
file
*
f
,
const
struct
cred
*
cred
)
{
int
flags
=
f
->
f_flags
;
/* Don't check read permission here if called from do_execve(). */
...
...
@@ -510,7 +510,7 @@ static struct security_operations tomoyo_security_ops = {
.
bprm_set_creds
=
tomoyo_bprm_set_creds
,
.
bprm_check_security
=
tomoyo_bprm_check_security
,
.
file_fcntl
=
tomoyo_file_fcntl
,
.
dentry_open
=
tomoyo_dentry
_open
,
.
file_open
=
tomoyo_file
_open
,
.
path_truncate
=
tomoyo_path_truncate
,
.
path_unlink
=
tomoyo_path_unlink
,
.
path_mkdir
=
tomoyo_path_mkdir
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment