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
Kirill Smelkov
linux
Commits
5d54e69c
Commit
5d54e69c
authored
Sep 13, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6
parents
63f3d1df
b6ddc518
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
356 additions
and
171 deletions
+356
-171
MAINTAINERS
MAINTAINERS
+4
-1
arch/ppc64/kernel/asm-offsets.c
arch/ppc64/kernel/asm-offsets.c
+1
-0
arch/ppc64/kernel/entry.S
arch/ppc64/kernel/entry.S
+14
-4
fs/namei.c
fs/namei.c
+1
-1
include/linux/audit.h
include/linux/audit.h
+23
-13
kernel/audit.c
kernel/audit.c
+79
-49
kernel/auditsc.c
kernel/auditsc.c
+229
-98
security/selinux/avc.c
security/selinux/avc.c
+2
-2
security/selinux/hooks.c
security/selinux/hooks.c
+1
-1
security/selinux/ss/services.c
security/selinux/ss/services.c
+2
-2
No files found.
MAINTAINERS
View file @
5d54e69c
...
...
@@ -370,7 +370,10 @@ W: http://atmelwlandriver.sourceforge.net/
S: Maintained
AUDIT SUBSYSTEM
L: linux-audit@redhat.com (subscribers-only)
P: David Woodhouse
M: dwmw2@infradead.org
L: linux-audit@redhat.com
W: http://people.redhat.com/sgrubb/audit/
S: Maintained
AX.25 NETWORK LAYER
...
...
arch/ppc64/kernel/asm-offsets.c
View file @
5d54e69c
...
...
@@ -68,6 +68,7 @@ int main(void)
DEFINE
(
THREAD_USED_VR
,
offsetof
(
struct
thread_struct
,
used_vr
));
#endif
/* CONFIG_ALTIVEC */
DEFINE
(
MM
,
offsetof
(
struct
task_struct
,
mm
));
DEFINE
(
AUDITCONTEXT
,
offsetof
(
struct
task_struct
,
audit_context
));
DEFINE
(
DCACHEL1LINESIZE
,
offsetof
(
struct
ppc64_caches
,
dline_size
));
DEFINE
(
DCACHEL1LOGLINESIZE
,
offsetof
(
struct
ppc64_caches
,
log_dline_size
));
...
...
arch/ppc64/kernel/entry.S
View file @
5d54e69c
...
...
@@ -276,12 +276,22 @@ _GLOBAL(ppc64_rt_sigsuspend)
_GLOBAL
(
ppc32_rt_sigsuspend
)
bl
.
save_nvgprs
bl
.
sys32_rt_sigsuspend
/
*
If
sigsuspend
()
returns
zero
,
we
are
going
into
a
signal
handler
*/
70
:
cmpdi
0
,
r3
,
0
beq
.
ret_from_except
/
*
If
it
returned
-
EINTR
,
we
need
to
return
via
syscall_exit
to
set
/
*
If
it
returned
an
error
,
we
need
to
return
via
syscall_exit
to
set
the
SO
bit
in
cr0
and
potentially
stop
for
ptrace
.
*/
b
syscall_exit
bne
syscall_exit
/
*
If
sigsuspend
()
returns
zero
,
we
are
going
into
a
signal
handler
.
We
may
need
to
call
audit_syscall_exit
()
to
mark
the
exit
from
sigsuspend
()
*/
#ifdef CONFIG_AUDIT
ld
r3
,
PACACURRENT
(
r13
)
ld
r4
,
AUDITCONTEXT
(
r3
)
cmpdi
0
,
r4
,
0
beq
.
ret_from_except
/*
No
audit_context
:
Leave
immediately
.
*/
li
r4
,
2
/*
AUDITSC_FAILURE
*/
li
r5
,-
4
/*
It
's always -EINTR */
bl
.
audit_syscall_exit
#endif
b
.
ret_from_except
_GLOBAL
(
ppc_fork
)
bl
.
save_nvgprs
...
...
fs/namei.c
View file @
5d54e69c
...
...
@@ -1048,7 +1048,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
out:
if
(
unlikely
(
current
->
audit_context
&&
nd
&&
nd
->
dentry
&&
nd
->
dentry
->
d_inode
))
audit_inode
(
name
,
nd
->
dentry
->
d_inode
);
audit_inode
(
name
,
nd
->
dentry
->
d_inode
,
flags
);
return
retval
;
}
...
...
include/linux/audit.h
View file @
5d54e69c
...
...
@@ -51,7 +51,8 @@
#define AUDIT_WATCH_LIST 1009
/* List all file/dir watches */
#define AUDIT_SIGNAL_INFO 1010
/* Get info about sender of signal to auditd */
#define AUDIT_FIRST_USER_MSG 1100
/* Userspace messages uninteresting to kernel */
#define AUDIT_FIRST_USER_MSG 1100
/* Userspace messages mostly uninteresting to kernel */
#define AUDIT_USER_AVC 1107
/* We filter this differently */
#define AUDIT_LAST_USER_MSG 1199
#define AUDIT_DAEMON_START 1200
/* Daemon startup record */
...
...
@@ -75,10 +76,15 @@
#define AUDIT_KERNEL 2000
/* Asynchronous audit record. NOT A REQUEST. */
/* Rule flags */
#define AUDIT_PER_TASK 0x01
/* Apply rule at task creation (not syscall) */
#define AUDIT_AT_ENTRY 0x02
/* Apply rule at syscall entry */
#define AUDIT_AT_EXIT 0x04
/* Apply rule at syscall exit */
#define AUDIT_PREPEND 0x10
/* Prepend to front of list */
#define AUDIT_FILTER_USER 0x00
/* Apply rule to user-generated messages */
#define AUDIT_FILTER_TASK 0x01
/* Apply rule at task creation (not syscall) */
#define AUDIT_FILTER_ENTRY 0x02
/* Apply rule at syscall entry */
#define AUDIT_FILTER_WATCH 0x03
/* Apply rule to file system watches */
#define AUDIT_FILTER_EXIT 0x04
/* Apply rule at syscall exit */
#define AUDIT_NR_FILTERS 5
#define AUDIT_FILTER_PREPEND 0x10
/* Prepend to front of list */
/* Rule actions */
#define AUDIT_NEVER 0
/* Do not build context if rule matches */
...
...
@@ -199,6 +205,7 @@ struct audit_sig_info {
struct
audit_buffer
;
struct
audit_context
;
struct
inode
;
struct
netlink_skb_parms
;
#define AUDITSC_INVALID 0
#define AUDITSC_SUCCESS 1
...
...
@@ -215,7 +222,7 @@ extern void audit_syscall_entry(struct task_struct *task, int arch,
extern
void
audit_syscall_exit
(
struct
task_struct
*
task
,
int
failed
,
long
return_code
);
extern
void
audit_getname
(
const
char
*
name
);
extern
void
audit_putname
(
const
char
*
name
);
extern
void
audit_inode
(
const
char
*
name
,
const
struct
inode
*
inode
);
extern
void
audit_inode
(
const
char
*
name
,
const
struct
inode
*
inode
,
unsigned
flags
);
/* Private API (for audit.c only) */
extern
int
audit_receive_filter
(
int
type
,
int
pid
,
int
uid
,
int
seq
,
...
...
@@ -230,6 +237,7 @@ extern int audit_socketcall(int nargs, unsigned long *args);
extern
int
audit_sockaddr
(
int
len
,
void
*
addr
);
extern
int
audit_avc_path
(
struct
dentry
*
dentry
,
struct
vfsmount
*
mnt
);
extern
void
audit_signal_info
(
int
sig
,
struct
task_struct
*
t
);
extern
int
audit_filter_user
(
struct
netlink_skb_parms
*
cb
,
int
type
);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
...
...
@@ -237,7 +245,7 @@ extern void audit_signal_info(int sig, struct task_struct *t);
#define audit_syscall_exit(t,f,r) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
#define audit_inode(n,i) do { ; } while (0)
#define audit_inode(n,i
,f
) do { ; } while (0)
#define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
...
...
@@ -246,16 +254,17 @@ extern void audit_signal_info(int sig, struct task_struct *t);
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
#define audit_signal_info(s,t) do { ; } while (0)
#define audit_filter_user(cb,t) ({ 1; })
#endif
#ifdef CONFIG_AUDIT
/* These are defined in audit.c */
/* Public API */
extern
void
audit_log
(
struct
audit_context
*
ctx
,
int
type
,
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
3
,
4
)));
extern
void
audit_log
(
struct
audit_context
*
ctx
,
int
gfp_mask
,
int
type
,
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
4
,
5
)));
extern
struct
audit_buffer
*
audit_log_start
(
struct
audit_context
*
ctx
,
int
type
);
extern
struct
audit_buffer
*
audit_log_start
(
struct
audit_context
*
ctx
,
int
gfp_mask
,
int
type
);
extern
void
audit_log_format
(
struct
audit_buffer
*
ab
,
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
2
,
3
)));
...
...
@@ -274,9 +283,10 @@ extern void audit_send_reply(int pid, int seq, int type,
int
done
,
int
multi
,
void
*
payload
,
int
size
);
extern
void
audit_log_lost
(
const
char
*
message
);
extern
struct
semaphore
audit_netlink_sem
;
#else
#define audit_log(c,t,f,...) do { ; } while (0)
#define audit_log_start(c,t) ({ NULL; })
#define audit_log(c,
g,
t,f,...) do { ; } while (0)
#define audit_log_start(c,
g,
t) ({ NULL; })
#define audit_log_vformat(b,f,a) do { ; } while (0)
#define audit_log_format(b,f,...) do { ; } while (0)
#define audit_log_end(b) do { ; } while (0)
...
...
kernel/audit.c
View file @
5d54e69c
...
...
@@ -79,6 +79,8 @@ static int audit_rate_limit;
/* Number of outstanding audit_buffers allowed. */
static
int
audit_backlog_limit
=
64
;
static
int
audit_backlog_wait_time
=
60
*
HZ
;
static
int
audit_backlog_wait_overflow
=
0
;
/* The identity of the user shutting down the audit system. */
uid_t
audit_sig_uid
=
-
1
;
...
...
@@ -106,18 +108,12 @@ static LIST_HEAD(audit_freelist);
static
struct
sk_buff_head
audit_skb_queue
;
static
struct
task_struct
*
kauditd_task
;
static
DECLARE_WAIT_QUEUE_HEAD
(
kauditd_wait
);
/* There are three lists of rules -- one to search at task creation
* time, one to search at syscall entry time, and another to search at
* syscall exit time. */
static
LIST_HEAD
(
audit_tsklist
);
static
LIST_HEAD
(
audit_entlist
);
static
LIST_HEAD
(
audit_extlist
);
static
DECLARE_WAIT_QUEUE_HEAD
(
audit_backlog_wait
);
/* The netlink socket is only to be read by 1 CPU, which lets us assume
* that list additions and deletions never happen simultaneously in
* auditsc.c */
static
DECLARE_MUTEX
(
audit_netlink_sem
);
DECLARE_MUTEX
(
audit_netlink_sem
);
/* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
* audit records. Since printk uses a 1024 byte buffer, this buffer
...
...
@@ -137,6 +133,7 @@ struct audit_buffer {
struct
list_head
list
;
struct
sk_buff
*
skb
;
/* formatted skb ready to send */
struct
audit_context
*
ctx
;
/* NULL or associated context */
int
gfp_mask
;
};
static
void
audit_set_pid
(
struct
audit_buffer
*
ab
,
pid_t
pid
)
...
...
@@ -145,11 +142,6 @@ static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
nlh
->
nlmsg_pid
=
pid
;
}
struct
audit_entry
{
struct
list_head
list
;
struct
audit_rule
rule
;
};
static
void
audit_panic
(
const
char
*
message
)
{
switch
(
audit_failure
)
...
...
@@ -233,7 +225,7 @@ static int audit_set_rate_limit(int limit, uid_t loginuid)
{
int
old
=
audit_rate_limit
;
audit_rate_limit
=
limit
;
audit_log
(
NULL
,
AUDIT_CONFIG_CHANGE
,
audit_log
(
NULL
,
GFP_KERNEL
,
AUDIT_CONFIG_CHANGE
,
"audit_rate_limit=%d old=%d by auid=%u"
,
audit_rate_limit
,
old
,
loginuid
);
return
old
;
...
...
@@ -243,7 +235,7 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid)
{
int
old
=
audit_backlog_limit
;
audit_backlog_limit
=
limit
;
audit_log
(
NULL
,
AUDIT_CONFIG_CHANGE
,
audit_log
(
NULL
,
GFP_KERNEL
,
AUDIT_CONFIG_CHANGE
,
"audit_backlog_limit=%d old=%d by auid=%u"
,
audit_backlog_limit
,
old
,
loginuid
);
return
old
;
...
...
@@ -255,7 +247,7 @@ static int audit_set_enabled(int state, uid_t loginuid)
if
(
state
!=
0
&&
state
!=
1
)
return
-
EINVAL
;
audit_enabled
=
state
;
audit_log
(
NULL
,
AUDIT_CONFIG_CHANGE
,
audit_log
(
NULL
,
GFP_KERNEL
,
AUDIT_CONFIG_CHANGE
,
"audit_enabled=%d old=%d by auid=%u"
,
audit_enabled
,
old
,
loginuid
);
return
old
;
...
...
@@ -269,7 +261,7 @@ static int audit_set_failure(int state, uid_t loginuid)
&&
state
!=
AUDIT_FAIL_PANIC
)
return
-
EINVAL
;
audit_failure
=
state
;
audit_log
(
NULL
,
AUDIT_CONFIG_CHANGE
,
audit_log
(
NULL
,
GFP_KERNEL
,
AUDIT_CONFIG_CHANGE
,
"audit_failure=%d old=%d by auid=%u"
,
audit_failure
,
old
,
loginuid
);
return
old
;
...
...
@@ -281,6 +273,7 @@ int kauditd_thread(void *dummy)
while
(
1
)
{
skb
=
skb_dequeue
(
&
audit_skb_queue
);
wake_up
(
&
audit_backlog_wait
);
if
(
skb
)
{
if
(
audit_pid
)
{
int
err
=
netlink_unicast
(
audit_sock
,
skb
,
audit_pid
,
0
);
...
...
@@ -290,7 +283,7 @@ int kauditd_thread(void *dummy)
audit_pid
=
0
;
}
}
else
{
printk
(
KERN_
ERR
"%s
\n
"
,
skb
->
data
+
NLMSG_SPACE
(
0
));
printk
(
KERN_
NOTICE
"%s
\n
"
,
skb
->
data
+
NLMSG_SPACE
(
0
));
kfree_skb
(
skb
);
}
}
else
{
...
...
@@ -423,7 +416,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if
(
status_get
->
mask
&
AUDIT_STATUS_PID
)
{
int
old
=
audit_pid
;
audit_pid
=
status_get
->
pid
;
audit_log
(
NULL
,
AUDIT_CONFIG_CHANGE
,
audit_log
(
NULL
,
GFP_KERNEL
,
AUDIT_CONFIG_CHANGE
,
"audit_pid=%d old=%d by auid=%u"
,
audit_pid
,
old
,
loginuid
);
}
...
...
@@ -435,15 +428,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
break
;
case
AUDIT_USER
:
case
AUDIT_FIRST_USER_MSG
...
AUDIT_LAST_USER_MSG
:
ab
=
audit_log_start
(
NULL
,
msg_type
);
if
(
!
ab
)
break
;
/* audit_panic has been called */
audit_log_format
(
ab
,
"user pid=%d uid=%u auid=%u"
" msg='%.1024s'"
,
pid
,
uid
,
loginuid
,
(
char
*
)
data
);
audit_set_pid
(
ab
,
pid
);
audit_log_end
(
ab
);
if
(
!
audit_enabled
&&
msg_type
!=
AUDIT_USER_AVC
)
return
0
;
err
=
audit_filter_user
(
&
NETLINK_CB
(
skb
),
msg_type
);
if
(
err
==
1
)
{
err
=
0
;
ab
=
audit_log_start
(
NULL
,
GFP_KERNEL
,
msg_type
);
if
(
ab
)
{
audit_log_format
(
ab
,
"user pid=%d uid=%u auid=%u msg='%.1024s'"
,
pid
,
uid
,
loginuid
,
(
char
*
)
data
);
audit_set_pid
(
ab
,
pid
);
audit_log_end
(
ab
);
}
}
break
;
case
AUDIT_ADD
:
case
AUDIT_DEL
:
...
...
@@ -523,7 +522,7 @@ static int __init audit_init(void)
skb_queue_head_init
(
&
audit_skb_queue
);
audit_initialized
=
1
;
audit_enabled
=
audit_default
;
audit_log
(
NULL
,
AUDIT_KERNEL
,
"initialized"
);
audit_log
(
NULL
,
GFP_KERNEL
,
AUDIT_KERNEL
,
"initialized"
);
return
0
;
}
__initcall
(
audit_init
);
...
...
@@ -561,7 +560,7 @@ static void audit_buffer_free(struct audit_buffer *ab)
}
static
struct
audit_buffer
*
audit_buffer_alloc
(
struct
audit_context
*
ctx
,
in
t
gfp_mask
,
int
type
)
unsigned
int
__nocas
t
gfp_mask
,
int
type
)
{
unsigned
long
flags
;
struct
audit_buffer
*
ab
=
NULL
;
...
...
@@ -587,6 +586,7 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
goto
err
;
ab
->
ctx
=
ctx
;
ab
->
gfp_mask
=
gfp_mask
;
nlh
=
(
struct
nlmsghdr
*
)
skb_put
(
ab
->
skb
,
NLMSG_SPACE
(
0
));
nlh
->
nlmsg_type
=
type
;
nlh
->
nlmsg_flags
=
0
;
...
...
@@ -606,26 +606,27 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
* (timestamp,serial) tuple is unique for each syscall and is live from
* syscall entry to syscall exit.
*
* Atomic values are only guaranteed to be 24-bit, so we count down.
*
* NOTE: Another possibility is to store the formatted records off the
* audit context (for those records that have a context), and emit them
* all at syscall exit. However, this could delay the reporting of
* significant errors until syscall exit (or never, if the system
* halts). */
unsigned
int
audit_serial
(
void
)
{
static
atomic_t
serial
=
ATOMIC_INIT
(
0xffffff
);
unsigned
int
a
,
b
;
static
spinlock_t
serial_lock
=
SPIN_LOCK_UNLOCKED
;
static
unsigned
int
serial
=
0
;
unsigned
long
flags
;
unsigned
int
ret
;
spin_lock_irqsave
(
&
serial_lock
,
flags
);
do
{
a
=
atomic_read
(
&
serial
);
if
(
atomic_dec_and_test
(
&
serial
))
atomic_set
(
&
serial
,
0xffffff
);
b
=
atomic_read
(
&
serial
);
}
while
(
b
!=
a
-
1
);
ret
=
++
serial
;
}
while
(
unlikely
(
!
ret
));
spin_unlock_irqrestore
(
&
serial_lock
,
flags
);
return
0xffffff
-
b
;
return
ret
;
}
static
inline
void
audit_get_stamp
(
struct
audit_context
*
ctx
,
...
...
@@ -645,17 +646,43 @@ static inline void audit_get_stamp(struct audit_context *ctx,
* syscall, then the syscall is marked as auditable and an audit record
* will be written at syscall exit. If there is no associated task, tsk
* should be NULL. */
struct
audit_buffer
*
audit_log_start
(
struct
audit_context
*
ctx
,
int
type
)
struct
audit_buffer
*
audit_log_start
(
struct
audit_context
*
ctx
,
int
gfp_mask
,
int
type
)
{
struct
audit_buffer
*
ab
=
NULL
;
struct
timespec
t
;
unsigned
int
serial
;
int
reserve
;
unsigned
long
timeout_start
=
jiffies
;
if
(
!
audit_initialized
)
return
NULL
;
if
(
audit_backlog_limit
&&
skb_queue_len
(
&
audit_skb_queue
)
>
audit_backlog_limit
)
{
if
(
gfp_mask
&
__GFP_WAIT
)
reserve
=
0
;
else
reserve
=
5
;
/* Allow atomic callers to go up to five
entries over the normal backlog limit */
while
(
audit_backlog_limit
&&
skb_queue_len
(
&
audit_skb_queue
)
>
audit_backlog_limit
+
reserve
)
{
if
(
gfp_mask
&
__GFP_WAIT
&&
audit_backlog_wait_time
&&
time_before
(
jiffies
,
timeout_start
+
audit_backlog_wait_time
))
{
/* Wait for auditd to drain the queue a little */
DECLARE_WAITQUEUE
(
wait
,
current
);
set_current_state
(
TASK_INTERRUPTIBLE
);
add_wait_queue
(
&
audit_backlog_wait
,
&
wait
);
if
(
audit_backlog_limit
&&
skb_queue_len
(
&
audit_skb_queue
)
>
audit_backlog_limit
)
schedule_timeout
(
timeout_start
+
audit_backlog_wait_time
-
jiffies
);
__set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
audit_backlog_wait
,
&
wait
);
continue
;
}
if
(
audit_rate_check
())
printk
(
KERN_WARNING
"audit: audit_backlog=%d > "
...
...
@@ -663,10 +690,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
skb_queue_len
(
&
audit_skb_queue
),
audit_backlog_limit
);
audit_log_lost
(
"backlog limit exceeded"
);
audit_backlog_wait_time
=
audit_backlog_wait_overflow
;
wake_up
(
&
audit_backlog_wait
);
return
NULL
;
}
ab
=
audit_buffer_alloc
(
ctx
,
GFP_ATOMIC
,
type
);
ab
=
audit_buffer_alloc
(
ctx
,
gfp_mask
,
type
);
if
(
!
ab
)
{
audit_log_lost
(
"out of memory in audit_log_start"
);
return
NULL
;
...
...
@@ -690,7 +719,7 @@ static inline int audit_expand(struct audit_buffer *ab, int extra)
{
struct
sk_buff
*
skb
=
ab
->
skb
;
int
ret
=
pskb_expand_head
(
skb
,
skb_headroom
(
skb
),
extra
,
GFP_ATOMIC
);
ab
->
gfp_mask
);
if
(
ret
<
0
)
{
audit_log_lost
(
"out of memory in audit_expand"
);
return
0
;
...
...
@@ -809,7 +838,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
audit_log_format
(
ab
,
" %s"
,
prefix
);
/* We will allow 11 spaces for ' (deleted)' to be appended */
path
=
kmalloc
(
PATH_MAX
+
11
,
GFP_KERNEL
);
path
=
kmalloc
(
PATH_MAX
+
11
,
ab
->
gfp_mask
);
if
(
!
path
)
{
audit_log_format
(
ab
,
"<no memory>"
);
return
;
...
...
@@ -841,7 +870,7 @@ void audit_log_end(struct audit_buffer *ab)
ab
->
skb
=
NULL
;
wake_up_interruptible
(
&
kauditd_wait
);
}
else
{
printk
(
"%s
\n
"
,
ab
->
skb
->
data
+
NLMSG_SPACE
(
0
));
printk
(
KERN_NOTICE
"%s
\n
"
,
ab
->
skb
->
data
+
NLMSG_SPACE
(
0
));
}
}
audit_buffer_free
(
ab
);
...
...
@@ -850,12 +879,13 @@ void audit_log_end(struct audit_buffer *ab)
/* Log an audit record. This is a convenience function that calls
* audit_log_start, audit_log_vformat, and audit_log_end. It may be
* called in any context. */
void
audit_log
(
struct
audit_context
*
ctx
,
int
type
,
const
char
*
fmt
,
...)
void
audit_log
(
struct
audit_context
*
ctx
,
int
gfp_mask
,
int
type
,
const
char
*
fmt
,
...)
{
struct
audit_buffer
*
ab
;
va_list
args
;
ab
=
audit_log_start
(
ctx
,
type
);
ab
=
audit_log_start
(
ctx
,
gfp_mask
,
type
);
if
(
ab
)
{
va_start
(
args
,
fmt
);
audit_log_vformat
(
ab
,
fmt
,
args
);
...
...
kernel/auditsc.c
View file @
5d54e69c
...
...
@@ -39,6 +39,9 @@
#include <linux/audit.h>
#include <linux/personality.h>
#include <linux/time.h>
#include <linux/kthread.h>
#include <linux/netlink.h>
#include <linux/compiler.h>
#include <asm/unistd.h>
/* 0 = no checking
...
...
@@ -95,6 +98,7 @@ struct audit_names {
uid_t
uid
;
gid_t
gid
;
dev_t
rdev
;
unsigned
flags
;
};
struct
audit_aux_data
{
...
...
@@ -167,9 +171,16 @@ struct audit_context {
/* There are three lists of rules -- one to search at task creation
* time, one to search at syscall entry time, and another to search at
* syscall exit time. */
static
LIST_HEAD
(
audit_tsklist
);
static
LIST_HEAD
(
audit_entlist
);
static
LIST_HEAD
(
audit_extlist
);
static
struct
list_head
audit_filter_list
[
AUDIT_NR_FILTERS
]
=
{
LIST_HEAD_INIT
(
audit_filter_list
[
0
]),
LIST_HEAD_INIT
(
audit_filter_list
[
1
]),
LIST_HEAD_INIT
(
audit_filter_list
[
2
]),
LIST_HEAD_INIT
(
audit_filter_list
[
3
]),
LIST_HEAD_INIT
(
audit_filter_list
[
4
]),
#if AUDIT_NR_FILTERS != 5
#error Fix audit_filter_list initialiser
#endif
};
struct
audit_entry
{
struct
list_head
list
;
...
...
@@ -179,9 +190,36 @@ struct audit_entry {
extern
int
audit_pid
;
/* Copy rule from user-space to kernel-space. Called from
* audit_add_rule during AUDIT_ADD. */
static
inline
int
audit_copy_rule
(
struct
audit_rule
*
d
,
struct
audit_rule
*
s
)
{
int
i
;
if
(
s
->
action
!=
AUDIT_NEVER
&&
s
->
action
!=
AUDIT_POSSIBLE
&&
s
->
action
!=
AUDIT_ALWAYS
)
return
-
1
;
if
(
s
->
field_count
<
0
||
s
->
field_count
>
AUDIT_MAX_FIELDS
)
return
-
1
;
if
((
s
->
flags
&
~
AUDIT_FILTER_PREPEND
)
>=
AUDIT_NR_FILTERS
)
return
-
1
;
d
->
flags
=
s
->
flags
;
d
->
action
=
s
->
action
;
d
->
field_count
=
s
->
field_count
;
for
(
i
=
0
;
i
<
d
->
field_count
;
i
++
)
{
d
->
fields
[
i
]
=
s
->
fields
[
i
];
d
->
values
[
i
]
=
s
->
values
[
i
];
}
for
(
i
=
0
;
i
<
AUDIT_BITMASK_SIZE
;
i
++
)
d
->
mask
[
i
]
=
s
->
mask
[
i
];
return
0
;
}
/* Check to see if two rules are identical. It is called from
* audit_add_rule during AUDIT_ADD and
* audit_del_rule during AUDIT_DEL. */
static
int
audit_compare_rule
(
struct
audit_rule
*
a
,
struct
audit_rule
*
b
)
static
in
line
in
t
audit_compare_rule
(
struct
audit_rule
*
a
,
struct
audit_rule
*
b
)
{
int
i
;
...
...
@@ -210,19 +248,37 @@ static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
/* Note that audit_add_rule and audit_del_rule are called via
* audit_receive() in audit.c, and are protected by
* audit_netlink_sem. */
static
inline
int
audit_add_rule
(
struct
audit_
entry
*
entry
,
struct
list_head
*
list
)
static
inline
int
audit_add_rule
(
struct
audit_
rule
*
rule
,
struct
list_head
*
list
)
{
if
(
entry
->
rule
.
flags
&
AUDIT_PREPEND
)
{
entry
->
rule
.
flags
&=
~
AUDIT_PREPEND
;
struct
audit_entry
*
entry
;
/* Do not use the _rcu iterator here, since this is the only
* addition routine. */
list_for_each_entry
(
entry
,
list
,
list
)
{
if
(
!
audit_compare_rule
(
rule
,
&
entry
->
rule
))
{
return
-
EEXIST
;
}
}
if
(
!
(
entry
=
kmalloc
(
sizeof
(
*
entry
),
GFP_KERNEL
)))
return
-
ENOMEM
;
if
(
audit_copy_rule
(
&
entry
->
rule
,
rule
))
{
kfree
(
entry
);
return
-
EINVAL
;
}
if
(
entry
->
rule
.
flags
&
AUDIT_FILTER_PREPEND
)
{
entry
->
rule
.
flags
&=
~
AUDIT_FILTER_PREPEND
;
list_add_rcu
(
&
entry
->
list
,
list
);
}
else
{
list_add_tail_rcu
(
&
entry
->
list
,
list
);
}
return
0
;
}
static
void
audit_free_rule
(
struct
rcu_head
*
head
)
static
inline
void
audit_free_rule
(
struct
rcu_head
*
head
)
{
struct
audit_entry
*
e
=
container_of
(
head
,
struct
audit_entry
,
rcu
);
kfree
(
e
);
...
...
@@ -245,82 +301,82 @@ static inline int audit_del_rule(struct audit_rule *rule,
return
0
;
}
}
return
-
E
FAUL
T
;
/* No matching rule */
return
-
E
NOEN
T
;
/* No matching rule */
}
/* Copy rule from user-space to kernel-space. Called during
* AUDIT_ADD. */
static
int
audit_copy_rule
(
struct
audit_rule
*
d
,
struct
audit_rule
*
s
)
static
int
audit_list_rules
(
void
*
_dest
)
{
int
pid
,
seq
;
int
*
dest
=
_dest
;
struct
audit_entry
*
entry
;
int
i
;
if
(
s
->
action
!=
AUDIT_NEVER
&&
s
->
action
!=
AUDIT_POSSIBLE
&&
s
->
action
!=
AUDIT_ALWAYS
)
return
-
1
;
if
(
s
->
field_count
<
0
||
s
->
field_count
>
AUDIT_MAX_FIELDS
)
return
-
1
;
pid
=
dest
[
0
];
seq
=
dest
[
1
];
kfree
(
dest
);
d
->
flags
=
s
->
flags
;
d
->
action
=
s
->
action
;
d
->
field_count
=
s
->
field_count
;
for
(
i
=
0
;
i
<
d
->
field_count
;
i
++
)
{
d
->
fields
[
i
]
=
s
->
fields
[
i
];
d
->
values
[
i
]
=
s
->
values
[
i
];
down
(
&
audit_netlink_sem
);
/* The *_rcu iterators not needed here because we are
always called with audit_netlink_sem held. */
for
(
i
=
0
;
i
<
AUDIT_NR_FILTERS
;
i
++
)
{
list_for_each_entry
(
entry
,
&
audit_filter_list
[
i
],
list
)
audit_send_reply
(
pid
,
seq
,
AUDIT_LIST
,
0
,
1
,
&
entry
->
rule
,
sizeof
(
entry
->
rule
));
}
for
(
i
=
0
;
i
<
AUDIT_BITMASK_SIZE
;
i
++
)
d
->
mask
[
i
]
=
s
->
mask
[
i
];
audit_send_reply
(
pid
,
seq
,
AUDIT_LIST
,
1
,
1
,
NULL
,
0
);
up
(
&
audit_netlink_sem
);
return
0
;
}
int
audit_receive_filter
(
int
type
,
int
pid
,
int
uid
,
int
seq
,
void
*
data
,
uid_t
loginuid
)
{
u32
flags
;
struct
audit_entry
*
entry
;
struct
task_struct
*
tsk
;
int
*
dest
;
int
err
=
0
;
unsigned
listnr
;
switch
(
type
)
{
case
AUDIT_LIST
:
/* The *_rcu iterators not needed here because we are
always called with audit_netlink_sem held. */
list_for_each_entry
(
entry
,
&
audit_tsklist
,
list
)
audit_send_reply
(
pid
,
seq
,
AUDIT_LIST
,
0
,
1
,
&
entry
->
rule
,
sizeof
(
entry
->
rule
));
list_for_each_entry
(
entry
,
&
audit_entlist
,
list
)
audit_send_reply
(
pid
,
seq
,
AUDIT_LIST
,
0
,
1
,
&
entry
->
rule
,
sizeof
(
entry
->
rule
));
list_for_each_entry
(
entry
,
&
audit_extlist
,
list
)
audit_send_reply
(
pid
,
seq
,
AUDIT_LIST
,
0
,
1
,
&
entry
->
rule
,
sizeof
(
entry
->
rule
));
audit_send_reply
(
pid
,
seq
,
AUDIT_LIST
,
1
,
1
,
NULL
,
0
);
/* We can't just spew out the rules here because we might fill
* the available socket buffer space and deadlock waiting for
* auditctl to read from it... which isn't ever going to
* happen if we're actually running in the context of auditctl
* trying to _send_ the stuff */
dest
=
kmalloc
(
2
*
sizeof
(
int
),
GFP_KERNEL
);
if
(
!
dest
)
return
-
ENOMEM
;
dest
[
0
]
=
pid
;
dest
[
1
]
=
seq
;
tsk
=
kthread_run
(
audit_list_rules
,
dest
,
"audit_list_rules"
);
if
(
IS_ERR
(
tsk
))
{
kfree
(
dest
);
err
=
PTR_ERR
(
tsk
);
}
break
;
case
AUDIT_ADD
:
if
(
!
(
entry
=
kmalloc
(
sizeof
(
*
entry
),
GFP_KERNEL
)))
return
-
ENOMEM
;
if
(
audit_copy_rule
(
&
entry
->
rule
,
data
))
{
kfree
(
entry
);
listnr
=
((
struct
audit_rule
*
)
data
)
->
flags
&
~
AUDIT_FILTER_PREPEND
;
if
(
listnr
>=
AUDIT_NR_FILTERS
)
return
-
EINVAL
;
}
flags
=
entry
->
rule
.
flags
;
if
(
!
err
&&
(
flags
&
AUDIT_PER_TASK
))
err
=
audit_add_rule
(
entry
,
&
audit_tsklist
);
if
(
!
err
&&
(
flags
&
AUDIT_AT_ENTRY
))
err
=
audit_add_rule
(
entry
,
&
audit_entlist
);
if
(
!
err
&&
(
flags
&
AUDIT_AT_EXIT
))
err
=
audit_add_rule
(
entry
,
&
audit_extlist
);
audit_log
(
NULL
,
AUDIT_CONFIG_CHANGE
,
"auid=%u added an audit rule
\n
"
,
loginuid
);
err
=
audit_add_rule
(
data
,
&
audit_filter_list
[
listnr
]);
if
(
!
err
)
audit_log
(
NULL
,
GFP_KERNEL
,
AUDIT_CONFIG_CHANGE
,
"auid=%u added an audit rule
\n
"
,
loginuid
);
break
;
case
AUDIT_DEL
:
flags
=
((
struct
audit_rule
*
)
data
)
->
flags
;
if
(
!
err
&&
(
flags
&
AUDIT_PER_TASK
))
err
=
audit_del_rule
(
data
,
&
audit_tsklist
);
if
(
!
err
&&
(
flags
&
AUDIT_AT_ENTRY
))
err
=
audit_del_rule
(
data
,
&
audit_entlist
);
if
(
!
err
&&
(
flags
&
AUDIT_AT_EXIT
))
err
=
audit_del_rule
(
data
,
&
audit_extlist
);
audit_log
(
NULL
,
AUDIT_CONFIG_CHANGE
,
"auid=%u removed an audit rule
\n
"
,
loginuid
);
listnr
=
((
struct
audit_rule
*
)
data
)
->
flags
&
~
AUDIT_FILTER_PREPEND
;
if
(
listnr
>=
AUDIT_NR_FILTERS
)
return
-
EINVAL
;
err
=
audit_del_rule
(
data
,
&
audit_filter_list
[
listnr
]);
if
(
!
err
)
audit_log
(
NULL
,
GFP_KERNEL
,
AUDIT_CONFIG_CHANGE
,
"auid=%u removed an audit rule
\n
"
,
loginuid
);
break
;
default:
return
-
EINVAL
;
...
...
@@ -384,8 +440,12 @@ static int audit_filter_rules(struct task_struct *tsk,
result
=
(
ctx
->
return_code
==
value
);
break
;
case
AUDIT_SUCCESS
:
if
(
ctx
&&
ctx
->
return_valid
)
result
=
(
ctx
->
return_valid
==
AUDITSC_SUCCESS
);
if
(
ctx
&&
ctx
->
return_valid
)
{
if
(
value
)
result
=
(
ctx
->
return_valid
==
AUDITSC_SUCCESS
);
else
result
=
(
ctx
->
return_valid
==
AUDITSC_FAILURE
);
}
break
;
case
AUDIT_DEVMAJOR
:
if
(
ctx
)
{
...
...
@@ -454,7 +514,7 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
enum
audit_state
state
;
rcu_read_lock
();
list_for_each_entry_rcu
(
e
,
&
audit_
tsklist
,
list
)
{
list_for_each_entry_rcu
(
e
,
&
audit_
filter_list
[
AUDIT_FILTER_TASK
]
,
list
)
{
if
(
audit_filter_rules
(
tsk
,
&
e
->
rule
,
NULL
,
&
state
))
{
rcu_read_unlock
();
return
state
;
...
...
@@ -472,22 +532,86 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
static
enum
audit_state
audit_filter_syscall
(
struct
task_struct
*
tsk
,
struct
audit_context
*
ctx
,
struct
list_head
*
list
)
{
struct
audit_entry
*
e
;
enum
audit_state
state
;
if
(
audit_pid
&&
tsk
->
tgid
==
audit_pid
)
return
AUDIT_DISABLED
;
rcu_read_lock
();
if
(
!
list_empty
(
list
))
{
int
word
=
AUDIT_WORD
(
ctx
->
major
);
int
bit
=
AUDIT_BIT
(
ctx
->
major
);
list_for_each_entry_rcu
(
e
,
list
,
list
)
{
if
((
e
->
rule
.
mask
[
word
]
&
bit
)
==
bit
&&
audit_filter_rules
(
tsk
,
&
e
->
rule
,
ctx
,
&
state
))
{
rcu_read_unlock
();
return
state
;
}
}
}
rcu_read_unlock
();
return
AUDIT_BUILD_CONTEXT
;
}
static
int
audit_filter_user_rules
(
struct
netlink_skb_parms
*
cb
,
struct
audit_rule
*
rule
,
enum
audit_state
*
state
)
{
int
i
;
for
(
i
=
0
;
i
<
rule
->
field_count
;
i
++
)
{
u32
field
=
rule
->
fields
[
i
]
&
~
AUDIT_NEGATE
;
u32
value
=
rule
->
values
[
i
];
int
result
=
0
;
switch
(
field
)
{
case
AUDIT_PID
:
result
=
(
cb
->
creds
.
pid
==
value
);
break
;
case
AUDIT_UID
:
result
=
(
cb
->
creds
.
uid
==
value
);
break
;
case
AUDIT_GID
:
result
=
(
cb
->
creds
.
gid
==
value
);
break
;
case
AUDIT_LOGINUID
:
result
=
(
cb
->
loginuid
==
value
);
break
;
}
if
(
rule
->
fields
[
i
]
&
AUDIT_NEGATE
)
result
=
!
result
;
if
(
!
result
)
return
0
;
}
switch
(
rule
->
action
)
{
case
AUDIT_NEVER
:
*
state
=
AUDIT_DISABLED
;
break
;
case
AUDIT_POSSIBLE
:
*
state
=
AUDIT_BUILD_CONTEXT
;
break
;
case
AUDIT_ALWAYS
:
*
state
=
AUDIT_RECORD_CONTEXT
;
break
;
}
return
1
;
}
int
audit_filter_user
(
struct
netlink_skb_parms
*
cb
,
int
type
)
{
struct
audit_entry
*
e
;
enum
audit_state
state
;
int
word
=
AUDIT_WORD
(
ctx
->
major
);
int
bit
=
AUDIT_BIT
(
ctx
->
major
);
int
ret
=
1
;
rcu_read_lock
();
list_for_each_entry_rcu
(
e
,
list
,
list
)
{
if
(
(
e
->
rule
.
mask
[
word
]
&
bit
)
==
bit
&&
audit_filter_rules
(
tsk
,
&
e
->
rule
,
ctx
,
&
state
))
{
rcu_read_unlock
()
;
return
state
;
list_for_each_entry_rcu
(
e
,
&
audit_filter_list
[
AUDIT_FILTER_USER
]
,
list
)
{
if
(
audit_filter_user_rules
(
cb
,
&
e
->
rule
,
&
state
))
{
if
(
state
==
AUDIT_DISABLED
)
ret
=
0
;
break
;
}
}
rcu_read_unlock
();
return
AUDIT_BUILD_CONTEXT
;
return
ret
;
/* Audit by default */
}
/* This should be called with task_lock() held. */
...
...
@@ -504,7 +628,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
if
(
context
->
in_syscall
&&
!
context
->
auditable
)
{
enum
audit_state
state
;
state
=
audit_filter_syscall
(
tsk
,
context
,
&
audit_
extlist
);
state
=
audit_filter_syscall
(
tsk
,
context
,
&
audit_
filter_list
[
AUDIT_FILTER_EXIT
]
);
if
(
state
==
AUDIT_RECORD_CONTEXT
)
context
->
auditable
=
1
;
}
...
...
@@ -679,13 +803,13 @@ static void audit_log_task_info(struct audit_buffer *ab)
up_read
(
&
mm
->
mmap_sem
);
}
static
void
audit_log_exit
(
struct
audit_context
*
context
)
static
void
audit_log_exit
(
struct
audit_context
*
context
,
unsigned
int
gfp_mask
)
{
int
i
;
struct
audit_buffer
*
ab
;
struct
audit_aux_data
*
aux
;
ab
=
audit_log_start
(
context
,
AUDIT_SYSCALL
);
ab
=
audit_log_start
(
context
,
gfp_mask
,
AUDIT_SYSCALL
);
if
(
!
ab
)
return
;
/* audit_panic has been called */
audit_log_format
(
ab
,
"arch=%x syscall=%d"
,
...
...
@@ -717,7 +841,7 @@ static void audit_log_exit(struct audit_context *context)
for
(
aux
=
context
->
aux
;
aux
;
aux
=
aux
->
next
)
{
ab
=
audit_log_start
(
context
,
aux
->
type
);
ab
=
audit_log_start
(
context
,
GFP_KERNEL
,
aux
->
type
);
if
(
!
ab
)
continue
;
/* audit_panic has been called */
...
...
@@ -754,14 +878,14 @@ static void audit_log_exit(struct audit_context *context)
}
if
(
context
->
pwd
&&
context
->
pwdmnt
)
{
ab
=
audit_log_start
(
context
,
AUDIT_CWD
);
ab
=
audit_log_start
(
context
,
GFP_KERNEL
,
AUDIT_CWD
);
if
(
ab
)
{
audit_log_d_path
(
ab
,
"cwd="
,
context
->
pwd
,
context
->
pwdmnt
);
audit_log_end
(
ab
);
}
}
for
(
i
=
0
;
i
<
context
->
name_count
;
i
++
)
{
ab
=
audit_log_start
(
context
,
AUDIT_PATH
);
ab
=
audit_log_start
(
context
,
GFP_KERNEL
,
AUDIT_PATH
);
if
(
!
ab
)
continue
;
/* audit_panic has been called */
...
...
@@ -770,6 +894,8 @@ static void audit_log_exit(struct audit_context *context)
audit_log_format
(
ab
,
" name="
);
audit_log_untrustedstring
(
ab
,
context
->
names
[
i
].
name
);
}
audit_log_format
(
ab
,
" flags=%x
\n
"
,
context
->
names
[
i
].
flags
);
if
(
context
->
names
[
i
].
ino
!=
(
unsigned
long
)
-
1
)
audit_log_format
(
ab
,
" inode=%lu dev=%02x:%02x mode=%#o"
" ouid=%u ogid=%u rdev=%02x:%02x"
,
...
...
@@ -799,9 +925,11 @@ void audit_free(struct task_struct *tsk)
return
;
/* Check for system calls that do not go through the exit
* function (e.g., exit_group), then free context block. */
if
(
context
->
in_syscall
&&
context
->
auditable
&&
context
->
pid
!=
audit_pid
)
audit_log_exit
(
context
);
* function (e.g., exit_group), then free context block.
* We use GFP_ATOMIC here because we might be doing this
* in the context of the idle thread */
if
(
context
->
in_syscall
&&
context
->
auditable
)
audit_log_exit
(
context
,
GFP_ATOMIC
);
audit_free_context
(
context
);
}
...
...
@@ -876,11 +1004,11 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
state
=
context
->
state
;
if
(
state
==
AUDIT_SETUP_CONTEXT
||
state
==
AUDIT_BUILD_CONTEXT
)
state
=
audit_filter_syscall
(
tsk
,
context
,
&
audit_
entlist
);
state
=
audit_filter_syscall
(
tsk
,
context
,
&
audit_
filter_list
[
AUDIT_FILTER_ENTRY
]
);
if
(
likely
(
state
==
AUDIT_DISABLED
))
return
;
context
->
serial
=
audit_serial
()
;
context
->
serial
=
0
;
context
->
ctime
=
CURRENT_TIME
;
context
->
in_syscall
=
1
;
context
->
auditable
=
!!
(
state
==
AUDIT_RECORD_CONTEXT
);
...
...
@@ -903,10 +1031,10 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
/* Not having a context here is ok, since the parent may have
* called __put_task_struct. */
if
(
likely
(
!
context
))
return
;
goto
out
;
if
(
context
->
in_syscall
&&
context
->
auditable
&&
context
->
pid
!=
audit_pid
)
audit_log_exit
(
context
);
if
(
context
->
in_syscall
&&
context
->
auditable
)
audit_log_exit
(
context
,
GFP_KERNEL
);
context
->
in_syscall
=
0
;
context
->
auditable
=
0
;
...
...
@@ -919,9 +1047,9 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
}
else
{
audit_free_names
(
context
);
audit_free_aux
(
context
);
audit_zero_context
(
context
,
context
->
state
);
tsk
->
audit_context
=
context
;
}
out:
put_task_struct
(
tsk
);
}
...
...
@@ -996,7 +1124,7 @@ void audit_putname(const char *name)
/* Store the inode and device from a lookup. Called from
* fs/namei.c:path_lookup(). */
void
audit_inode
(
const
char
*
name
,
const
struct
inode
*
inode
)
void
audit_inode
(
const
char
*
name
,
const
struct
inode
*
inode
,
unsigned
flags
)
{
int
idx
;
struct
audit_context
*
context
=
current
->
audit_context
;
...
...
@@ -1022,17 +1150,20 @@ void audit_inode(const char *name, const struct inode *inode)
++
context
->
ino_count
;
#endif
}
context
->
names
[
idx
].
ino
=
inode
->
i_ino
;
context
->
names
[
idx
].
dev
=
inode
->
i_sb
->
s_dev
;
context
->
names
[
idx
].
mode
=
inode
->
i_mode
;
context
->
names
[
idx
].
uid
=
inode
->
i_uid
;
context
->
names
[
idx
].
gid
=
inode
->
i_gid
;
context
->
names
[
idx
].
rdev
=
inode
->
i_rdev
;
context
->
names
[
idx
].
flags
=
flags
;
context
->
names
[
idx
].
ino
=
inode
->
i_ino
;
context
->
names
[
idx
].
dev
=
inode
->
i_sb
->
s_dev
;
context
->
names
[
idx
].
mode
=
inode
->
i_mode
;
context
->
names
[
idx
].
uid
=
inode
->
i_uid
;
context
->
names
[
idx
].
gid
=
inode
->
i_gid
;
context
->
names
[
idx
].
rdev
=
inode
->
i_rdev
;
}
void
auditsc_get_stamp
(
struct
audit_context
*
ctx
,
struct
timespec
*
t
,
unsigned
int
*
serial
)
{
if
(
!
ctx
->
serial
)
ctx
->
serial
=
audit_serial
();
t
->
tv_sec
=
ctx
->
ctime
.
tv_sec
;
t
->
tv_nsec
=
ctx
->
ctime
.
tv_nsec
;
*
serial
=
ctx
->
serial
;
...
...
@@ -1044,7 +1175,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
if
(
task
->
audit_context
)
{
struct
audit_buffer
*
ab
;
ab
=
audit_log_start
(
NULL
,
AUDIT_LOGIN
);
ab
=
audit_log_start
(
NULL
,
GFP_KERNEL
,
AUDIT_LOGIN
);
if
(
ab
)
{
audit_log_format
(
ab
,
"login pid=%d uid=%u "
"old auid=%u new auid=%u"
,
...
...
@@ -1153,7 +1284,7 @@ void audit_signal_info(int sig, struct task_struct *t)
extern
pid_t
audit_sig_pid
;
extern
uid_t
audit_sig_uid
;
if
(
unlikely
(
audit_pid
&&
t
->
p
id
==
audit_pid
))
{
if
(
unlikely
(
audit_pid
&&
t
->
tg
id
==
audit_pid
))
{
if
(
sig
==
SIGTERM
||
sig
==
SIGHUP
)
{
struct
audit_context
*
ctx
=
current
->
audit_context
;
audit_sig_pid
=
current
->
pid
;
...
...
security/selinux/avc.c
View file @
5d54e69c
...
...
@@ -242,7 +242,7 @@ void __init avc_init(void)
avc_node_cachep
=
kmem_cache_create
(
"avc_node"
,
sizeof
(
struct
avc_node
),
0
,
SLAB_PANIC
,
NULL
,
NULL
);
audit_log
(
current
->
audit_context
,
AUDIT_KERNEL
,
"AVC INITIALIZED
\n
"
);
audit_log
(
current
->
audit_context
,
GFP_KERNEL
,
AUDIT_KERNEL
,
"AVC INITIALIZED
\n
"
);
}
int
avc_get_hash_stats
(
char
*
page
)
...
...
@@ -550,7 +550,7 @@ void avc_audit(u32 ssid, u32 tsid,
return
;
}
ab
=
audit_log_start
(
current
->
audit_context
,
AUDIT_AVC
);
ab
=
audit_log_start
(
current
->
audit_context
,
GFP_ATOMIC
,
AUDIT_AVC
);
if
(
!
ab
)
return
;
/* audit_panic has been called */
audit_log_format
(
ab
,
"avc: %s "
,
denied
?
"denied"
:
"granted"
);
...
...
security/selinux/hooks.c
View file @
5d54e69c
...
...
@@ -3389,7 +3389,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
err
=
selinux_nlmsg_lookup
(
isec
->
sclass
,
nlh
->
nlmsg_type
,
&
perm
);
if
(
err
)
{
if
(
err
==
-
EINVAL
)
{
audit_log
(
current
->
audit_context
,
AUDIT_SELINUX_ERR
,
audit_log
(
current
->
audit_context
,
GFP_KERNEL
,
AUDIT_SELINUX_ERR
,
"SELinux: unrecognized netlink message"
" type=%hu for sclass=%hu
\n
"
,
nlh
->
nlmsg_type
,
isec
->
sclass
);
...
...
security/selinux/ss/services.c
View file @
5d54e69c
...
...
@@ -381,7 +381,7 @@ static int security_validtrans_handle_fail(struct context *ocontext,
goto
out
;
if
(
context_struct_to_string
(
tcontext
,
&
t
,
&
tlen
)
<
0
)
goto
out
;
audit_log
(
current
->
audit_context
,
AUDIT_SELINUX_ERR
,
audit_log
(
current
->
audit_context
,
GFP_ATOMIC
,
AUDIT_SELINUX_ERR
,
"security_validate_transition: denied for"
" oldcontext=%s newcontext=%s taskcontext=%s tclass=%s"
,
o
,
n
,
t
,
policydb
.
p_class_val_to_name
[
tclass
-
1
]);
...
...
@@ -787,7 +787,7 @@ static int compute_sid_handle_invalid_context(
goto
out
;
if
(
context_struct_to_string
(
newcontext
,
&
n
,
&
nlen
)
<
0
)
goto
out
;
audit_log
(
current
->
audit_context
,
AUDIT_SELINUX_ERR
,
audit_log
(
current
->
audit_context
,
GFP_ATOMIC
,
AUDIT_SELINUX_ERR
,
"security_compute_sid: invalid context %s"
" for scontext=%s"
" tcontext=%s"
...
...
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