diff options
| -rw-r--r-- | Documentation/filesystems/proc.txt | 7 | ||||
| -rw-r--r-- | drivers/char/tty_audit.c | 19 | ||||
| -rw-r--r-- | fs/proc/base.c | 2 | ||||
| -rw-r--r-- | include/linux/audit.h | 13 | ||||
| -rw-r--r-- | include/linux/init_task.h | 8 | ||||
| -rw-r--r-- | include/linux/sched.h | 4 | ||||
| -rw-r--r-- | kernel/audit.c | 434 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 54 | ||||
| -rw-r--r-- | kernel/auditsc.c | 349 | ||||
| -rw-r--r-- | kernel/sysctl.c | 11 | ||||
| -rw-r--r-- | net/core/dev.c | 15 | ||||
| -rw-r--r-- | net/key/af_key.c | 14 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 2 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 2 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 17 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 5 |
16 files changed, 533 insertions, 423 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 11fe51c036bf..194c8f351320 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
| @@ -1134,13 +1134,6 @@ check the amount of free space (value is in seconds). Default settings are: 4, | |||
| 1134 | resume it if we have a value of 3 or more percent; consider information about | 1134 | resume it if we have a value of 3 or more percent; consider information about |
| 1135 | the amount of free space valid for 30 seconds | 1135 | the amount of free space valid for 30 seconds |
| 1136 | 1136 | ||
| 1137 | audit_argv_kb | ||
| 1138 | ------------- | ||
| 1139 | |||
| 1140 | The file contains a single value denoting the limit on the argv array size | ||
| 1141 | for execve (in KiB). This limit is only applied when system call auditing for | ||
| 1142 | execve is enabled, otherwise the value is ignored. | ||
| 1143 | |||
| 1144 | ctrl-alt-del | 1137 | ctrl-alt-del |
| 1145 | ------------ | 1138 | ------------ |
| 1146 | 1139 | ||
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index d222012c1b0c..bacded0eefab 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c | |||
| @@ -73,6 +73,7 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf) | |||
| 73 | * @tsk with @loginuid. @buf->mutex must be locked. | 73 | * @tsk with @loginuid. @buf->mutex must be locked. |
| 74 | */ | 74 | */ |
| 75 | static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid, | 75 | static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid, |
| 76 | unsigned int sessionid, | ||
| 76 | struct tty_audit_buf *buf) | 77 | struct tty_audit_buf *buf) |
| 77 | { | 78 | { |
| 78 | struct audit_buffer *ab; | 79 | struct audit_buffer *ab; |
| @@ -85,9 +86,9 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid, | |||
| 85 | if (ab) { | 86 | if (ab) { |
| 86 | char name[sizeof(tsk->comm)]; | 87 | char name[sizeof(tsk->comm)]; |
| 87 | 88 | ||
| 88 | audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d " | 89 | audit_log_format(ab, "tty pid=%u uid=%u auid=%u ses=%u " |
| 89 | "minor=%d comm=", tsk->pid, tsk->uid, | 90 | "major=%d minor=%d comm=", tsk->pid, tsk->uid, |
| 90 | loginuid, buf->major, buf->minor); | 91 | loginuid, sessionid, buf->major, buf->minor); |
| 91 | get_task_comm(name, tsk); | 92 | get_task_comm(name, tsk); |
| 92 | audit_log_untrustedstring(ab, name); | 93 | audit_log_untrustedstring(ab, name); |
| 93 | audit_log_format(ab, " data="); | 94 | audit_log_format(ab, " data="); |
| @@ -105,8 +106,9 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid, | |||
| 105 | */ | 106 | */ |
| 106 | static void tty_audit_buf_push_current(struct tty_audit_buf *buf) | 107 | static void tty_audit_buf_push_current(struct tty_audit_buf *buf) |
| 107 | { | 108 | { |
| 108 | tty_audit_buf_push(current, audit_get_loginuid(current->audit_context), | 109 | uid_t auid = audit_get_loginuid(current); |
| 109 | buf); | 110 | unsigned int sessionid = audit_get_sessionid(current); |
| 111 | tty_audit_buf_push(current, auid, sessionid, buf); | ||
| 110 | } | 112 | } |
| 111 | 113 | ||
| 112 | /** | 114 | /** |
| @@ -152,6 +154,11 @@ void tty_audit_fork(struct signal_struct *sig) | |||
| 152 | void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid) | 154 | void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid) |
| 153 | { | 155 | { |
| 154 | struct tty_audit_buf *buf; | 156 | struct tty_audit_buf *buf; |
| 157 | /* FIXME I think this is correct. Check against netlink once that is | ||
| 158 | * I really need to read this code more closely. But that's for | ||
| 159 | * another patch. | ||
| 160 | */ | ||
| 161 | unsigned int sessionid = audit_get_sessionid(tsk); | ||
| 155 | 162 | ||
| 156 | spin_lock_irq(&tsk->sighand->siglock); | 163 | spin_lock_irq(&tsk->sighand->siglock); |
| 157 | buf = tsk->signal->tty_audit_buf; | 164 | buf = tsk->signal->tty_audit_buf; |
| @@ -162,7 +169,7 @@ void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid) | |||
| 162 | return; | 169 | return; |
| 163 | 170 | ||
| 164 | mutex_lock(&buf->mutex); | 171 | mutex_lock(&buf->mutex); |
| 165 | tty_audit_buf_push(tsk, loginuid, buf); | 172 | tty_audit_buf_push(tsk, loginuid, sessionid, buf); |
| 166 | mutex_unlock(&buf->mutex); | 173 | mutex_unlock(&buf->mutex); |
| 167 | 174 | ||
| 168 | tty_audit_buf_put(buf); | 175 | tty_audit_buf_put(buf); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 9fa9708cc715..33537487f5ab 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -984,7 +984,7 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf, | |||
| 984 | if (!task) | 984 | if (!task) |
| 985 | return -ESRCH; | 985 | return -ESRCH; |
| 986 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", | 986 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", |
| 987 | audit_get_loginuid(task->audit_context)); | 987 | audit_get_loginuid(task)); |
| 988 | put_task_struct(task); | 988 | put_task_struct(task); |
| 989 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 989 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
| 990 | } | 990 | } |
diff --git a/include/linux/audit.h b/include/linux/audit.h index bdd6f5de5fc4..97153027207a 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -98,6 +98,7 @@ | |||
| 98 | #define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */ | 98 | #define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */ |
| 99 | #define AUDIT_OBJ_PID 1318 /* ptrace target */ | 99 | #define AUDIT_OBJ_PID 1318 /* ptrace target */ |
| 100 | #define AUDIT_TTY 1319 /* Input on an administrative TTY */ | 100 | #define AUDIT_TTY 1319 /* Input on an administrative TTY */ |
| 101 | #define AUDIT_EOE 1320 /* End of multi-record event */ | ||
| 101 | 102 | ||
| 102 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ | 103 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
| 103 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ | 104 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
| @@ -409,7 +410,8 @@ extern unsigned int audit_serial(void); | |||
| 409 | extern void auditsc_get_stamp(struct audit_context *ctx, | 410 | extern void auditsc_get_stamp(struct audit_context *ctx, |
| 410 | struct timespec *t, unsigned int *serial); | 411 | struct timespec *t, unsigned int *serial); |
| 411 | extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); | 412 | extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); |
| 412 | extern uid_t audit_get_loginuid(struct audit_context *ctx); | 413 | #define audit_get_loginuid(t) ((t)->loginuid) |
| 414 | #define audit_get_sessionid(t) ((t)->sessionid) | ||
| 413 | extern void audit_log_task_context(struct audit_buffer *ab); | 415 | extern void audit_log_task_context(struct audit_buffer *ab); |
| 414 | extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp); | 416 | extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp); |
| 415 | extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); | 417 | extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); |
| @@ -488,7 +490,8 @@ extern int audit_signals; | |||
| 488 | #define audit_inode_child(d,i,p) do { ; } while (0) | 490 | #define audit_inode_child(d,i,p) do { ; } while (0) |
| 489 | #define audit_core_dumps(i) do { ; } while (0) | 491 | #define audit_core_dumps(i) do { ; } while (0) |
| 490 | #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) | 492 | #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) |
| 491 | #define audit_get_loginuid(c) ({ -1; }) | 493 | #define audit_get_loginuid(t) (-1) |
| 494 | #define audit_get_sessionid(t) (-1) | ||
| 492 | #define audit_log_task_context(b) do { ; } while (0) | 495 | #define audit_log_task_context(b) do { ; } while (0) |
| 493 | #define audit_ipc_obj(i) ({ 0; }) | 496 | #define audit_ipc_obj(i) ({ 0; }) |
| 494 | #define audit_ipc_set_perm(q,u,g,m) ({ 0; }) | 497 | #define audit_ipc_set_perm(q,u,g,m) ({ 0; }) |
| @@ -522,9 +525,11 @@ extern void audit_log_end(struct audit_buffer *ab); | |||
| 522 | extern void audit_log_hex(struct audit_buffer *ab, | 525 | extern void audit_log_hex(struct audit_buffer *ab, |
| 523 | const unsigned char *buf, | 526 | const unsigned char *buf, |
| 524 | size_t len); | 527 | size_t len); |
| 525 | extern const char * audit_log_untrustedstring(struct audit_buffer *ab, | 528 | extern int audit_string_contains_control(const char *string, |
| 529 | size_t len); | ||
| 530 | extern void audit_log_untrustedstring(struct audit_buffer *ab, | ||
| 526 | const char *string); | 531 | const char *string); |
| 527 | extern const char * audit_log_n_untrustedstring(struct audit_buffer *ab, | 532 | extern void audit_log_n_untrustedstring(struct audit_buffer *ab, |
| 528 | size_t n, | 533 | size_t n, |
| 529 | const char *string); | 534 | const char *string); |
| 530 | extern void audit_log_d_path(struct audit_buffer *ab, | 535 | extern void audit_log_d_path(struct audit_buffer *ab, |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index e6b3f7080679..f42663eaf655 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
| @@ -114,6 +114,13 @@ extern struct group_info init_groups; | |||
| 114 | .pid = &init_struct_pid, \ | 114 | .pid = &init_struct_pid, \ |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | #ifdef CONFIG_AUDITSYSCALL | ||
| 118 | #define INIT_IDS \ | ||
| 119 | .loginuid = -1, \ | ||
| 120 | .sessionid = -1, | ||
| 121 | #else | ||
| 122 | #define INIT_IDS | ||
| 123 | #endif | ||
| 117 | /* | 124 | /* |
| 118 | * INIT_TASK is used to set up the first task table, touch at | 125 | * INIT_TASK is used to set up the first task table, touch at |
| 119 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 126 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
| @@ -173,6 +180,7 @@ extern struct group_info init_groups; | |||
| 173 | [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ | 180 | [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ |
| 174 | }, \ | 181 | }, \ |
| 175 | .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \ | 182 | .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \ |
| 183 | INIT_IDS \ | ||
| 176 | INIT_TRACE_IRQFLAGS \ | 184 | INIT_TRACE_IRQFLAGS \ |
| 177 | INIT_LOCKDEP \ | 185 | INIT_LOCKDEP \ |
| 178 | } | 186 | } |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 6c333579d9da..af6947e69b40 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1139,6 +1139,10 @@ struct task_struct { | |||
| 1139 | void *security; | 1139 | void *security; |
| 1140 | #endif | 1140 | #endif |
| 1141 | struct audit_context *audit_context; | 1141 | struct audit_context *audit_context; |
| 1142 | #ifdef CONFIG_AUDITSYSCALL | ||
| 1143 | uid_t loginuid; | ||
| 1144 | unsigned int sessionid; | ||
| 1145 | #endif | ||
| 1142 | seccomp_t seccomp; | 1146 | seccomp_t seccomp; |
| 1143 | 1147 | ||
| 1144 | /* Thread group tracking */ | 1148 | /* Thread group tracking */ |
diff --git a/kernel/audit.c b/kernel/audit.c index 801c946dd24b..c8555b180213 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -66,10 +66,11 @@ | |||
| 66 | * (Initialization happens after skb_init is called.) */ | 66 | * (Initialization happens after skb_init is called.) */ |
| 67 | static int audit_initialized; | 67 | static int audit_initialized; |
| 68 | 68 | ||
| 69 | /* 0 - no auditing | 69 | #define AUDIT_OFF 0 |
| 70 | * 1 - auditing enabled | 70 | #define AUDIT_ON 1 |
| 71 | * 2 - auditing enabled and configuration is locked/unchangeable. */ | 71 | #define AUDIT_LOCKED 2 |
| 72 | int audit_enabled; | 72 | int audit_enabled; |
| 73 | int audit_ever_enabled; | ||
| 73 | 74 | ||
| 74 | /* Default state when kernel boots without any parameters. */ | 75 | /* Default state when kernel boots without any parameters. */ |
| 75 | static int audit_default; | 76 | static int audit_default; |
| @@ -152,8 +153,10 @@ struct audit_buffer { | |||
| 152 | 153 | ||
| 153 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) | 154 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) |
| 154 | { | 155 | { |
| 155 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); | 156 | if (ab) { |
| 156 | nlh->nlmsg_pid = pid; | 157 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); |
| 158 | nlh->nlmsg_pid = pid; | ||
| 159 | } | ||
| 157 | } | 160 | } |
| 158 | 161 | ||
| 159 | void audit_panic(const char *message) | 162 | void audit_panic(const char *message) |
| @@ -163,7 +166,8 @@ void audit_panic(const char *message) | |||
| 163 | case AUDIT_FAIL_SILENT: | 166 | case AUDIT_FAIL_SILENT: |
| 164 | break; | 167 | break; |
| 165 | case AUDIT_FAIL_PRINTK: | 168 | case AUDIT_FAIL_PRINTK: |
| 166 | printk(KERN_ERR "audit: %s\n", message); | 169 | if (printk_ratelimit()) |
| 170 | printk(KERN_ERR "audit: %s\n", message); | ||
| 167 | break; | 171 | break; |
| 168 | case AUDIT_FAIL_PANIC: | 172 | case AUDIT_FAIL_PANIC: |
| 169 | panic("audit: %s\n", message); | 173 | panic("audit: %s\n", message); |
| @@ -231,161 +235,107 @@ void audit_log_lost(const char *message) | |||
| 231 | } | 235 | } |
| 232 | 236 | ||
| 233 | if (print) { | 237 | if (print) { |
| 234 | printk(KERN_WARNING | 238 | if (printk_ratelimit()) |
| 235 | "audit: audit_lost=%d audit_rate_limit=%d audit_backlog_limit=%d\n", | 239 | printk(KERN_WARNING |
| 236 | atomic_read(&audit_lost), | 240 | "audit: audit_lost=%d audit_rate_limit=%d " |
| 237 | audit_rate_limit, | 241 | "audit_backlog_limit=%d\n", |
| 238 | audit_backlog_limit); | 242 | atomic_read(&audit_lost), |
| 243 | audit_rate_limit, | ||
| 244 | audit_backlog_limit); | ||
| 239 | audit_panic(message); | 245 | audit_panic(message); |
| 240 | } | 246 | } |
| 241 | } | 247 | } |
| 242 | 248 | ||
| 243 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid) | 249 | static int audit_log_config_change(char *function_name, int new, int old, |
| 250 | uid_t loginuid, u32 sid, int allow_changes) | ||
| 244 | { | 251 | { |
| 245 | int res, rc = 0, old = audit_rate_limit; | 252 | struct audit_buffer *ab; |
| 246 | 253 | int rc = 0; | |
| 247 | /* check if we are locked */ | ||
| 248 | if (audit_enabled == 2) | ||
| 249 | res = 0; | ||
| 250 | else | ||
| 251 | res = 1; | ||
| 252 | 254 | ||
| 255 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | ||
| 256 | audit_log_format(ab, "%s=%d old=%d by auid=%u", function_name, new, | ||
| 257 | old, loginuid); | ||
| 253 | if (sid) { | 258 | if (sid) { |
| 254 | char *ctx = NULL; | 259 | char *ctx = NULL; |
| 255 | u32 len; | 260 | u32 len; |
| 256 | if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { | 261 | |
| 257 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 262 | rc = selinux_sid_to_string(sid, &ctx, &len); |
| 258 | "audit_rate_limit=%d old=%d by auid=%u" | 263 | if (rc) { |
| 259 | " subj=%s res=%d", | 264 | audit_log_format(ab, " sid=%u", sid); |
| 260 | limit, old, loginuid, ctx, res); | 265 | allow_changes = 0; /* Something weird, deny request */ |
| 266 | } else { | ||
| 267 | audit_log_format(ab, " subj=%s", ctx); | ||
| 261 | kfree(ctx); | 268 | kfree(ctx); |
| 262 | } else | 269 | } |
| 263 | res = 0; /* Something weird, deny request */ | ||
| 264 | } | 270 | } |
| 265 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 271 | audit_log_format(ab, " res=%d", allow_changes); |
| 266 | "audit_rate_limit=%d old=%d by auid=%u res=%d", | 272 | audit_log_end(ab); |
| 267 | limit, old, loginuid, res); | ||
| 268 | |||
| 269 | /* If we are allowed, make the change */ | ||
| 270 | if (res == 1) | ||
| 271 | audit_rate_limit = limit; | ||
| 272 | /* Not allowed, update reason */ | ||
| 273 | else if (rc == 0) | ||
| 274 | rc = -EPERM; | ||
| 275 | return rc; | 273 | return rc; |
| 276 | } | 274 | } |
| 277 | 275 | ||
| 278 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) | 276 | static int audit_do_config_change(char *function_name, int *to_change, |
| 277 | int new, uid_t loginuid, u32 sid) | ||
| 279 | { | 278 | { |
| 280 | int res, rc = 0, old = audit_backlog_limit; | 279 | int allow_changes, rc = 0, old = *to_change; |
| 281 | 280 | ||
| 282 | /* check if we are locked */ | 281 | /* check if we are locked */ |
| 283 | if (audit_enabled == 2) | 282 | if (audit_enabled == AUDIT_LOCKED) |
| 284 | res = 0; | 283 | allow_changes = 0; |
| 285 | else | 284 | else |
| 286 | res = 1; | 285 | allow_changes = 1; |
| 287 | 286 | ||
| 288 | if (sid) { | 287 | if (audit_enabled != AUDIT_OFF) { |
| 289 | char *ctx = NULL; | 288 | rc = audit_log_config_change(function_name, new, old, |
| 290 | u32 len; | 289 | loginuid, sid, allow_changes); |
| 291 | if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { | 290 | if (rc) |
| 292 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 291 | allow_changes = 0; |
| 293 | "audit_backlog_limit=%d old=%d by auid=%u" | ||
| 294 | " subj=%s res=%d", | ||
| 295 | limit, old, loginuid, ctx, res); | ||
| 296 | kfree(ctx); | ||
| 297 | } else | ||
| 298 | res = 0; /* Something weird, deny request */ | ||
| 299 | } | 292 | } |
| 300 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
| 301 | "audit_backlog_limit=%d old=%d by auid=%u res=%d", | ||
| 302 | limit, old, loginuid, res); | ||
| 303 | 293 | ||
| 304 | /* If we are allowed, make the change */ | 294 | /* If we are allowed, make the change */ |
| 305 | if (res == 1) | 295 | if (allow_changes == 1) |
| 306 | audit_backlog_limit = limit; | 296 | *to_change = new; |
| 307 | /* Not allowed, update reason */ | 297 | /* Not allowed, update reason */ |
| 308 | else if (rc == 0) | 298 | else if (rc == 0) |
| 309 | rc = -EPERM; | 299 | rc = -EPERM; |
| 310 | return rc; | 300 | return rc; |
| 311 | } | 301 | } |
| 312 | 302 | ||
| 313 | static int audit_set_enabled(int state, uid_t loginuid, u32 sid) | 303 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid) |
| 304 | { | ||
| 305 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, | ||
| 306 | limit, loginuid, sid); | ||
| 307 | } | ||
| 308 | |||
| 309 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) | ||
| 314 | { | 310 | { |
| 315 | int res, rc = 0, old = audit_enabled; | 311 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, |
| 312 | limit, loginuid, sid); | ||
| 313 | } | ||
| 316 | 314 | ||
| 317 | if (state < 0 || state > 2) | 315 | static int audit_set_enabled(int state, uid_t loginuid, u32 sid) |
| 316 | { | ||
| 317 | int rc; | ||
| 318 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) | ||
| 318 | return -EINVAL; | 319 | return -EINVAL; |
| 319 | 320 | ||
| 320 | /* check if we are locked */ | 321 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state, |
| 321 | if (audit_enabled == 2) | 322 | loginuid, sid); |
| 322 | res = 0; | ||
| 323 | else | ||
| 324 | res = 1; | ||
| 325 | 323 | ||
| 326 | if (sid) { | 324 | if (!rc) |
| 327 | char *ctx = NULL; | 325 | audit_ever_enabled |= !!state; |
| 328 | u32 len; | ||
| 329 | if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { | ||
| 330 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
| 331 | "audit_enabled=%d old=%d by auid=%u" | ||
| 332 | " subj=%s res=%d", | ||
| 333 | state, old, loginuid, ctx, res); | ||
| 334 | kfree(ctx); | ||
| 335 | } else | ||
| 336 | res = 0; /* Something weird, deny request */ | ||
| 337 | } | ||
| 338 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
| 339 | "audit_enabled=%d old=%d by auid=%u res=%d", | ||
| 340 | state, old, loginuid, res); | ||
| 341 | 326 | ||
| 342 | /* If we are allowed, make the change */ | ||
| 343 | if (res == 1) | ||
| 344 | audit_enabled = state; | ||
| 345 | /* Not allowed, update reason */ | ||
| 346 | else if (rc == 0) | ||
| 347 | rc = -EPERM; | ||
| 348 | return rc; | 327 | return rc; |
| 349 | } | 328 | } |
| 350 | 329 | ||
| 351 | static int audit_set_failure(int state, uid_t loginuid, u32 sid) | 330 | static int audit_set_failure(int state, uid_t loginuid, u32 sid) |
| 352 | { | 331 | { |
| 353 | int res, rc = 0, old = audit_failure; | ||
| 354 | |||
| 355 | if (state != AUDIT_FAIL_SILENT | 332 | if (state != AUDIT_FAIL_SILENT |
| 356 | && state != AUDIT_FAIL_PRINTK | 333 | && state != AUDIT_FAIL_PRINTK |
| 357 | && state != AUDIT_FAIL_PANIC) | 334 | && state != AUDIT_FAIL_PANIC) |
| 358 | return -EINVAL; | 335 | return -EINVAL; |
| 359 | 336 | ||
| 360 | /* check if we are locked */ | 337 | return audit_do_config_change("audit_failure", &audit_failure, state, |
| 361 | if (audit_enabled == 2) | 338 | loginuid, sid); |
| 362 | res = 0; | ||
| 363 | else | ||
| 364 | res = 1; | ||
| 365 | |||
| 366 | if (sid) { | ||
| 367 | char *ctx = NULL; | ||
| 368 | u32 len; | ||
| 369 | if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { | ||
| 370 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
| 371 | "audit_failure=%d old=%d by auid=%u" | ||
| 372 | " subj=%s res=%d", | ||
| 373 | state, old, loginuid, ctx, res); | ||
| 374 | kfree(ctx); | ||
| 375 | } else | ||
| 376 | res = 0; /* Something weird, deny request */ | ||
| 377 | } | ||
| 378 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
| 379 | "audit_failure=%d old=%d by auid=%u res=%d", | ||
| 380 | state, old, loginuid, res); | ||
| 381 | |||
| 382 | /* If we are allowed, make the change */ | ||
| 383 | if (res == 1) | ||
| 384 | audit_failure = state; | ||
| 385 | /* Not allowed, update reason */ | ||
| 386 | else if (rc == 0) | ||
| 387 | rc = -EPERM; | ||
| 388 | return rc; | ||
| 389 | } | 339 | } |
| 390 | 340 | ||
| 391 | static int kauditd_thread(void *dummy) | 341 | static int kauditd_thread(void *dummy) |
| @@ -405,7 +355,11 @@ static int kauditd_thread(void *dummy) | |||
| 405 | audit_pid = 0; | 355 | audit_pid = 0; |
| 406 | } | 356 | } |
| 407 | } else { | 357 | } else { |
| 408 | printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0)); | 358 | if (printk_ratelimit()) |
| 359 | printk(KERN_NOTICE "%s\n", skb->data + | ||
| 360 | NLMSG_SPACE(0)); | ||
| 361 | else | ||
| 362 | audit_log_lost("printk limit exceeded\n"); | ||
| 409 | kfree_skb(skb); | 363 | kfree_skb(skb); |
| 410 | } | 364 | } |
| 411 | } else { | 365 | } else { |
| @@ -573,6 +527,33 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
| 573 | return err; | 527 | return err; |
| 574 | } | 528 | } |
| 575 | 529 | ||
| 530 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | ||
| 531 | u32 pid, u32 uid, uid_t auid, u32 sid) | ||
| 532 | { | ||
| 533 | int rc = 0; | ||
| 534 | char *ctx = NULL; | ||
| 535 | u32 len; | ||
| 536 | |||
| 537 | if (!audit_enabled) { | ||
| 538 | *ab = NULL; | ||
| 539 | return rc; | ||
| 540 | } | ||
| 541 | |||
| 542 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | ||
| 543 | audit_log_format(*ab, "user pid=%d uid=%u auid=%u", | ||
| 544 | pid, uid, auid); | ||
| 545 | if (sid) { | ||
| 546 | rc = selinux_sid_to_string(sid, &ctx, &len); | ||
| 547 | if (rc) | ||
| 548 | audit_log_format(*ab, " ssid=%u", sid); | ||
| 549 | else | ||
| 550 | audit_log_format(*ab, " subj=%s", ctx); | ||
| 551 | kfree(ctx); | ||
| 552 | } | ||
| 553 | |||
| 554 | return rc; | ||
| 555 | } | ||
| 556 | |||
| 576 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 557 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
| 577 | { | 558 | { |
| 578 | u32 uid, pid, seq, sid; | 559 | u32 uid, pid, seq, sid; |
| @@ -583,7 +564,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 583 | u16 msg_type = nlh->nlmsg_type; | 564 | u16 msg_type = nlh->nlmsg_type; |
| 584 | uid_t loginuid; /* loginuid of sender */ | 565 | uid_t loginuid; /* loginuid of sender */ |
| 585 | struct audit_sig_info *sig_data; | 566 | struct audit_sig_info *sig_data; |
| 586 | char *ctx; | 567 | char *ctx = NULL; |
| 587 | u32 len; | 568 | u32 len; |
| 588 | 569 | ||
| 589 | err = audit_netlink_ok(skb, msg_type); | 570 | err = audit_netlink_ok(skb, msg_type); |
| @@ -634,23 +615,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 634 | if (err < 0) return err; | 615 | if (err < 0) return err; |
| 635 | } | 616 | } |
| 636 | if (status_get->mask & AUDIT_STATUS_PID) { | 617 | if (status_get->mask & AUDIT_STATUS_PID) { |
| 637 | int old = audit_pid; | 618 | int new_pid = status_get->pid; |
| 638 | if (sid) { | 619 | |
| 639 | if ((err = selinux_sid_to_string( | 620 | if (audit_enabled != AUDIT_OFF) |
| 640 | sid, &ctx, &len))) | 621 | audit_log_config_change("audit_pid", new_pid, |
| 641 | return err; | 622 | audit_pid, loginuid, |
| 642 | else | 623 | sid, 1); |
| 643 | audit_log(NULL, GFP_KERNEL, | 624 | |
| 644 | AUDIT_CONFIG_CHANGE, | 625 | audit_pid = new_pid; |
| 645 | "audit_pid=%d old=%d by auid=%u subj=%s", | ||
| 646 | status_get->pid, old, | ||
| 647 | loginuid, ctx); | ||
| 648 | kfree(ctx); | ||
| 649 | } else | ||
| 650 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
| 651 | "audit_pid=%d old=%d by auid=%u", | ||
| 652 | status_get->pid, old, loginuid); | ||
| 653 | audit_pid = status_get->pid; | ||
| 654 | } | 626 | } |
| 655 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) | 627 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) |
| 656 | err = audit_set_rate_limit(status_get->rate_limit, | 628 | err = audit_set_rate_limit(status_get->rate_limit, |
| @@ -673,64 +645,35 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 673 | if (err) | 645 | if (err) |
| 674 | break; | 646 | break; |
| 675 | } | 647 | } |
| 676 | ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 648 | audit_log_common_recv_msg(&ab, msg_type, pid, uid, |
| 677 | if (ab) { | 649 | loginuid, sid); |
| 678 | audit_log_format(ab, | 650 | |
| 679 | "user pid=%d uid=%u auid=%u", | 651 | if (msg_type != AUDIT_USER_TTY) |
| 680 | pid, uid, loginuid); | 652 | audit_log_format(ab, " msg='%.1024s'", |
| 681 | if (sid) { | 653 | (char *)data); |
| 682 | if (selinux_sid_to_string( | 654 | else { |
| 683 | sid, &ctx, &len)) { | 655 | int size; |
| 684 | audit_log_format(ab, | 656 | |
| 685 | " ssid=%u", sid); | 657 | audit_log_format(ab, " msg="); |
| 686 | /* Maybe call audit_panic? */ | 658 | size = nlmsg_len(nlh); |
| 687 | } else | 659 | audit_log_n_untrustedstring(ab, size, |
| 688 | audit_log_format(ab, | 660 | data); |
| 689 | " subj=%s", ctx); | ||
| 690 | kfree(ctx); | ||
| 691 | } | ||
| 692 | if (msg_type != AUDIT_USER_TTY) | ||
| 693 | audit_log_format(ab, " msg='%.1024s'", | ||
| 694 | (char *)data); | ||
| 695 | else { | ||
| 696 | int size; | ||
| 697 | |||
| 698 | audit_log_format(ab, " msg="); | ||
| 699 | size = nlmsg_len(nlh); | ||
| 700 | audit_log_n_untrustedstring(ab, size, | ||
| 701 | data); | ||
| 702 | } | ||
| 703 | audit_set_pid(ab, pid); | ||
| 704 | audit_log_end(ab); | ||
| 705 | } | 661 | } |
| 662 | audit_set_pid(ab, pid); | ||
| 663 | audit_log_end(ab); | ||
| 706 | } | 664 | } |
| 707 | break; | 665 | break; |
| 708 | case AUDIT_ADD: | 666 | case AUDIT_ADD: |
| 709 | case AUDIT_DEL: | 667 | case AUDIT_DEL: |
| 710 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) | 668 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) |
| 711 | return -EINVAL; | 669 | return -EINVAL; |
| 712 | if (audit_enabled == 2) { | 670 | if (audit_enabled == AUDIT_LOCKED) { |
| 713 | ab = audit_log_start(NULL, GFP_KERNEL, | 671 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
| 714 | AUDIT_CONFIG_CHANGE); | 672 | uid, loginuid, sid); |
| 715 | if (ab) { | 673 | |
| 716 | audit_log_format(ab, | 674 | audit_log_format(ab, " audit_enabled=%d res=0", |
| 717 | "pid=%d uid=%u auid=%u", | 675 | audit_enabled); |
| 718 | pid, uid, loginuid); | 676 | audit_log_end(ab); |
| 719 | if (sid) { | ||
| 720 | if (selinux_sid_to_string( | ||
| 721 | sid, &ctx, &len)) { | ||
| 722 | audit_log_format(ab, | ||
| 723 | " ssid=%u", sid); | ||
| 724 | /* Maybe call audit_panic? */ | ||
| 725 | } else | ||
| 726 | audit_log_format(ab, | ||
| 727 | " subj=%s", ctx); | ||
| 728 | kfree(ctx); | ||
| 729 | } | ||
| 730 | audit_log_format(ab, " audit_enabled=%d res=0", | ||
| 731 | audit_enabled); | ||
| 732 | audit_log_end(ab); | ||
| 733 | } | ||
| 734 | return -EPERM; | 677 | return -EPERM; |
| 735 | } | 678 | } |
| 736 | /* fallthrough */ | 679 | /* fallthrough */ |
| @@ -743,28 +686,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 743 | case AUDIT_DEL_RULE: | 686 | case AUDIT_DEL_RULE: |
| 744 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) | 687 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) |
| 745 | return -EINVAL; | 688 | return -EINVAL; |
| 746 | if (audit_enabled == 2) { | 689 | if (audit_enabled == AUDIT_LOCKED) { |
| 747 | ab = audit_log_start(NULL, GFP_KERNEL, | 690 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
| 748 | AUDIT_CONFIG_CHANGE); | 691 | uid, loginuid, sid); |
| 749 | if (ab) { | 692 | |
| 750 | audit_log_format(ab, | 693 | audit_log_format(ab, " audit_enabled=%d res=0", |
| 751 | "pid=%d uid=%u auid=%u", | 694 | audit_enabled); |
| 752 | pid, uid, loginuid); | 695 | audit_log_end(ab); |
| 753 | if (sid) { | ||
| 754 | if (selinux_sid_to_string( | ||
| 755 | sid, &ctx, &len)) { | ||
| 756 | audit_log_format(ab, | ||
| 757 | " ssid=%u", sid); | ||
| 758 | /* Maybe call audit_panic? */ | ||
| 759 | } else | ||
| 760 | audit_log_format(ab, | ||
| 761 | " subj=%s", ctx); | ||
| 762 | kfree(ctx); | ||
| 763 | } | ||
| 764 | audit_log_format(ab, " audit_enabled=%d res=0", | ||
| 765 | audit_enabled); | ||
| 766 | audit_log_end(ab); | ||
| 767 | } | ||
| 768 | return -EPERM; | 696 | return -EPERM; |
| 769 | } | 697 | } |
| 770 | /* fallthrough */ | 698 | /* fallthrough */ |
| @@ -775,19 +703,10 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 775 | break; | 703 | break; |
| 776 | case AUDIT_TRIM: | 704 | case AUDIT_TRIM: |
| 777 | audit_trim_trees(); | 705 | audit_trim_trees(); |
| 778 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 706 | |
| 779 | if (!ab) | 707 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
| 780 | break; | 708 | uid, loginuid, sid); |
| 781 | audit_log_format(ab, "auid=%u", loginuid); | 709 | |
| 782 | if (sid) { | ||
| 783 | u32 len; | ||
| 784 | ctx = NULL; | ||
| 785 | if (selinux_sid_to_string(sid, &ctx, &len)) | ||
| 786 | audit_log_format(ab, " ssid=%u", sid); | ||
| 787 | else | ||
| 788 | audit_log_format(ab, " subj=%s", ctx); | ||
| 789 | kfree(ctx); | ||
| 790 | } | ||
| 791 | audit_log_format(ab, " op=trim res=1"); | 710 | audit_log_format(ab, " op=trim res=1"); |
| 792 | audit_log_end(ab); | 711 | audit_log_end(ab); |
| 793 | break; | 712 | break; |
| @@ -817,22 +736,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 817 | /* OK, here comes... */ | 736 | /* OK, here comes... */ |
| 818 | err = audit_tag_tree(old, new); | 737 | err = audit_tag_tree(old, new); |
| 819 | 738 | ||
| 820 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 739 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
| 821 | if (!ab) { | 740 | uid, loginuid, sid); |
| 822 | kfree(old); | 741 | |
| 823 | kfree(new); | ||
| 824 | break; | ||
| 825 | } | ||
| 826 | audit_log_format(ab, "auid=%u", loginuid); | ||
| 827 | if (sid) { | ||
| 828 | u32 len; | ||
| 829 | ctx = NULL; | ||
| 830 | if (selinux_sid_to_string(sid, &ctx, &len)) | ||
| 831 | audit_log_format(ab, " ssid=%u", sid); | ||
| 832 | else | ||
| 833 | audit_log_format(ab, " subj=%s", ctx); | ||
| 834 | kfree(ctx); | ||
| 835 | } | ||
| 836 | audit_log_format(ab, " op=make_equiv old="); | 742 | audit_log_format(ab, " op=make_equiv old="); |
| 837 | audit_log_untrustedstring(ab, old); | 743 | audit_log_untrustedstring(ab, old); |
| 838 | audit_log_format(ab, " new="); | 744 | audit_log_format(ab, " new="); |
| @@ -965,6 +871,7 @@ static int __init audit_init(void) | |||
| 965 | skb_queue_head_init(&audit_skb_queue); | 871 | skb_queue_head_init(&audit_skb_queue); |
| 966 | audit_initialized = 1; | 872 | audit_initialized = 1; |
| 967 | audit_enabled = audit_default; | 873 | audit_enabled = audit_default; |
| 874 | audit_ever_enabled |= !!audit_default; | ||
| 968 | 875 | ||
| 969 | /* Register the callback with selinux. This callback will be invoked | 876 | /* Register the callback with selinux. This callback will be invoked |
| 970 | * when a new policy is loaded. */ | 877 | * when a new policy is loaded. */ |
| @@ -992,8 +899,10 @@ static int __init audit_enable(char *str) | |||
| 992 | printk(KERN_INFO "audit: %s%s\n", | 899 | printk(KERN_INFO "audit: %s%s\n", |
| 993 | audit_default ? "enabled" : "disabled", | 900 | audit_default ? "enabled" : "disabled", |
| 994 | audit_initialized ? "" : " (after initialization)"); | 901 | audit_initialized ? "" : " (after initialization)"); |
| 995 | if (audit_initialized) | 902 | if (audit_initialized) { |
| 996 | audit_enabled = audit_default; | 903 | audit_enabled = audit_default; |
| 904 | audit_ever_enabled |= !!audit_default; | ||
| 905 | } | ||
| 997 | return 1; | 906 | return 1; |
| 998 | } | 907 | } |
| 999 | 908 | ||
| @@ -1130,7 +1039,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, | |||
| 1130 | { | 1039 | { |
| 1131 | struct audit_buffer *ab = NULL; | 1040 | struct audit_buffer *ab = NULL; |
| 1132 | struct timespec t; | 1041 | struct timespec t; |
| 1133 | unsigned int serial; | 1042 | unsigned int uninitialized_var(serial); |
| 1134 | int reserve; | 1043 | int reserve; |
| 1135 | unsigned long timeout_start = jiffies; | 1044 | unsigned long timeout_start = jiffies; |
| 1136 | 1045 | ||
| @@ -1164,7 +1073,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, | |||
| 1164 | remove_wait_queue(&audit_backlog_wait, &wait); | 1073 | remove_wait_queue(&audit_backlog_wait, &wait); |
| 1165 | continue; | 1074 | continue; |
| 1166 | } | 1075 | } |
| 1167 | if (audit_rate_check()) | 1076 | if (audit_rate_check() && printk_ratelimit()) |
| 1168 | printk(KERN_WARNING | 1077 | printk(KERN_WARNING |
| 1169 | "audit: audit_backlog=%d > " | 1078 | "audit: audit_backlog=%d > " |
| 1170 | "audit_backlog_limit=%d\n", | 1079 | "audit_backlog_limit=%d\n", |
| @@ -1249,6 +1158,7 @@ static void audit_log_vformat(struct audit_buffer *ab, const char *fmt, | |||
| 1249 | goto out; | 1158 | goto out; |
| 1250 | len = vsnprintf(skb_tail_pointer(skb), avail, fmt, args2); | 1159 | len = vsnprintf(skb_tail_pointer(skb), avail, fmt, args2); |
| 1251 | } | 1160 | } |
| 1161 | va_end(args2); | ||
| 1252 | if (len > 0) | 1162 | if (len > 0) |
| 1253 | skb_put(skb, len); | 1163 | skb_put(skb, len); |
| 1254 | out: | 1164 | out: |
| @@ -1350,6 +1260,21 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen, | |||
| 1350 | } | 1260 | } |
| 1351 | 1261 | ||
| 1352 | /** | 1262 | /** |
| 1263 | * audit_string_contains_control - does a string need to be logged in hex | ||
| 1264 | * @string - string to be checked | ||
| 1265 | * @len - max length of the string to check | ||
| 1266 | */ | ||
| 1267 | int audit_string_contains_control(const char *string, size_t len) | ||
| 1268 | { | ||
| 1269 | const unsigned char *p; | ||
| 1270 | for (p = string; p < (const unsigned char *)string + len && *p; p++) { | ||
| 1271 | if (*p == '"' || *p < 0x21 || *p > 0x7f) | ||
| 1272 | return 1; | ||
| 1273 | } | ||
| 1274 | return 0; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | /** | ||
| 1353 | * audit_log_n_untrustedstring - log a string that may contain random characters | 1278 | * audit_log_n_untrustedstring - log a string that may contain random characters |
| 1354 | * @ab: audit_buffer | 1279 | * @ab: audit_buffer |
| 1355 | * @len: lenth of string (not including trailing null) | 1280 | * @len: lenth of string (not including trailing null) |
| @@ -1363,19 +1288,13 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen, | |||
| 1363 | * The caller specifies the number of characters in the string to log, which may | 1288 | * The caller specifies the number of characters in the string to log, which may |
| 1364 | * or may not be the entire string. | 1289 | * or may not be the entire string. |
| 1365 | */ | 1290 | */ |
| 1366 | const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | 1291 | void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, |
| 1367 | const char *string) | 1292 | const char *string) |
| 1368 | { | 1293 | { |
| 1369 | const unsigned char *p; | 1294 | if (audit_string_contains_control(string, len)) |
| 1370 | 1295 | audit_log_hex(ab, string, len); | |
| 1371 | for (p = string; p < (const unsigned char *)string + len && *p; p++) { | 1296 | else |
| 1372 | if (*p == '"' || *p < 0x21 || *p > 0x7f) { | 1297 | audit_log_n_string(ab, len, string); |
| 1373 | audit_log_hex(ab, string, len); | ||
| 1374 | return string + len + 1; | ||
| 1375 | } | ||
| 1376 | } | ||
| 1377 | audit_log_n_string(ab, len, string); | ||
| 1378 | return p + 1; | ||
| 1379 | } | 1298 | } |
| 1380 | 1299 | ||
| 1381 | /** | 1300 | /** |
| @@ -1386,9 +1305,9 @@ const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | |||
| 1386 | * Same as audit_log_n_untrustedstring(), except that strlen is used to | 1305 | * Same as audit_log_n_untrustedstring(), except that strlen is used to |
| 1387 | * determine string length. | 1306 | * determine string length. |
| 1388 | */ | 1307 | */ |
| 1389 | const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | 1308 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) |
| 1390 | { | 1309 | { |
| 1391 | return audit_log_n_untrustedstring(ab, strlen(string), string); | 1310 | audit_log_n_untrustedstring(ab, strlen(string), string); |
| 1392 | } | 1311 | } |
| 1393 | 1312 | ||
| 1394 | /* This is a helper-function to print the escaped d_path */ | 1313 | /* This is a helper-function to print the escaped d_path */ |
| @@ -1437,8 +1356,11 @@ void audit_log_end(struct audit_buffer *ab) | |||
| 1437 | skb_queue_tail(&audit_skb_queue, ab->skb); | 1356 | skb_queue_tail(&audit_skb_queue, ab->skb); |
| 1438 | ab->skb = NULL; | 1357 | ab->skb = NULL; |
| 1439 | wake_up_interruptible(&kauditd_wait); | 1358 | wake_up_interruptible(&kauditd_wait); |
| 1359 | } else if (printk_ratelimit()) { | ||
| 1360 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); | ||
| 1361 | printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, ab->skb->data + NLMSG_SPACE(0)); | ||
| 1440 | } else { | 1362 | } else { |
| 1441 | printk(KERN_NOTICE "%s\n", ab->skb->data + NLMSG_SPACE(0)); | 1363 | audit_log_lost("printk limit exceeded\n"); |
| 1442 | } | 1364 | } |
| 1443 | } | 1365 | } |
| 1444 | audit_buffer_free(ab); | 1366 | audit_buffer_free(ab); |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 5d96f2cc7be8..6f19fd477aac 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -95,6 +95,8 @@ extern struct inotify_handle *audit_ih; | |||
| 95 | /* Inotify events we care about. */ | 95 | /* Inotify events we care about. */ |
| 96 | #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF | 96 | #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF |
| 97 | 97 | ||
| 98 | extern int audit_enabled; | ||
| 99 | |||
| 98 | void audit_free_parent(struct inotify_watch *i_watch) | 100 | void audit_free_parent(struct inotify_watch *i_watch) |
| 99 | { | 101 | { |
| 100 | struct audit_parent *parent; | 102 | struct audit_parent *parent; |
| @@ -974,7 +976,6 @@ static void audit_update_watch(struct audit_parent *parent, | |||
| 974 | struct audit_watch *owatch, *nwatch, *nextw; | 976 | struct audit_watch *owatch, *nwatch, *nextw; |
| 975 | struct audit_krule *r, *nextr; | 977 | struct audit_krule *r, *nextr; |
| 976 | struct audit_entry *oentry, *nentry; | 978 | struct audit_entry *oentry, *nentry; |
| 977 | struct audit_buffer *ab; | ||
| 978 | 979 | ||
| 979 | mutex_lock(&audit_filter_mutex); | 980 | mutex_lock(&audit_filter_mutex); |
| 980 | list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { | 981 | list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { |
| @@ -1014,13 +1015,18 @@ static void audit_update_watch(struct audit_parent *parent, | |||
| 1014 | call_rcu(&oentry->rcu, audit_free_rule_rcu); | 1015 | call_rcu(&oentry->rcu, audit_free_rule_rcu); |
| 1015 | } | 1016 | } |
| 1016 | 1017 | ||
| 1017 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 1018 | if (audit_enabled) { |
| 1018 | audit_log_format(ab, "op=updated rules specifying path="); | 1019 | struct audit_buffer *ab; |
| 1019 | audit_log_untrustedstring(ab, owatch->path); | 1020 | ab = audit_log_start(NULL, GFP_KERNEL, |
| 1020 | audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino); | 1021 | AUDIT_CONFIG_CHANGE); |
| 1021 | audit_log_format(ab, " list=%d res=1", r->listnr); | 1022 | audit_log_format(ab, |
| 1022 | audit_log_end(ab); | 1023 | "op=updated rules specifying path="); |
| 1023 | 1024 | audit_log_untrustedstring(ab, owatch->path); | |
| 1025 | audit_log_format(ab, " with dev=%u ino=%lu\n", | ||
| 1026 | dev, ino); | ||
| 1027 | audit_log_format(ab, " list=%d res=1", r->listnr); | ||
| 1028 | audit_log_end(ab); | ||
| 1029 | } | ||
| 1024 | audit_remove_watch(owatch); | 1030 | audit_remove_watch(owatch); |
| 1025 | goto add_watch_to_parent; /* event applies to a single watch */ | 1031 | goto add_watch_to_parent; /* event applies to a single watch */ |
| 1026 | } | 1032 | } |
| @@ -1039,25 +1045,28 @@ static void audit_remove_parent_watches(struct audit_parent *parent) | |||
| 1039 | struct audit_watch *w, *nextw; | 1045 | struct audit_watch *w, *nextw; |
| 1040 | struct audit_krule *r, *nextr; | 1046 | struct audit_krule *r, *nextr; |
| 1041 | struct audit_entry *e; | 1047 | struct audit_entry *e; |
| 1042 | struct audit_buffer *ab; | ||
| 1043 | 1048 | ||
| 1044 | mutex_lock(&audit_filter_mutex); | 1049 | mutex_lock(&audit_filter_mutex); |
| 1045 | parent->flags |= AUDIT_PARENT_INVALID; | 1050 | parent->flags |= AUDIT_PARENT_INVALID; |
| 1046 | list_for_each_entry_safe(w, nextw, &parent->watches, wlist) { | 1051 | list_for_each_entry_safe(w, nextw, &parent->watches, wlist) { |
| 1047 | list_for_each_entry_safe(r, nextr, &w->rules, rlist) { | 1052 | list_for_each_entry_safe(r, nextr, &w->rules, rlist) { |
| 1048 | e = container_of(r, struct audit_entry, rule); | 1053 | e = container_of(r, struct audit_entry, rule); |
| 1049 | 1054 | if (audit_enabled) { | |
| 1050 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 1055 | struct audit_buffer *ab; |
| 1051 | audit_log_format(ab, "op=remove rule path="); | 1056 | ab = audit_log_start(NULL, GFP_KERNEL, |
| 1052 | audit_log_untrustedstring(ab, w->path); | 1057 | AUDIT_CONFIG_CHANGE); |
| 1053 | if (r->filterkey) { | 1058 | audit_log_format(ab, "op=remove rule path="); |
| 1054 | audit_log_format(ab, " key="); | 1059 | audit_log_untrustedstring(ab, w->path); |
| 1055 | audit_log_untrustedstring(ab, r->filterkey); | 1060 | if (r->filterkey) { |
| 1056 | } else | 1061 | audit_log_format(ab, " key="); |
| 1057 | audit_log_format(ab, " key=(null)"); | 1062 | audit_log_untrustedstring(ab, |
| 1058 | audit_log_format(ab, " list=%d res=1", r->listnr); | 1063 | r->filterkey); |
| 1059 | audit_log_end(ab); | 1064 | } else |
| 1060 | 1065 | audit_log_format(ab, " key=(null)"); | |
| 1066 | audit_log_format(ab, " list=%d res=1", | ||
| 1067 | r->listnr); | ||
| 1068 | audit_log_end(ab); | ||
| 1069 | } | ||
| 1061 | list_del(&r->rlist); | 1070 | list_del(&r->rlist); |
| 1062 | list_del_rcu(&e->list); | 1071 | list_del_rcu(&e->list); |
| 1063 | call_rcu(&e->rcu, audit_free_rule_rcu); | 1072 | call_rcu(&e->rcu, audit_free_rule_rcu); |
| @@ -1495,6 +1504,9 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, | |||
| 1495 | { | 1504 | { |
| 1496 | struct audit_buffer *ab; | 1505 | struct audit_buffer *ab; |
| 1497 | 1506 | ||
| 1507 | if (!audit_enabled) | ||
| 1508 | return; | ||
| 1509 | |||
| 1498 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 1510 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 1499 | if (!ab) | 1511 | if (!ab) |
| 1500 | return; | 1512 | return; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index bce9ecdb7712..1c06ecf38d7b 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -70,6 +70,7 @@ | |||
| 70 | #include "audit.h" | 70 | #include "audit.h" |
| 71 | 71 | ||
| 72 | extern struct list_head audit_filter_list[]; | 72 | extern struct list_head audit_filter_list[]; |
| 73 | extern int audit_ever_enabled; | ||
| 73 | 74 | ||
| 74 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | 75 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context |
| 75 | * for saving names from getname(). */ | 76 | * for saving names from getname(). */ |
| @@ -78,6 +79,9 @@ extern struct list_head audit_filter_list[]; | |||
| 78 | /* Indicates that audit should log the full pathname. */ | 79 | /* Indicates that audit should log the full pathname. */ |
| 79 | #define AUDIT_NAME_FULL -1 | 80 | #define AUDIT_NAME_FULL -1 |
| 80 | 81 | ||
| 82 | /* no execve audit message should be longer than this (userspace limits) */ | ||
| 83 | #define MAX_EXECVE_AUDIT_LEN 7500 | ||
| 84 | |||
| 81 | /* number of audit rules */ | 85 | /* number of audit rules */ |
| 82 | int audit_n_rules; | 86 | int audit_n_rules; |
| 83 | 87 | ||
| @@ -176,7 +180,11 @@ struct audit_aux_data_fd_pair { | |||
| 176 | struct audit_aux_data_pids { | 180 | struct audit_aux_data_pids { |
| 177 | struct audit_aux_data d; | 181 | struct audit_aux_data d; |
| 178 | pid_t target_pid[AUDIT_AUX_PIDS]; | 182 | pid_t target_pid[AUDIT_AUX_PIDS]; |
| 183 | uid_t target_auid[AUDIT_AUX_PIDS]; | ||
| 184 | uid_t target_uid[AUDIT_AUX_PIDS]; | ||
| 185 | unsigned int target_sessionid[AUDIT_AUX_PIDS]; | ||
| 179 | u32 target_sid[AUDIT_AUX_PIDS]; | 186 | u32 target_sid[AUDIT_AUX_PIDS]; |
| 187 | char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN]; | ||
| 180 | int pid_count; | 188 | int pid_count; |
| 181 | }; | 189 | }; |
| 182 | 190 | ||
| @@ -192,7 +200,6 @@ struct audit_context { | |||
| 192 | enum audit_state state; | 200 | enum audit_state state; |
| 193 | unsigned int serial; /* serial number for record */ | 201 | unsigned int serial; /* serial number for record */ |
| 194 | struct timespec ctime; /* time of syscall entry */ | 202 | struct timespec ctime; /* time of syscall entry */ |
| 195 | uid_t loginuid; /* login uid (identity) */ | ||
| 196 | int major; /* syscall number */ | 203 | int major; /* syscall number */ |
| 197 | unsigned long argv[4]; /* syscall arguments */ | 204 | unsigned long argv[4]; /* syscall arguments */ |
| 198 | int return_valid; /* return code is valid */ | 205 | int return_valid; /* return code is valid */ |
| @@ -215,7 +222,11 @@ struct audit_context { | |||
| 215 | int arch; | 222 | int arch; |
| 216 | 223 | ||
| 217 | pid_t target_pid; | 224 | pid_t target_pid; |
| 225 | uid_t target_auid; | ||
| 226 | uid_t target_uid; | ||
| 227 | unsigned int target_sessionid; | ||
| 218 | u32 target_sid; | 228 | u32 target_sid; |
| 229 | char target_comm[TASK_COMM_LEN]; | ||
| 219 | 230 | ||
| 220 | struct audit_tree_refs *trees, *first_trees; | 231 | struct audit_tree_refs *trees, *first_trees; |
| 221 | int tree_count; | 232 | int tree_count; |
| @@ -506,7 +517,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 506 | case AUDIT_LOGINUID: | 517 | case AUDIT_LOGINUID: |
| 507 | result = 0; | 518 | result = 0; |
| 508 | if (ctx) | 519 | if (ctx) |
| 509 | result = audit_comparator(ctx->loginuid, f->op, f->val); | 520 | result = audit_comparator(tsk->loginuid, f->op, f->val); |
| 510 | break; | 521 | break; |
| 511 | case AUDIT_SUBJ_USER: | 522 | case AUDIT_SUBJ_USER: |
| 512 | case AUDIT_SUBJ_ROLE: | 523 | case AUDIT_SUBJ_ROLE: |
| @@ -702,7 +713,24 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
| 702 | if (likely(!context)) | 713 | if (likely(!context)) |
| 703 | return NULL; | 714 | return NULL; |
| 704 | context->return_valid = return_valid; | 715 | context->return_valid = return_valid; |
| 705 | context->return_code = return_code; | 716 | |
| 717 | /* | ||
| 718 | * we need to fix up the return code in the audit logs if the actual | ||
| 719 | * return codes are later going to be fixed up by the arch specific | ||
| 720 | * signal handlers | ||
| 721 | * | ||
| 722 | * This is actually a test for: | ||
| 723 | * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) || | ||
| 724 | * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK) | ||
| 725 | * | ||
| 726 | * but is faster than a bunch of || | ||
| 727 | */ | ||
| 728 | if (unlikely(return_code <= -ERESTARTSYS) && | ||
| 729 | (return_code >= -ERESTART_RESTARTBLOCK) && | ||
| 730 | (return_code != -ENOIOCTLCMD)) | ||
| 731 | context->return_code = -EINTR; | ||
| 732 | else | ||
| 733 | context->return_code = return_code; | ||
| 706 | 734 | ||
| 707 | if (context->in_syscall && !context->dummy && !context->auditable) { | 735 | if (context->in_syscall && !context->dummy && !context->auditable) { |
| 708 | enum audit_state state; | 736 | enum audit_state state; |
| @@ -783,11 +811,8 @@ static inline void audit_free_aux(struct audit_context *context) | |||
| 783 | static inline void audit_zero_context(struct audit_context *context, | 811 | static inline void audit_zero_context(struct audit_context *context, |
| 784 | enum audit_state state) | 812 | enum audit_state state) |
| 785 | { | 813 | { |
| 786 | uid_t loginuid = context->loginuid; | ||
| 787 | |||
| 788 | memset(context, 0, sizeof(*context)); | 814 | memset(context, 0, sizeof(*context)); |
| 789 | context->state = state; | 815 | context->state = state; |
| 790 | context->loginuid = loginuid; | ||
| 791 | } | 816 | } |
| 792 | 817 | ||
| 793 | static inline struct audit_context *audit_alloc_context(enum audit_state state) | 818 | static inline struct audit_context *audit_alloc_context(enum audit_state state) |
| @@ -814,7 +839,7 @@ int audit_alloc(struct task_struct *tsk) | |||
| 814 | struct audit_context *context; | 839 | struct audit_context *context; |
| 815 | enum audit_state state; | 840 | enum audit_state state; |
| 816 | 841 | ||
| 817 | if (likely(!audit_enabled)) | 842 | if (likely(!audit_ever_enabled)) |
| 818 | return 0; /* Return if not auditing. */ | 843 | return 0; /* Return if not auditing. */ |
| 819 | 844 | ||
| 820 | state = audit_filter_task(tsk); | 845 | state = audit_filter_task(tsk); |
| @@ -826,11 +851,6 @@ int audit_alloc(struct task_struct *tsk) | |||
| 826 | return -ENOMEM; | 851 | return -ENOMEM; |
| 827 | } | 852 | } |
| 828 | 853 | ||
| 829 | /* Preserve login uid */ | ||
| 830 | context->loginuid = -1; | ||
| 831 | if (current->audit_context) | ||
| 832 | context->loginuid = current->audit_context->loginuid; | ||
| 833 | |||
| 834 | tsk->audit_context = context; | 854 | tsk->audit_context = context; |
| 835 | set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); | 855 | set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); |
| 836 | return 0; | 856 | return 0; |
| @@ -922,7 +942,8 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk | |||
| 922 | } | 942 | } |
| 923 | 943 | ||
| 924 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, | 944 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, |
| 925 | u32 sid) | 945 | uid_t auid, uid_t uid, unsigned int sessionid, |
| 946 | u32 sid, char *comm) | ||
| 926 | { | 947 | { |
| 927 | struct audit_buffer *ab; | 948 | struct audit_buffer *ab; |
| 928 | char *s = NULL; | 949 | char *s = NULL; |
| @@ -931,68 +952,204 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid, | |||
| 931 | 952 | ||
| 932 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); | 953 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); |
| 933 | if (!ab) | 954 | if (!ab) |
| 934 | return 1; | 955 | return rc; |
| 935 | 956 | ||
| 957 | audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid, | ||
| 958 | uid, sessionid); | ||
| 936 | if (selinux_sid_to_string(sid, &s, &len)) { | 959 | if (selinux_sid_to_string(sid, &s, &len)) { |
| 937 | audit_log_format(ab, "opid=%d obj=(none)", pid); | 960 | audit_log_format(ab, " obj=(none)"); |
| 938 | rc = 1; | 961 | rc = 1; |
| 939 | } else | 962 | } else |
| 940 | audit_log_format(ab, "opid=%d obj=%s", pid, s); | 963 | audit_log_format(ab, " obj=%s", s); |
| 964 | audit_log_format(ab, " ocomm="); | ||
| 965 | audit_log_untrustedstring(ab, comm); | ||
| 941 | audit_log_end(ab); | 966 | audit_log_end(ab); |
| 942 | kfree(s); | 967 | kfree(s); |
| 943 | 968 | ||
| 944 | return rc; | 969 | return rc; |
| 945 | } | 970 | } |
| 946 | 971 | ||
| 947 | static void audit_log_execve_info(struct audit_buffer *ab, | 972 | /* |
| 948 | struct audit_aux_data_execve *axi) | 973 | * to_send and len_sent accounting are very loose estimates. We aren't |
| 974 | * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being | ||
| 975 | * within about 500 bytes (next page boundry) | ||
| 976 | * | ||
| 977 | * why snprintf? an int is up to 12 digits long. if we just assumed when | ||
| 978 | * logging that a[%d]= was going to be 16 characters long we would be wasting | ||
| 979 | * space in every audit message. In one 7500 byte message we can log up to | ||
| 980 | * about 1000 min size arguments. That comes down to about 50% waste of space | ||
| 981 | * if we didn't do the snprintf to find out how long arg_num_len was. | ||
| 982 | */ | ||
| 983 | static int audit_log_single_execve_arg(struct audit_context *context, | ||
| 984 | struct audit_buffer **ab, | ||
| 985 | int arg_num, | ||
| 986 | size_t *len_sent, | ||
| 987 | const char __user *p, | ||
| 988 | char *buf) | ||
| 949 | { | 989 | { |
| 950 | int i; | 990 | char arg_num_len_buf[12]; |
| 951 | long len, ret; | 991 | const char __user *tmp_p = p; |
| 952 | const char __user *p; | 992 | /* how many digits are in arg_num? 3 is the length of a=\n */ |
| 953 | char *buf; | 993 | size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 3; |
| 994 | size_t len, len_left, to_send; | ||
| 995 | size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN; | ||
| 996 | unsigned int i, has_cntl = 0, too_long = 0; | ||
| 997 | int ret; | ||
| 998 | |||
| 999 | /* strnlen_user includes the null we don't want to send */ | ||
| 1000 | len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1; | ||
| 954 | 1001 | ||
| 955 | if (axi->mm != current->mm) | 1002 | /* |
| 956 | return; /* execve failed, no additional info */ | 1003 | * We just created this mm, if we can't find the strings |
| 957 | 1004 | * we just copied into it something is _very_ wrong. Similar | |
| 958 | p = (const char __user *)axi->mm->arg_start; | 1005 | * for strings that are too long, we should not have created |
| 1006 | * any. | ||
| 1007 | */ | ||
| 1008 | if (unlikely((len = -1) || len > MAX_ARG_STRLEN - 1)) { | ||
| 1009 | WARN_ON(1); | ||
| 1010 | send_sig(SIGKILL, current, 0); | ||
| 1011 | } | ||
| 959 | 1012 | ||
| 960 | for (i = 0; i < axi->argc; i++, p += len) { | 1013 | /* walk the whole argument looking for non-ascii chars */ |
| 961 | len = strnlen_user(p, MAX_ARG_STRLEN); | 1014 | do { |
| 1015 | if (len_left > MAX_EXECVE_AUDIT_LEN) | ||
| 1016 | to_send = MAX_EXECVE_AUDIT_LEN; | ||
| 1017 | else | ||
| 1018 | to_send = len_left; | ||
| 1019 | ret = copy_from_user(buf, tmp_p, to_send); | ||
| 962 | /* | 1020 | /* |
| 963 | * We just created this mm, if we can't find the strings | 1021 | * There is no reason for this copy to be short. We just |
| 964 | * we just copied into it something is _very_ wrong. Similar | 1022 | * copied them here, and the mm hasn't been exposed to user- |
| 965 | * for strings that are too long, we should not have created | 1023 | * space yet. |
| 966 | * any. | ||
| 967 | */ | 1024 | */ |
| 968 | if (!len || len > MAX_ARG_STRLEN) { | 1025 | if (ret) { |
| 969 | WARN_ON(1); | 1026 | WARN_ON(1); |
| 970 | send_sig(SIGKILL, current, 0); | 1027 | send_sig(SIGKILL, current, 0); |
| 971 | } | 1028 | } |
| 972 | 1029 | buf[to_send] = '\0'; | |
| 973 | buf = kmalloc(len, GFP_KERNEL); | 1030 | has_cntl = audit_string_contains_control(buf, to_send); |
| 974 | if (!buf) { | 1031 | if (has_cntl) { |
| 975 | audit_panic("out of memory for argv string\n"); | 1032 | /* |
| 1033 | * hex messages get logged as 2 bytes, so we can only | ||
| 1034 | * send half as much in each message | ||
| 1035 | */ | ||
| 1036 | max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2; | ||
| 976 | break; | 1037 | break; |
| 977 | } | 1038 | } |
| 1039 | len_left -= to_send; | ||
| 1040 | tmp_p += to_send; | ||
| 1041 | } while (len_left > 0); | ||
| 1042 | |||
| 1043 | len_left = len; | ||
| 1044 | |||
| 1045 | if (len > max_execve_audit_len) | ||
| 1046 | too_long = 1; | ||
| 1047 | |||
| 1048 | /* rewalk the argument actually logging the message */ | ||
| 1049 | for (i = 0; len_left > 0; i++) { | ||
| 1050 | int room_left; | ||
| 1051 | |||
| 1052 | if (len_left > max_execve_audit_len) | ||
| 1053 | to_send = max_execve_audit_len; | ||
| 1054 | else | ||
| 1055 | to_send = len_left; | ||
| 1056 | |||
| 1057 | /* do we have space left to send this argument in this ab? */ | ||
| 1058 | room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent; | ||
| 1059 | if (has_cntl) | ||
| 1060 | room_left -= (to_send * 2); | ||
| 1061 | else | ||
| 1062 | room_left -= to_send; | ||
| 1063 | if (room_left < 0) { | ||
| 1064 | *len_sent = 0; | ||
| 1065 | audit_log_end(*ab); | ||
| 1066 | *ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE); | ||
| 1067 | if (!*ab) | ||
| 1068 | return 0; | ||
| 1069 | } | ||
| 978 | 1070 | ||
| 979 | ret = copy_from_user(buf, p, len); | ||
| 980 | /* | 1071 | /* |
| 981 | * There is no reason for this copy to be short. We just | 1072 | * first record needs to say how long the original string was |
| 982 | * copied them here, and the mm hasn't been exposed to user- | 1073 | * so we can be sure nothing was lost. |
| 983 | * space yet. | 1074 | */ |
| 1075 | if ((i == 0) && (too_long)) | ||
| 1076 | audit_log_format(*ab, "a%d_len=%ld ", arg_num, | ||
| 1077 | has_cntl ? 2*len : len); | ||
| 1078 | |||
| 1079 | /* | ||
| 1080 | * normally arguments are small enough to fit and we already | ||
| 1081 | * filled buf above when we checked for control characters | ||
| 1082 | * so don't bother with another copy_from_user | ||
| 984 | */ | 1083 | */ |
| 1084 | if (len >= max_execve_audit_len) | ||
| 1085 | ret = copy_from_user(buf, p, to_send); | ||
| 1086 | else | ||
| 1087 | ret = 0; | ||
| 985 | if (ret) { | 1088 | if (ret) { |
| 986 | WARN_ON(1); | 1089 | WARN_ON(1); |
| 987 | send_sig(SIGKILL, current, 0); | 1090 | send_sig(SIGKILL, current, 0); |
| 988 | } | 1091 | } |
| 1092 | buf[to_send] = '\0'; | ||
| 1093 | |||
| 1094 | /* actually log it */ | ||
| 1095 | audit_log_format(*ab, "a%d", arg_num); | ||
| 1096 | if (too_long) | ||
| 1097 | audit_log_format(*ab, "[%d]", i); | ||
| 1098 | audit_log_format(*ab, "="); | ||
| 1099 | if (has_cntl) | ||
| 1100 | audit_log_hex(*ab, buf, to_send); | ||
| 1101 | else | ||
| 1102 | audit_log_format(*ab, "\"%s\"", buf); | ||
| 1103 | audit_log_format(*ab, "\n"); | ||
| 1104 | |||
| 1105 | p += to_send; | ||
| 1106 | len_left -= to_send; | ||
| 1107 | *len_sent += arg_num_len; | ||
| 1108 | if (has_cntl) | ||
| 1109 | *len_sent += to_send * 2; | ||
| 1110 | else | ||
| 1111 | *len_sent += to_send; | ||
| 1112 | } | ||
| 1113 | /* include the null we didn't log */ | ||
| 1114 | return len + 1; | ||
| 1115 | } | ||
| 989 | 1116 | ||
| 990 | audit_log_format(ab, "a%d=", i); | 1117 | static void audit_log_execve_info(struct audit_context *context, |
| 991 | audit_log_untrustedstring(ab, buf); | 1118 | struct audit_buffer **ab, |
| 992 | audit_log_format(ab, "\n"); | 1119 | struct audit_aux_data_execve *axi) |
| 1120 | { | ||
| 1121 | int i; | ||
| 1122 | size_t len, len_sent = 0; | ||
| 1123 | const char __user *p; | ||
| 1124 | char *buf; | ||
| 1125 | |||
| 1126 | if (axi->mm != current->mm) | ||
| 1127 | return; /* execve failed, no additional info */ | ||
| 1128 | |||
| 1129 | p = (const char __user *)axi->mm->arg_start; | ||
| 1130 | |||
| 1131 | audit_log_format(*ab, "argc=%d ", axi->argc); | ||
| 1132 | |||
| 1133 | /* | ||
| 1134 | * we need some kernel buffer to hold the userspace args. Just | ||
| 1135 | * allocate one big one rather than allocating one of the right size | ||
| 1136 | * for every single argument inside audit_log_single_execve_arg() | ||
| 1137 | * should be <8k allocation so should be pretty safe. | ||
| 1138 | */ | ||
| 1139 | buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); | ||
| 1140 | if (!buf) { | ||
| 1141 | audit_panic("out of memory for argv string\n"); | ||
| 1142 | return; | ||
| 1143 | } | ||
| 993 | 1144 | ||
| 994 | kfree(buf); | 1145 | for (i = 0; i < axi->argc; i++) { |
| 1146 | len = audit_log_single_execve_arg(context, ab, i, | ||
| 1147 | &len_sent, p, buf); | ||
| 1148 | if (len <= 0) | ||
| 1149 | break; | ||
| 1150 | p += len; | ||
| 995 | } | 1151 | } |
| 1152 | kfree(buf); | ||
| 996 | } | 1153 | } |
| 997 | 1154 | ||
| 998 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) | 1155 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
| @@ -1039,7 +1196,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1039 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" | 1196 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" |
| 1040 | " ppid=%d pid=%d auid=%u uid=%u gid=%u" | 1197 | " ppid=%d pid=%d auid=%u uid=%u gid=%u" |
| 1041 | " euid=%u suid=%u fsuid=%u" | 1198 | " euid=%u suid=%u fsuid=%u" |
| 1042 | " egid=%u sgid=%u fsgid=%u tty=%s", | 1199 | " egid=%u sgid=%u fsgid=%u tty=%s ses=%u", |
| 1043 | context->argv[0], | 1200 | context->argv[0], |
| 1044 | context->argv[1], | 1201 | context->argv[1], |
| 1045 | context->argv[2], | 1202 | context->argv[2], |
| @@ -1047,11 +1204,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1047 | context->name_count, | 1204 | context->name_count, |
| 1048 | context->ppid, | 1205 | context->ppid, |
| 1049 | context->pid, | 1206 | context->pid, |
| 1050 | context->loginuid, | 1207 | tsk->loginuid, |
| 1051 | context->uid, | 1208 | context->uid, |
| 1052 | context->gid, | 1209 | context->gid, |
| 1053 | context->euid, context->suid, context->fsuid, | 1210 | context->euid, context->suid, context->fsuid, |
| 1054 | context->egid, context->sgid, context->fsgid, tty); | 1211 | context->egid, context->sgid, context->fsgid, tty, |
| 1212 | tsk->sessionid); | ||
| 1055 | 1213 | ||
| 1056 | mutex_unlock(&tty_mutex); | 1214 | mutex_unlock(&tty_mutex); |
| 1057 | 1215 | ||
| @@ -1135,7 +1293,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1135 | 1293 | ||
| 1136 | case AUDIT_EXECVE: { | 1294 | case AUDIT_EXECVE: { |
| 1137 | struct audit_aux_data_execve *axi = (void *)aux; | 1295 | struct audit_aux_data_execve *axi = (void *)aux; |
| 1138 | audit_log_execve_info(ab, axi); | 1296 | audit_log_execve_info(context, &ab, axi); |
| 1139 | break; } | 1297 | break; } |
| 1140 | 1298 | ||
| 1141 | case AUDIT_SOCKETCALL: { | 1299 | case AUDIT_SOCKETCALL: { |
| @@ -1168,13 +1326,19 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1168 | 1326 | ||
| 1169 | for (i = 0; i < axs->pid_count; i++) | 1327 | for (i = 0; i < axs->pid_count; i++) |
| 1170 | if (audit_log_pid_context(context, axs->target_pid[i], | 1328 | if (audit_log_pid_context(context, axs->target_pid[i], |
| 1171 | axs->target_sid[i])) | 1329 | axs->target_auid[i], |
| 1330 | axs->target_uid[i], | ||
| 1331 | axs->target_sessionid[i], | ||
| 1332 | axs->target_sid[i], | ||
| 1333 | axs->target_comm[i])) | ||
| 1172 | call_panic = 1; | 1334 | call_panic = 1; |
| 1173 | } | 1335 | } |
| 1174 | 1336 | ||
| 1175 | if (context->target_pid && | 1337 | if (context->target_pid && |
| 1176 | audit_log_pid_context(context, context->target_pid, | 1338 | audit_log_pid_context(context, context->target_pid, |
| 1177 | context->target_sid)) | 1339 | context->target_auid, context->target_uid, |
| 1340 | context->target_sessionid, | ||
| 1341 | context->target_sid, context->target_comm)) | ||
| 1178 | call_panic = 1; | 1342 | call_panic = 1; |
| 1179 | 1343 | ||
| 1180 | if (context->pwd && context->pwdmnt) { | 1344 | if (context->pwd && context->pwdmnt) { |
| @@ -1242,6 +1406,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1242 | 1406 | ||
| 1243 | audit_log_end(ab); | 1407 | audit_log_end(ab); |
| 1244 | } | 1408 | } |
| 1409 | |||
| 1410 | /* Send end of event record to help user space know we are finished */ | ||
| 1411 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); | ||
| 1412 | if (ab) | ||
| 1413 | audit_log_end(ab); | ||
| 1245 | if (call_panic) | 1414 | if (call_panic) |
| 1246 | audit_panic("error converting sid to string"); | 1415 | audit_panic("error converting sid to string"); |
| 1247 | } | 1416 | } |
| @@ -1766,6 +1935,9 @@ void auditsc_get_stamp(struct audit_context *ctx, | |||
| 1766 | ctx->auditable = 1; | 1935 | ctx->auditable = 1; |
| 1767 | } | 1936 | } |
| 1768 | 1937 | ||
| 1938 | /* global counter which is incremented every time something logs in */ | ||
| 1939 | static atomic_t session_id = ATOMIC_INIT(0); | ||
| 1940 | |||
| 1769 | /** | 1941 | /** |
| 1770 | * audit_set_loginuid - set a task's audit_context loginuid | 1942 | * audit_set_loginuid - set a task's audit_context loginuid |
| 1771 | * @task: task whose audit context is being modified | 1943 | * @task: task whose audit context is being modified |
| @@ -1777,41 +1949,29 @@ void auditsc_get_stamp(struct audit_context *ctx, | |||
| 1777 | */ | 1949 | */ |
| 1778 | int audit_set_loginuid(struct task_struct *task, uid_t loginuid) | 1950 | int audit_set_loginuid(struct task_struct *task, uid_t loginuid) |
| 1779 | { | 1951 | { |
| 1952 | unsigned int sessionid = atomic_inc_return(&session_id); | ||
| 1780 | struct audit_context *context = task->audit_context; | 1953 | struct audit_context *context = task->audit_context; |
| 1781 | 1954 | ||
| 1782 | if (context) { | 1955 | if (context && context->in_syscall) { |
| 1783 | /* Only log if audit is enabled */ | 1956 | struct audit_buffer *ab; |
| 1784 | if (context->in_syscall) { | 1957 | |
| 1785 | struct audit_buffer *ab; | 1958 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); |
| 1786 | 1959 | if (ab) { | |
| 1787 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); | 1960 | audit_log_format(ab, "login pid=%d uid=%u " |
| 1788 | if (ab) { | 1961 | "old auid=%u new auid=%u" |
| 1789 | audit_log_format(ab, "login pid=%d uid=%u " | 1962 | " old ses=%u new ses=%u", |
| 1790 | "old auid=%u new auid=%u", | 1963 | task->pid, task->uid, |
| 1791 | task->pid, task->uid, | 1964 | task->loginuid, loginuid, |
| 1792 | context->loginuid, loginuid); | 1965 | task->sessionid, sessionid); |
| 1793 | audit_log_end(ab); | 1966 | audit_log_end(ab); |
| 1794 | } | ||
| 1795 | } | 1967 | } |
| 1796 | context->loginuid = loginuid; | ||
| 1797 | } | 1968 | } |
| 1969 | task->sessionid = sessionid; | ||
| 1970 | task->loginuid = loginuid; | ||
| 1798 | return 0; | 1971 | return 0; |
| 1799 | } | 1972 | } |
| 1800 | 1973 | ||
| 1801 | /** | 1974 | /** |
| 1802 | * audit_get_loginuid - get the loginuid for an audit_context | ||
| 1803 | * @ctx: the audit_context | ||
| 1804 | * | ||
| 1805 | * Returns the context's loginuid or -1 if @ctx is NULL. | ||
| 1806 | */ | ||
| 1807 | uid_t audit_get_loginuid(struct audit_context *ctx) | ||
| 1808 | { | ||
| 1809 | return ctx ? ctx->loginuid : -1; | ||
| 1810 | } | ||
| 1811 | |||
| 1812 | EXPORT_SYMBOL(audit_get_loginuid); | ||
| 1813 | |||
| 1814 | /** | ||
| 1815 | * __audit_mq_open - record audit data for a POSIX MQ open | 1975 | * __audit_mq_open - record audit data for a POSIX MQ open |
| 1816 | * @oflag: open flag | 1976 | * @oflag: open flag |
| 1817 | * @mode: mode bits | 1977 | * @mode: mode bits |
| @@ -2070,8 +2230,6 @@ int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode | |||
| 2070 | return 0; | 2230 | return 0; |
| 2071 | } | 2231 | } |
| 2072 | 2232 | ||
| 2073 | int audit_argv_kb = 32; | ||
| 2074 | |||
| 2075 | int audit_bprm(struct linux_binprm *bprm) | 2233 | int audit_bprm(struct linux_binprm *bprm) |
| 2076 | { | 2234 | { |
| 2077 | struct audit_aux_data_execve *ax; | 2235 | struct audit_aux_data_execve *ax; |
| @@ -2080,14 +2238,6 @@ int audit_bprm(struct linux_binprm *bprm) | |||
| 2080 | if (likely(!audit_enabled || !context || context->dummy)) | 2238 | if (likely(!audit_enabled || !context || context->dummy)) |
| 2081 | return 0; | 2239 | return 0; |
| 2082 | 2240 | ||
| 2083 | /* | ||
| 2084 | * Even though the stack code doesn't limit the arg+env size any more, | ||
| 2085 | * the audit code requires that _all_ arguments be logged in a single | ||
| 2086 | * netlink skb. Hence cap it :-( | ||
| 2087 | */ | ||
| 2088 | if (bprm->argv_len > (audit_argv_kb << 10)) | ||
| 2089 | return -E2BIG; | ||
| 2090 | |||
| 2091 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); | 2241 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); |
| 2092 | if (!ax) | 2242 | if (!ax) |
| 2093 | return -ENOMEM; | 2243 | return -ENOMEM; |
| @@ -2193,7 +2343,11 @@ void __audit_ptrace(struct task_struct *t) | |||
| 2193 | struct audit_context *context = current->audit_context; | 2343 | struct audit_context *context = current->audit_context; |
| 2194 | 2344 | ||
| 2195 | context->target_pid = t->pid; | 2345 | context->target_pid = t->pid; |
| 2346 | context->target_auid = audit_get_loginuid(t); | ||
| 2347 | context->target_uid = t->uid; | ||
| 2348 | context->target_sessionid = audit_get_sessionid(t); | ||
| 2196 | selinux_get_task_sid(t, &context->target_sid); | 2349 | selinux_get_task_sid(t, &context->target_sid); |
| 2350 | memcpy(context->target_comm, t->comm, TASK_COMM_LEN); | ||
| 2197 | } | 2351 | } |
| 2198 | 2352 | ||
| 2199 | /** | 2353 | /** |
| @@ -2216,8 +2370,8 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
| 2216 | if (audit_pid && t->tgid == audit_pid) { | 2370 | if (audit_pid && t->tgid == audit_pid) { |
| 2217 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { | 2371 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { |
| 2218 | audit_sig_pid = tsk->pid; | 2372 | audit_sig_pid = tsk->pid; |
| 2219 | if (ctx) | 2373 | if (tsk->loginuid != -1) |
| 2220 | audit_sig_uid = ctx->loginuid; | 2374 | audit_sig_uid = tsk->loginuid; |
| 2221 | else | 2375 | else |
| 2222 | audit_sig_uid = tsk->uid; | 2376 | audit_sig_uid = tsk->uid; |
| 2223 | selinux_get_task_sid(tsk, &audit_sig_sid); | 2377 | selinux_get_task_sid(tsk, &audit_sig_sid); |
| @@ -2230,7 +2384,11 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
| 2230 | * in audit_context */ | 2384 | * in audit_context */ |
| 2231 | if (!ctx->target_pid) { | 2385 | if (!ctx->target_pid) { |
| 2232 | ctx->target_pid = t->tgid; | 2386 | ctx->target_pid = t->tgid; |
| 2387 | ctx->target_auid = audit_get_loginuid(t); | ||
| 2388 | ctx->target_uid = t->uid; | ||
| 2389 | ctx->target_sessionid = audit_get_sessionid(t); | ||
| 2233 | selinux_get_task_sid(t, &ctx->target_sid); | 2390 | selinux_get_task_sid(t, &ctx->target_sid); |
| 2391 | memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN); | ||
| 2234 | return 0; | 2392 | return 0; |
| 2235 | } | 2393 | } |
| 2236 | 2394 | ||
| @@ -2247,7 +2405,11 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
| 2247 | BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); | 2405 | BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); |
| 2248 | 2406 | ||
| 2249 | axp->target_pid[axp->pid_count] = t->tgid; | 2407 | axp->target_pid[axp->pid_count] = t->tgid; |
| 2408 | axp->target_auid[axp->pid_count] = audit_get_loginuid(t); | ||
| 2409 | axp->target_uid[axp->pid_count] = t->uid; | ||
| 2410 | axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); | ||
| 2250 | selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]); | 2411 | selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]); |
| 2412 | memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN); | ||
| 2251 | axp->pid_count++; | 2413 | axp->pid_count++; |
| 2252 | 2414 | ||
| 2253 | return 0; | 2415 | return 0; |
| @@ -2264,6 +2426,8 @@ void audit_core_dumps(long signr) | |||
| 2264 | { | 2426 | { |
| 2265 | struct audit_buffer *ab; | 2427 | struct audit_buffer *ab; |
| 2266 | u32 sid; | 2428 | u32 sid; |
| 2429 | uid_t auid = audit_get_loginuid(current); | ||
| 2430 | unsigned int sessionid = audit_get_sessionid(current); | ||
| 2267 | 2431 | ||
| 2268 | if (!audit_enabled) | 2432 | if (!audit_enabled) |
| 2269 | return; | 2433 | return; |
| @@ -2272,9 +2436,8 @@ void audit_core_dumps(long signr) | |||
| 2272 | return; | 2436 | return; |
| 2273 | 2437 | ||
| 2274 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); | 2438 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); |
| 2275 | audit_log_format(ab, "auid=%u uid=%u gid=%u", | 2439 | audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u", |
| 2276 | audit_get_loginuid(current->audit_context), | 2440 | auid, current->uid, current->gid, sessionid); |
| 2277 | current->uid, current->gid); | ||
| 2278 | selinux_get_task_sid(current, &sid); | 2441 | selinux_get_task_sid(current, &sid); |
| 2279 | if (sid) { | 2442 | if (sid) { |
| 2280 | char *ctx = NULL; | 2443 | char *ctx = NULL; |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 357b68ba23ec..7cb1ac3e6fff 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -81,7 +81,6 @@ extern int percpu_pagelist_fraction; | |||
| 81 | extern int compat_log; | 81 | extern int compat_log; |
| 82 | extern int maps_protect; | 82 | extern int maps_protect; |
| 83 | extern int sysctl_stat_interval; | 83 | extern int sysctl_stat_interval; |
| 84 | extern int audit_argv_kb; | ||
| 85 | extern int latencytop_enabled; | 84 | extern int latencytop_enabled; |
| 86 | 85 | ||
| 87 | /* Constants used for minimum and maximum */ | 86 | /* Constants used for minimum and maximum */ |
| @@ -390,16 +389,6 @@ static struct ctl_table kern_table[] = { | |||
| 390 | .mode = 0644, | 389 | .mode = 0644, |
| 391 | .proc_handler = &proc_dointvec, | 390 | .proc_handler = &proc_dointvec, |
| 392 | }, | 391 | }, |
| 393 | #ifdef CONFIG_AUDITSYSCALL | ||
| 394 | { | ||
| 395 | .ctl_name = CTL_UNNUMBERED, | ||
| 396 | .procname = "audit_argv_kb", | ||
| 397 | .data = &audit_argv_kb, | ||
| 398 | .maxlen = sizeof(int), | ||
| 399 | .mode = 0644, | ||
| 400 | .proc_handler = &proc_dointvec, | ||
| 401 | }, | ||
| 402 | #endif | ||
| 403 | { | 392 | { |
| 404 | .ctl_name = KERN_CORE_PATTERN, | 393 | .ctl_name = KERN_CORE_PATTERN, |
| 405 | .procname = "core_pattern", | 394 | .procname = "core_pattern", |
diff --git a/net/core/dev.c b/net/core/dev.c index edaff2720e10..9549417250bb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2752,12 +2752,15 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc) | |||
| 2752 | printk(KERN_INFO "device %s %s promiscuous mode\n", | 2752 | printk(KERN_INFO "device %s %s promiscuous mode\n", |
| 2753 | dev->name, (dev->flags & IFF_PROMISC) ? "entered" : | 2753 | dev->name, (dev->flags & IFF_PROMISC) ? "entered" : |
| 2754 | "left"); | 2754 | "left"); |
| 2755 | audit_log(current->audit_context, GFP_ATOMIC, | 2755 | if (audit_enabled) |
| 2756 | AUDIT_ANOM_PROMISCUOUS, | 2756 | audit_log(current->audit_context, GFP_ATOMIC, |
| 2757 | "dev=%s prom=%d old_prom=%d auid=%u", | 2757 | AUDIT_ANOM_PROMISCUOUS, |
| 2758 | dev->name, (dev->flags & IFF_PROMISC), | 2758 | "dev=%s prom=%d old_prom=%d auid=%u uid=%u gid=%u ses=%u", |
| 2759 | (old_flags & IFF_PROMISC), | 2759 | dev->name, (dev->flags & IFF_PROMISC), |
| 2760 | audit_get_loginuid(current->audit_context)); | 2760 | (old_flags & IFF_PROMISC), |
| 2761 | audit_get_loginuid(current), | ||
| 2762 | current->uid, current->gid, | ||
| 2763 | audit_get_sessionid(current)); | ||
| 2761 | 2764 | ||
| 2762 | if (dev->change_rx_flags) | 2765 | if (dev->change_rx_flags) |
| 2763 | dev->change_rx_flags(dev, IFF_PROMISC); | 2766 | dev->change_rx_flags(dev, IFF_PROMISC); |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 16b72b5570c3..45c3c27d279a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -1466,7 +1466,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, | |||
| 1466 | err = xfrm_state_update(x); | 1466 | err = xfrm_state_update(x); |
| 1467 | 1467 | ||
| 1468 | xfrm_audit_state_add(x, err ? 0 : 1, | 1468 | xfrm_audit_state_add(x, err ? 0 : 1, |
| 1469 | audit_get_loginuid(current->audit_context), 0); | 1469 | audit_get_loginuid(current), 0); |
| 1470 | 1470 | ||
| 1471 | if (err < 0) { | 1471 | if (err < 0) { |
| 1472 | x->km.state = XFRM_STATE_DEAD; | 1472 | x->km.state = XFRM_STATE_DEAD; |
| @@ -1520,7 +1520,7 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 1520 | km_state_notify(x, &c); | 1520 | km_state_notify(x, &c); |
| 1521 | out: | 1521 | out: |
| 1522 | xfrm_audit_state_delete(x, err ? 0 : 1, | 1522 | xfrm_audit_state_delete(x, err ? 0 : 1, |
| 1523 | audit_get_loginuid(current->audit_context), 0); | 1523 | audit_get_loginuid(current), 0); |
| 1524 | xfrm_state_put(x); | 1524 | xfrm_state_put(x); |
| 1525 | 1525 | ||
| 1526 | return err; | 1526 | return err; |
| @@ -1695,7 +1695,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd | |||
| 1695 | if (proto == 0) | 1695 | if (proto == 0) |
| 1696 | return -EINVAL; | 1696 | return -EINVAL; |
| 1697 | 1697 | ||
| 1698 | audit_info.loginuid = audit_get_loginuid(current->audit_context); | 1698 | audit_info.loginuid = audit_get_loginuid(current); |
| 1699 | audit_info.secid = 0; | 1699 | audit_info.secid = 0; |
| 1700 | err = xfrm_state_flush(proto, &audit_info); | 1700 | err = xfrm_state_flush(proto, &audit_info); |
| 1701 | if (err) | 1701 | if (err) |
| @@ -2273,7 +2273,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 2273 | hdr->sadb_msg_type != SADB_X_SPDUPDATE); | 2273 | hdr->sadb_msg_type != SADB_X_SPDUPDATE); |
| 2274 | 2274 | ||
| 2275 | xfrm_audit_policy_add(xp, err ? 0 : 1, | 2275 | xfrm_audit_policy_add(xp, err ? 0 : 1, |
| 2276 | audit_get_loginuid(current->audit_context), 0); | 2276 | audit_get_loginuid(current), 0); |
| 2277 | 2277 | ||
| 2278 | if (err) | 2278 | if (err) |
| 2279 | goto out; | 2279 | goto out; |
| @@ -2356,7 +2356,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 2356 | return -ENOENT; | 2356 | return -ENOENT; |
| 2357 | 2357 | ||
| 2358 | xfrm_audit_policy_delete(xp, err ? 0 : 1, | 2358 | xfrm_audit_policy_delete(xp, err ? 0 : 1, |
| 2359 | audit_get_loginuid(current->audit_context), 0); | 2359 | audit_get_loginuid(current), 0); |
| 2360 | 2360 | ||
| 2361 | if (err) | 2361 | if (err) |
| 2362 | goto out; | 2362 | goto out; |
| @@ -2617,7 +2617,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 2617 | 2617 | ||
| 2618 | if (delete) { | 2618 | if (delete) { |
| 2619 | xfrm_audit_policy_delete(xp, err ? 0 : 1, | 2619 | xfrm_audit_policy_delete(xp, err ? 0 : 1, |
| 2620 | audit_get_loginuid(current->audit_context), 0); | 2620 | audit_get_loginuid(current), 0); |
| 2621 | 2621 | ||
| 2622 | if (err) | 2622 | if (err) |
| 2623 | goto out; | 2623 | goto out; |
| @@ -2694,7 +2694,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 2694 | struct xfrm_audit audit_info; | 2694 | struct xfrm_audit audit_info; |
| 2695 | int err; | 2695 | int err; |
| 2696 | 2696 | ||
| 2697 | audit_info.loginuid = audit_get_loginuid(current->audit_context); | 2697 | audit_info.loginuid = audit_get_loginuid(current); |
| 2698 | audit_info.secid = 0; | 2698 | audit_info.secid = 0; |
| 2699 | err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info); | 2699 | err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info); |
| 2700 | if (err) | 2700 | if (err) |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index ff9fb6ba0c5c..1ab0da2632e1 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1238,7 +1238,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1238 | 1238 | ||
| 1239 | NETLINK_CB(skb).pid = nlk->pid; | 1239 | NETLINK_CB(skb).pid = nlk->pid; |
| 1240 | NETLINK_CB(skb).dst_group = dst_group; | 1240 | NETLINK_CB(skb).dst_group = dst_group; |
| 1241 | NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context); | 1241 | NETLINK_CB(skb).loginuid = audit_get_loginuid(current); |
| 1242 | selinux_get_task_sid(current, &(NETLINK_CB(skb).sid)); | 1242 | selinux_get_task_sid(current, &(NETLINK_CB(skb).sid)); |
| 1243 | memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); | 1243 | memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); |
| 1244 | 1244 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 3ff76e84d548..7ba65e82941c 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -493,7 +493,7 @@ expired: | |||
| 493 | km_state_expired(x, 1, 0); | 493 | km_state_expired(x, 1, 0); |
| 494 | 494 | ||
| 495 | xfrm_audit_state_delete(x, err ? 0 : 1, | 495 | xfrm_audit_state_delete(x, err ? 0 : 1, |
| 496 | audit_get_loginuid(current->audit_context), 0); | 496 | audit_get_loginuid(current), 0); |
| 497 | 497 | ||
| 498 | out: | 498 | out: |
| 499 | spin_unlock(&x->lock); | 499 | spin_unlock(&x->lock); |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index a85740530afc..0341567665b3 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -172,9 +172,10 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf, | |||
| 172 | if (length) | 172 | if (length) |
| 173 | goto out; | 173 | goto out; |
| 174 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | 174 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, |
| 175 | "enforcing=%d old_enforcing=%d auid=%u", new_value, | 175 | "enforcing=%d old_enforcing=%d auid=%u ses=%u", |
| 176 | selinux_enforcing, | 176 | new_value, selinux_enforcing, |
| 177 | audit_get_loginuid(current->audit_context)); | 177 | audit_get_loginuid(current), |
| 178 | audit_get_sessionid(current)); | ||
| 178 | selinux_enforcing = new_value; | 179 | selinux_enforcing = new_value; |
| 179 | if (selinux_enforcing) | 180 | if (selinux_enforcing) |
| 180 | avc_ss_reset(0); | 181 | avc_ss_reset(0); |
| @@ -243,8 +244,9 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf, | |||
| 243 | if (length < 0) | 244 | if (length < 0) |
| 244 | goto out; | 245 | goto out; |
| 245 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | 246 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, |
| 246 | "selinux=0 auid=%u", | 247 | "selinux=0 auid=%u ses=%u", |
| 247 | audit_get_loginuid(current->audit_context)); | 248 | audit_get_loginuid(current), |
| 249 | audit_get_sessionid(current)); | ||
| 248 | } | 250 | } |
| 249 | 251 | ||
| 250 | length = count; | 252 | length = count; |
| @@ -356,8 +358,9 @@ out1: | |||
| 356 | (security_get_allow_unknown() ? "allow" : "deny"))); | 358 | (security_get_allow_unknown() ? "allow" : "deny"))); |
| 357 | 359 | ||
| 358 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, | 360 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, |
| 359 | "policy loaded auid=%u", | 361 | "policy loaded auid=%u ses=%u", |
| 360 | audit_get_loginuid(current->audit_context)); | 362 | audit_get_loginuid(current), |
| 363 | audit_get_sessionid(current)); | ||
| 361 | out: | 364 | out: |
| 362 | mutex_unlock(&sel_mutex); | 365 | mutex_unlock(&sel_mutex); |
| 363 | vfree(data); | 366 | vfree(data); |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 880d455aa659..fced6bccee76 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -1905,11 +1905,12 @@ int security_set_bools(int len, int *values) | |||
| 1905 | if (!!values[i] != policydb.bool_val_to_struct[i]->state) { | 1905 | if (!!values[i] != policydb.bool_val_to_struct[i]->state) { |
| 1906 | audit_log(current->audit_context, GFP_ATOMIC, | 1906 | audit_log(current->audit_context, GFP_ATOMIC, |
| 1907 | AUDIT_MAC_CONFIG_CHANGE, | 1907 | AUDIT_MAC_CONFIG_CHANGE, |
| 1908 | "bool=%s val=%d old_val=%d auid=%u", | 1908 | "bool=%s val=%d old_val=%d auid=%u ses=%u", |
| 1909 | policydb.p_bool_val_to_name[i], | 1909 | policydb.p_bool_val_to_name[i], |
| 1910 | !!values[i], | 1910 | !!values[i], |
| 1911 | policydb.bool_val_to_struct[i]->state, | 1911 | policydb.bool_val_to_struct[i]->state, |
| 1912 | audit_get_loginuid(current->audit_context)); | 1912 | audit_get_loginuid(current), |
| 1913 | audit_get_sessionid(current)); | ||
| 1913 | } | 1914 | } |
| 1914 | if (values[i]) { | 1915 | if (values[i]) { |
| 1915 | policydb.bool_val_to_struct[i]->state = 1; | 1916 | policydb.bool_val_to_struct[i]->state = 1; |
