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
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