diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 133 |
1 files changed, 100 insertions, 33 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 7aef2f4b6c64..f251a5e8d17a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -42,6 +42,8 @@ | |||
42 | * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance. | 42 | * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance. |
43 | */ | 43 | */ |
44 | 44 | ||
45 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
46 | |||
45 | #include <linux/init.h> | 47 | #include <linux/init.h> |
46 | #include <asm/types.h> | 48 | #include <asm/types.h> |
47 | #include <linux/atomic.h> | 49 | #include <linux/atomic.h> |
@@ -68,6 +70,7 @@ | |||
68 | #include <linux/capability.h> | 70 | #include <linux/capability.h> |
69 | #include <linux/fs_struct.h> | 71 | #include <linux/fs_struct.h> |
70 | #include <linux/compat.h> | 72 | #include <linux/compat.h> |
73 | #include <linux/ctype.h> | ||
71 | 74 | ||
72 | #include "audit.h" | 75 | #include "audit.h" |
73 | 76 | ||
@@ -79,6 +82,9 @@ | |||
79 | /* no execve audit message should be longer than this (userspace limits) */ | 82 | /* no execve audit message should be longer than this (userspace limits) */ |
80 | #define MAX_EXECVE_AUDIT_LEN 7500 | 83 | #define MAX_EXECVE_AUDIT_LEN 7500 |
81 | 84 | ||
85 | /* max length to print of cmdline/proctitle value during audit */ | ||
86 | #define MAX_PROCTITLE_AUDIT_LEN 128 | ||
87 | |||
82 | /* number of audit rules */ | 88 | /* number of audit rules */ |
83 | int audit_n_rules; | 89 | int audit_n_rules; |
84 | 90 | ||
@@ -451,15 +457,17 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
451 | struct audit_field *f = &rule->fields[i]; | 457 | struct audit_field *f = &rule->fields[i]; |
452 | struct audit_names *n; | 458 | struct audit_names *n; |
453 | int result = 0; | 459 | int result = 0; |
460 | pid_t pid; | ||
454 | 461 | ||
455 | switch (f->type) { | 462 | switch (f->type) { |
456 | case AUDIT_PID: | 463 | case AUDIT_PID: |
457 | result = audit_comparator(tsk->pid, f->op, f->val); | 464 | pid = task_pid_nr(tsk); |
465 | result = audit_comparator(pid, f->op, f->val); | ||
458 | break; | 466 | break; |
459 | case AUDIT_PPID: | 467 | case AUDIT_PPID: |
460 | if (ctx) { | 468 | if (ctx) { |
461 | if (!ctx->ppid) | 469 | if (!ctx->ppid) |
462 | ctx->ppid = sys_getppid(); | 470 | ctx->ppid = task_ppid_nr(tsk); |
463 | result = audit_comparator(ctx->ppid, f->op, f->val); | 471 | result = audit_comparator(ctx->ppid, f->op, f->val); |
464 | } | 472 | } |
465 | break; | 473 | break; |
@@ -805,7 +813,8 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) | |||
805 | rcu_read_unlock(); | 813 | rcu_read_unlock(); |
806 | } | 814 | } |
807 | 815 | ||
808 | static inline struct audit_context *audit_get_context(struct task_struct *tsk, | 816 | /* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */ |
817 | static inline struct audit_context *audit_take_context(struct task_struct *tsk, | ||
809 | int return_valid, | 818 | int return_valid, |
810 | long return_code) | 819 | long return_code) |
811 | { | 820 | { |
@@ -842,6 +851,13 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
842 | return context; | 851 | return context; |
843 | } | 852 | } |
844 | 853 | ||
854 | static inline void audit_proctitle_free(struct audit_context *context) | ||
855 | { | ||
856 | kfree(context->proctitle.value); | ||
857 | context->proctitle.value = NULL; | ||
858 | context->proctitle.len = 0; | ||
859 | } | ||
860 | |||
845 | static inline void audit_free_names(struct audit_context *context) | 861 | static inline void audit_free_names(struct audit_context *context) |
846 | { | 862 | { |
847 | struct audit_names *n, *next; | 863 | struct audit_names *n, *next; |
@@ -850,16 +866,15 @@ static inline void audit_free_names(struct audit_context *context) | |||
850 | if (context->put_count + context->ino_count != context->name_count) { | 866 | if (context->put_count + context->ino_count != context->name_count) { |
851 | int i = 0; | 867 | int i = 0; |
852 | 868 | ||
853 | printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" | 869 | pr_err("%s:%d(:%d): major=%d in_syscall=%d" |
854 | " name_count=%d put_count=%d" | 870 | " name_count=%d put_count=%d ino_count=%d" |
855 | " ino_count=%d [NOT freeing]\n", | 871 | " [NOT freeing]\n", __FILE__, __LINE__, |
856 | __FILE__, __LINE__, | ||
857 | context->serial, context->major, context->in_syscall, | 872 | context->serial, context->major, context->in_syscall, |
858 | context->name_count, context->put_count, | 873 | context->name_count, context->put_count, |
859 | context->ino_count); | 874 | context->ino_count); |
860 | list_for_each_entry(n, &context->names_list, list) { | 875 | list_for_each_entry(n, &context->names_list, list) { |
861 | printk(KERN_ERR "names[%d] = %p = %s\n", i++, | 876 | pr_err("names[%d] = %p = %s\n", i++, n->name, |
862 | n->name, n->name->name ?: "(null)"); | 877 | n->name->name ?: "(null)"); |
863 | } | 878 | } |
864 | dump_stack(); | 879 | dump_stack(); |
865 | return; | 880 | return; |
@@ -955,6 +970,7 @@ static inline void audit_free_context(struct audit_context *context) | |||
955 | audit_free_aux(context); | 970 | audit_free_aux(context); |
956 | kfree(context->filterkey); | 971 | kfree(context->filterkey); |
957 | kfree(context->sockaddr); | 972 | kfree(context->sockaddr); |
973 | audit_proctitle_free(context); | ||
958 | kfree(context); | 974 | kfree(context); |
959 | } | 975 | } |
960 | 976 | ||
@@ -1157,7 +1173,7 @@ static void audit_log_execve_info(struct audit_context *context, | |||
1157 | */ | 1173 | */ |
1158 | buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); | 1174 | buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); |
1159 | if (!buf) { | 1175 | if (!buf) { |
1160 | audit_panic("out of memory for argv string\n"); | 1176 | audit_panic("out of memory for argv string"); |
1161 | return; | 1177 | return; |
1162 | } | 1178 | } |
1163 | 1179 | ||
@@ -1271,6 +1287,59 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
1271 | audit_log_end(ab); | 1287 | audit_log_end(ab); |
1272 | } | 1288 | } |
1273 | 1289 | ||
1290 | static inline int audit_proctitle_rtrim(char *proctitle, int len) | ||
1291 | { | ||
1292 | char *end = proctitle + len - 1; | ||
1293 | while (end > proctitle && !isprint(*end)) | ||
1294 | end--; | ||
1295 | |||
1296 | /* catch the case where proctitle is only 1 non-print character */ | ||
1297 | len = end - proctitle + 1; | ||
1298 | len -= isprint(proctitle[len-1]) == 0; | ||
1299 | return len; | ||
1300 | } | ||
1301 | |||
1302 | static void audit_log_proctitle(struct task_struct *tsk, | ||
1303 | struct audit_context *context) | ||
1304 | { | ||
1305 | int res; | ||
1306 | char *buf; | ||
1307 | char *msg = "(null)"; | ||
1308 | int len = strlen(msg); | ||
1309 | struct audit_buffer *ab; | ||
1310 | |||
1311 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); | ||
1312 | if (!ab) | ||
1313 | return; /* audit_panic or being filtered */ | ||
1314 | |||
1315 | audit_log_format(ab, "proctitle="); | ||
1316 | |||
1317 | /* Not cached */ | ||
1318 | if (!context->proctitle.value) { | ||
1319 | buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL); | ||
1320 | if (!buf) | ||
1321 | goto out; | ||
1322 | /* Historically called this from procfs naming */ | ||
1323 | res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN); | ||
1324 | if (res == 0) { | ||
1325 | kfree(buf); | ||
1326 | goto out; | ||
1327 | } | ||
1328 | res = audit_proctitle_rtrim(buf, res); | ||
1329 | if (res == 0) { | ||
1330 | kfree(buf); | ||
1331 | goto out; | ||
1332 | } | ||
1333 | context->proctitle.value = buf; | ||
1334 | context->proctitle.len = res; | ||
1335 | } | ||
1336 | msg = context->proctitle.value; | ||
1337 | len = context->proctitle.len; | ||
1338 | out: | ||
1339 | audit_log_n_untrustedstring(ab, msg, len); | ||
1340 | audit_log_end(ab); | ||
1341 | } | ||
1342 | |||
1274 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) | 1343 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
1275 | { | 1344 | { |
1276 | int i, call_panic = 0; | 1345 | int i, call_panic = 0; |
@@ -1388,6 +1457,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1388 | audit_log_name(context, n, NULL, i++, &call_panic); | 1457 | audit_log_name(context, n, NULL, i++, &call_panic); |
1389 | } | 1458 | } |
1390 | 1459 | ||
1460 | audit_log_proctitle(tsk, context); | ||
1461 | |||
1391 | /* Send end of event record to help user space know we are finished */ | 1462 | /* Send end of event record to help user space know we are finished */ |
1392 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); | 1463 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); |
1393 | if (ab) | 1464 | if (ab) |
@@ -1406,7 +1477,7 @@ void __audit_free(struct task_struct *tsk) | |||
1406 | { | 1477 | { |
1407 | struct audit_context *context; | 1478 | struct audit_context *context; |
1408 | 1479 | ||
1409 | context = audit_get_context(tsk, 0, 0); | 1480 | context = audit_take_context(tsk, 0, 0); |
1410 | if (!context) | 1481 | if (!context) |
1411 | return; | 1482 | return; |
1412 | 1483 | ||
@@ -1500,7 +1571,7 @@ void __audit_syscall_exit(int success, long return_code) | |||
1500 | else | 1571 | else |
1501 | success = AUDITSC_FAILURE; | 1572 | success = AUDITSC_FAILURE; |
1502 | 1573 | ||
1503 | context = audit_get_context(tsk, success, return_code); | 1574 | context = audit_take_context(tsk, success, return_code); |
1504 | if (!context) | 1575 | if (!context) |
1505 | return; | 1576 | return; |
1506 | 1577 | ||
@@ -1550,7 +1621,7 @@ static inline void handle_one(const struct inode *inode) | |||
1550 | if (likely(put_tree_ref(context, chunk))) | 1621 | if (likely(put_tree_ref(context, chunk))) |
1551 | return; | 1622 | return; |
1552 | if (unlikely(!grow_tree_refs(context))) { | 1623 | if (unlikely(!grow_tree_refs(context))) { |
1553 | printk(KERN_WARNING "out of memory, audit has lost a tree reference\n"); | 1624 | pr_warn("out of memory, audit has lost a tree reference\n"); |
1554 | audit_set_auditable(context); | 1625 | audit_set_auditable(context); |
1555 | audit_put_chunk(chunk); | 1626 | audit_put_chunk(chunk); |
1556 | unroll_tree_refs(context, p, count); | 1627 | unroll_tree_refs(context, p, count); |
@@ -1609,8 +1680,7 @@ retry: | |||
1609 | goto retry; | 1680 | goto retry; |
1610 | } | 1681 | } |
1611 | /* too bad */ | 1682 | /* too bad */ |
1612 | printk(KERN_WARNING | 1683 | pr_warn("out of memory, audit has lost a tree reference\n"); |
1613 | "out of memory, audit has lost a tree reference\n"); | ||
1614 | unroll_tree_refs(context, p, count); | 1684 | unroll_tree_refs(context, p, count); |
1615 | audit_set_auditable(context); | 1685 | audit_set_auditable(context); |
1616 | return; | 1686 | return; |
@@ -1682,7 +1752,7 @@ void __audit_getname(struct filename *name) | |||
1682 | 1752 | ||
1683 | if (!context->in_syscall) { | 1753 | if (!context->in_syscall) { |
1684 | #if AUDIT_DEBUG == 2 | 1754 | #if AUDIT_DEBUG == 2 |
1685 | printk(KERN_ERR "%s:%d(:%d): ignoring getname(%p)\n", | 1755 | pr_err("%s:%d(:%d): ignoring getname(%p)\n", |
1686 | __FILE__, __LINE__, context->serial, name); | 1756 | __FILE__, __LINE__, context->serial, name); |
1687 | dump_stack(); | 1757 | dump_stack(); |
1688 | #endif | 1758 | #endif |
@@ -1721,15 +1791,15 @@ void audit_putname(struct filename *name) | |||
1721 | BUG_ON(!context); | 1791 | BUG_ON(!context); |
1722 | if (!name->aname || !context->in_syscall) { | 1792 | if (!name->aname || !context->in_syscall) { |
1723 | #if AUDIT_DEBUG == 2 | 1793 | #if AUDIT_DEBUG == 2 |
1724 | printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n", | 1794 | pr_err("%s:%d(:%d): final_putname(%p)\n", |
1725 | __FILE__, __LINE__, context->serial, name); | 1795 | __FILE__, __LINE__, context->serial, name); |
1726 | if (context->name_count) { | 1796 | if (context->name_count) { |
1727 | struct audit_names *n; | 1797 | struct audit_names *n; |
1728 | int i = 0; | 1798 | int i = 0; |
1729 | 1799 | ||
1730 | list_for_each_entry(n, &context->names_list, list) | 1800 | list_for_each_entry(n, &context->names_list, list) |
1731 | printk(KERN_ERR "name[%d] = %p = %s\n", i++, | 1801 | pr_err("name[%d] = %p = %s\n", i++, n->name, |
1732 | n->name, n->name->name ?: "(null)"); | 1802 | n->name->name ?: "(null)"); |
1733 | } | 1803 | } |
1734 | #endif | 1804 | #endif |
1735 | final_putname(name); | 1805 | final_putname(name); |
@@ -1738,9 +1808,8 @@ void audit_putname(struct filename *name) | |||
1738 | else { | 1808 | else { |
1739 | ++context->put_count; | 1809 | ++context->put_count; |
1740 | if (context->put_count > context->name_count) { | 1810 | if (context->put_count > context->name_count) { |
1741 | printk(KERN_ERR "%s:%d(:%d): major=%d" | 1811 | pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)" |
1742 | " in_syscall=%d putname(%p) name_count=%d" | 1812 | " name_count=%d put_count=%d\n", |
1743 | " put_count=%d\n", | ||
1744 | __FILE__, __LINE__, | 1813 | __FILE__, __LINE__, |
1745 | context->serial, context->major, | 1814 | context->serial, context->major, |
1746 | context->in_syscall, name->name, | 1815 | context->in_syscall, name->name, |
@@ -1981,12 +2050,10 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, | |||
1981 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); | 2050 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); |
1982 | if (!ab) | 2051 | if (!ab) |
1983 | return; | 2052 | return; |
1984 | audit_log_format(ab, "pid=%d uid=%u" | 2053 | audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); |
1985 | " old-auid=%u new-auid=%u old-ses=%u new-ses=%u" | 2054 | audit_log_task_context(ab); |
1986 | " res=%d", | 2055 | audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", |
1987 | current->pid, uid, | 2056 | oldloginuid, loginuid, oldsessionid, sessionid, !rc); |
1988 | oldloginuid, loginuid, oldsessionid, sessionid, | ||
1989 | !rc); | ||
1990 | audit_log_end(ab); | 2057 | audit_log_end(ab); |
1991 | } | 2058 | } |
1992 | 2059 | ||
@@ -2208,7 +2275,7 @@ void __audit_ptrace(struct task_struct *t) | |||
2208 | { | 2275 | { |
2209 | struct audit_context *context = current->audit_context; | 2276 | struct audit_context *context = current->audit_context; |
2210 | 2277 | ||
2211 | context->target_pid = t->pid; | 2278 | context->target_pid = task_pid_nr(t); |
2212 | context->target_auid = audit_get_loginuid(t); | 2279 | context->target_auid = audit_get_loginuid(t); |
2213 | context->target_uid = task_uid(t); | 2280 | context->target_uid = task_uid(t); |
2214 | context->target_sessionid = audit_get_sessionid(t); | 2281 | context->target_sessionid = audit_get_sessionid(t); |
@@ -2233,7 +2300,7 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
2233 | 2300 | ||
2234 | if (audit_pid && t->tgid == audit_pid) { | 2301 | if (audit_pid && t->tgid == audit_pid) { |
2235 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { | 2302 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { |
2236 | audit_sig_pid = tsk->pid; | 2303 | audit_sig_pid = task_pid_nr(tsk); |
2237 | if (uid_valid(tsk->loginuid)) | 2304 | if (uid_valid(tsk->loginuid)) |
2238 | audit_sig_uid = tsk->loginuid; | 2305 | audit_sig_uid = tsk->loginuid; |
2239 | else | 2306 | else |
@@ -2247,7 +2314,7 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
2247 | /* optimize the common case by putting first signal recipient directly | 2314 | /* optimize the common case by putting first signal recipient directly |
2248 | * in audit_context */ | 2315 | * in audit_context */ |
2249 | if (!ctx->target_pid) { | 2316 | if (!ctx->target_pid) { |
2250 | ctx->target_pid = t->tgid; | 2317 | ctx->target_pid = task_tgid_nr(t); |
2251 | ctx->target_auid = audit_get_loginuid(t); | 2318 | ctx->target_auid = audit_get_loginuid(t); |
2252 | ctx->target_uid = t_uid; | 2319 | ctx->target_uid = t_uid; |
2253 | ctx->target_sessionid = audit_get_sessionid(t); | 2320 | ctx->target_sessionid = audit_get_sessionid(t); |
@@ -2268,7 +2335,7 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
2268 | } | 2335 | } |
2269 | BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); | 2336 | BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); |
2270 | 2337 | ||
2271 | axp->target_pid[axp->pid_count] = t->tgid; | 2338 | axp->target_pid[axp->pid_count] = task_tgid_nr(t); |
2272 | axp->target_auid[axp->pid_count] = audit_get_loginuid(t); | 2339 | axp->target_auid[axp->pid_count] = audit_get_loginuid(t); |
2273 | axp->target_uid[axp->pid_count] = t_uid; | 2340 | axp->target_uid[axp->pid_count] = t_uid; |
2274 | axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); | 2341 | axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); |
@@ -2368,7 +2435,7 @@ static void audit_log_task(struct audit_buffer *ab) | |||
2368 | from_kgid(&init_user_ns, gid), | 2435 | from_kgid(&init_user_ns, gid), |
2369 | sessionid); | 2436 | sessionid); |
2370 | audit_log_task_context(ab); | 2437 | audit_log_task_context(ab); |
2371 | audit_log_format(ab, " pid=%d comm=", current->pid); | 2438 | audit_log_format(ab, " pid=%d comm=", task_pid_nr(current)); |
2372 | audit_log_untrustedstring(ab, current->comm); | 2439 | audit_log_untrustedstring(ab, current->comm); |
2373 | if (mm) { | 2440 | if (mm) { |
2374 | down_read(&mm->mmap_sem); | 2441 | down_read(&mm->mmap_sem); |