diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 150 |
1 files changed, 67 insertions, 83 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index b2d1f043f17f..6593a5207fb0 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -200,7 +200,6 @@ static int audit_match_filetype(struct audit_context *ctx, int val) | |||
200 | * References in it _are_ dropped - at the same time we free/drop aux stuff. | 200 | * References in it _are_ dropped - at the same time we free/drop aux stuff. |
201 | */ | 201 | */ |
202 | 202 | ||
203 | #ifdef CONFIG_AUDIT_TREE | ||
204 | static void audit_set_auditable(struct audit_context *ctx) | 203 | static void audit_set_auditable(struct audit_context *ctx) |
205 | { | 204 | { |
206 | if (!ctx->prio) { | 205 | if (!ctx->prio) { |
@@ -245,12 +244,10 @@ static int grow_tree_refs(struct audit_context *ctx) | |||
245 | ctx->tree_count = 31; | 244 | ctx->tree_count = 31; |
246 | return 1; | 245 | return 1; |
247 | } | 246 | } |
248 | #endif | ||
249 | 247 | ||
250 | static void unroll_tree_refs(struct audit_context *ctx, | 248 | static void unroll_tree_refs(struct audit_context *ctx, |
251 | struct audit_tree_refs *p, int count) | 249 | struct audit_tree_refs *p, int count) |
252 | { | 250 | { |
253 | #ifdef CONFIG_AUDIT_TREE | ||
254 | struct audit_tree_refs *q; | 251 | struct audit_tree_refs *q; |
255 | int n; | 252 | int n; |
256 | if (!p) { | 253 | if (!p) { |
@@ -274,7 +271,6 @@ static void unroll_tree_refs(struct audit_context *ctx, | |||
274 | } | 271 | } |
275 | ctx->trees = p; | 272 | ctx->trees = p; |
276 | ctx->tree_count = count; | 273 | ctx->tree_count = count; |
277 | #endif | ||
278 | } | 274 | } |
279 | 275 | ||
280 | static void free_tree_refs(struct audit_context *ctx) | 276 | static void free_tree_refs(struct audit_context *ctx) |
@@ -288,7 +284,6 @@ static void free_tree_refs(struct audit_context *ctx) | |||
288 | 284 | ||
289 | static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) | 285 | static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) |
290 | { | 286 | { |
291 | #ifdef CONFIG_AUDIT_TREE | ||
292 | struct audit_tree_refs *p; | 287 | struct audit_tree_refs *p; |
293 | int n; | 288 | int n; |
294 | if (!tree) | 289 | if (!tree) |
@@ -305,7 +300,6 @@ static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) | |||
305 | if (audit_tree_match(p->c[n], tree)) | 300 | if (audit_tree_match(p->c[n], tree)) |
306 | return 1; | 301 | return 1; |
307 | } | 302 | } |
308 | #endif | ||
309 | return 0; | 303 | return 0; |
310 | } | 304 | } |
311 | 305 | ||
@@ -836,44 +830,6 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) | |||
836 | rcu_read_unlock(); | 830 | rcu_read_unlock(); |
837 | } | 831 | } |
838 | 832 | ||
839 | /* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */ | ||
840 | static inline struct audit_context *audit_take_context(struct task_struct *tsk, | ||
841 | int return_valid, | ||
842 | long return_code) | ||
843 | { | ||
844 | struct audit_context *context = tsk->audit_context; | ||
845 | |||
846 | if (!context) | ||
847 | return NULL; | ||
848 | context->return_valid = return_valid; | ||
849 | |||
850 | /* | ||
851 | * we need to fix up the return code in the audit logs if the actual | ||
852 | * return codes are later going to be fixed up by the arch specific | ||
853 | * signal handlers | ||
854 | * | ||
855 | * This is actually a test for: | ||
856 | * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) || | ||
857 | * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK) | ||
858 | * | ||
859 | * but is faster than a bunch of || | ||
860 | */ | ||
861 | if (unlikely(return_code <= -ERESTARTSYS) && | ||
862 | (return_code >= -ERESTART_RESTARTBLOCK) && | ||
863 | (return_code != -ENOIOCTLCMD)) | ||
864 | context->return_code = -EINTR; | ||
865 | else | ||
866 | context->return_code = return_code; | ||
867 | |||
868 | if (context->in_syscall && !context->dummy) { | ||
869 | audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); | ||
870 | audit_filter_inodes(tsk, context); | ||
871 | } | ||
872 | |||
873 | audit_set_context(tsk, NULL); | ||
874 | return context; | ||
875 | } | ||
876 | |||
877 | static inline void audit_proctitle_free(struct audit_context *context) | 833 | static inline void audit_proctitle_free(struct audit_context *context) |
878 | { | 834 | { |
879 | kfree(context->proctitle.value); | 835 | kfree(context->proctitle.value); |
@@ -1107,7 +1063,7 @@ static void audit_log_execve_info(struct audit_context *context, | |||
1107 | } | 1063 | } |
1108 | 1064 | ||
1109 | /* write as much as we can to the audit log */ | 1065 | /* write as much as we can to the audit log */ |
1110 | if (len_buf > 0) { | 1066 | if (len_buf >= 0) { |
1111 | /* NOTE: some magic numbers here - basically if we | 1067 | /* NOTE: some magic numbers here - basically if we |
1112 | * can't fit a reasonable amount of data into the | 1068 | * can't fit a reasonable amount of data into the |
1113 | * existing audit buffer, flush it and start with | 1069 | * existing audit buffer, flush it and start with |
@@ -1302,15 +1258,18 @@ static inline int audit_proctitle_rtrim(char *proctitle, int len) | |||
1302 | return len; | 1258 | return len; |
1303 | } | 1259 | } |
1304 | 1260 | ||
1305 | static void audit_log_proctitle(struct task_struct *tsk, | 1261 | static void audit_log_proctitle(void) |
1306 | struct audit_context *context) | ||
1307 | { | 1262 | { |
1308 | int res; | 1263 | int res; |
1309 | char *buf; | 1264 | char *buf; |
1310 | char *msg = "(null)"; | 1265 | char *msg = "(null)"; |
1311 | int len = strlen(msg); | 1266 | int len = strlen(msg); |
1267 | struct audit_context *context = audit_context(); | ||
1312 | struct audit_buffer *ab; | 1268 | struct audit_buffer *ab; |
1313 | 1269 | ||
1270 | if (!context || context->dummy) | ||
1271 | return; | ||
1272 | |||
1314 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); | 1273 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); |
1315 | if (!ab) | 1274 | if (!ab) |
1316 | return; /* audit_panic or being filtered */ | 1275 | return; /* audit_panic or being filtered */ |
@@ -1323,7 +1282,7 @@ static void audit_log_proctitle(struct task_struct *tsk, | |||
1323 | if (!buf) | 1282 | if (!buf) |
1324 | goto out; | 1283 | goto out; |
1325 | /* Historically called this from procfs naming */ | 1284 | /* Historically called this from procfs naming */ |
1326 | res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN); | 1285 | res = get_cmdline(current, buf, MAX_PROCTITLE_AUDIT_LEN); |
1327 | if (res == 0) { | 1286 | if (res == 0) { |
1328 | kfree(buf); | 1287 | kfree(buf); |
1329 | goto out; | 1288 | goto out; |
@@ -1343,15 +1302,15 @@ out: | |||
1343 | audit_log_end(ab); | 1302 | audit_log_end(ab); |
1344 | } | 1303 | } |
1345 | 1304 | ||
1346 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) | 1305 | static void audit_log_exit(void) |
1347 | { | 1306 | { |
1348 | int i, call_panic = 0; | 1307 | int i, call_panic = 0; |
1308 | struct audit_context *context = audit_context(); | ||
1349 | struct audit_buffer *ab; | 1309 | struct audit_buffer *ab; |
1350 | struct audit_aux_data *aux; | 1310 | struct audit_aux_data *aux; |
1351 | struct audit_names *n; | 1311 | struct audit_names *n; |
1352 | 1312 | ||
1353 | /* tsk == current */ | 1313 | context->personality = current->personality; |
1354 | context->personality = tsk->personality; | ||
1355 | 1314 | ||
1356 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); | 1315 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); |
1357 | if (!ab) | 1316 | if (!ab) |
@@ -1373,7 +1332,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1373 | context->argv[3], | 1332 | context->argv[3], |
1374 | context->name_count); | 1333 | context->name_count); |
1375 | 1334 | ||
1376 | audit_log_task_info(ab, tsk); | 1335 | audit_log_task_info(ab); |
1377 | audit_log_key(ab, context->filterkey); | 1336 | audit_log_key(ab, context->filterkey); |
1378 | audit_log_end(ab); | 1337 | audit_log_end(ab); |
1379 | 1338 | ||
@@ -1462,7 +1421,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1462 | audit_log_name(context, n, NULL, i++, &call_panic); | 1421 | audit_log_name(context, n, NULL, i++, &call_panic); |
1463 | } | 1422 | } |
1464 | 1423 | ||
1465 | audit_log_proctitle(tsk, context); | 1424 | audit_log_proctitle(); |
1466 | 1425 | ||
1467 | /* Send end of event record to help user space know we are finished */ | 1426 | /* Send end of event record to help user space know we are finished */ |
1468 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); | 1427 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); |
@@ -1480,22 +1439,31 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1480 | */ | 1439 | */ |
1481 | void __audit_free(struct task_struct *tsk) | 1440 | void __audit_free(struct task_struct *tsk) |
1482 | { | 1441 | { |
1483 | struct audit_context *context; | 1442 | struct audit_context *context = tsk->audit_context; |
1484 | 1443 | ||
1485 | context = audit_take_context(tsk, 0, 0); | ||
1486 | if (!context) | 1444 | if (!context) |
1487 | return; | 1445 | return; |
1488 | 1446 | ||
1489 | /* Check for system calls that do not go through the exit | 1447 | /* We are called either by do_exit() or the fork() error handling code; |
1490 | * function (e.g., exit_group), then free context block. | 1448 | * in the former case tsk == current and in the latter tsk is a |
1491 | * We use GFP_ATOMIC here because we might be doing this | 1449 | * random task_struct that doesn't doesn't have any meaningful data we |
1492 | * in the context of the idle thread */ | 1450 | * need to log via audit_log_exit(). |
1493 | /* that can happen only if we are called from do_exit() */ | 1451 | */ |
1494 | if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) | 1452 | if (tsk == current && !context->dummy && context->in_syscall) { |
1495 | audit_log_exit(context, tsk); | 1453 | context->return_valid = 0; |
1454 | context->return_code = 0; | ||
1455 | |||
1456 | audit_filter_syscall(tsk, context, | ||
1457 | &audit_filter_list[AUDIT_FILTER_EXIT]); | ||
1458 | audit_filter_inodes(tsk, context); | ||
1459 | if (context->current_state == AUDIT_RECORD_CONTEXT) | ||
1460 | audit_log_exit(); | ||
1461 | } | ||
1462 | |||
1496 | if (!list_empty(&context->killed_trees)) | 1463 | if (!list_empty(&context->killed_trees)) |
1497 | audit_kill_trees(&context->killed_trees); | 1464 | audit_kill_trees(&context->killed_trees); |
1498 | 1465 | ||
1466 | audit_set_context(tsk, NULL); | ||
1499 | audit_free_context(context); | 1467 | audit_free_context(context); |
1500 | } | 1468 | } |
1501 | 1469 | ||
@@ -1565,17 +1533,40 @@ void __audit_syscall_exit(int success, long return_code) | |||
1565 | { | 1533 | { |
1566 | struct audit_context *context; | 1534 | struct audit_context *context; |
1567 | 1535 | ||
1568 | if (success) | 1536 | context = audit_context(); |
1569 | success = AUDITSC_SUCCESS; | ||
1570 | else | ||
1571 | success = AUDITSC_FAILURE; | ||
1572 | |||
1573 | context = audit_take_context(current, success, return_code); | ||
1574 | if (!context) | 1537 | if (!context) |
1575 | return; | 1538 | return; |
1576 | 1539 | ||
1577 | if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) | 1540 | if (!context->dummy && context->in_syscall) { |
1578 | audit_log_exit(context, current); | 1541 | if (success) |
1542 | context->return_valid = AUDITSC_SUCCESS; | ||
1543 | else | ||
1544 | context->return_valid = AUDITSC_FAILURE; | ||
1545 | |||
1546 | /* | ||
1547 | * we need to fix up the return code in the audit logs if the | ||
1548 | * actual return codes are later going to be fixed up by the | ||
1549 | * arch specific signal handlers | ||
1550 | * | ||
1551 | * This is actually a test for: | ||
1552 | * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) || | ||
1553 | * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK) | ||
1554 | * | ||
1555 | * but is faster than a bunch of || | ||
1556 | */ | ||
1557 | if (unlikely(return_code <= -ERESTARTSYS) && | ||
1558 | (return_code >= -ERESTART_RESTARTBLOCK) && | ||
1559 | (return_code != -ENOIOCTLCMD)) | ||
1560 | context->return_code = -EINTR; | ||
1561 | else | ||
1562 | context->return_code = return_code; | ||
1563 | |||
1564 | audit_filter_syscall(current, context, | ||
1565 | &audit_filter_list[AUDIT_FILTER_EXIT]); | ||
1566 | audit_filter_inodes(current, context); | ||
1567 | if (context->current_state == AUDIT_RECORD_CONTEXT) | ||
1568 | audit_log_exit(); | ||
1569 | } | ||
1579 | 1570 | ||
1580 | context->in_syscall = 0; | 1571 | context->in_syscall = 0; |
1581 | context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; | 1572 | context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; |
@@ -1597,12 +1588,10 @@ void __audit_syscall_exit(int success, long return_code) | |||
1597 | kfree(context->filterkey); | 1588 | kfree(context->filterkey); |
1598 | context->filterkey = NULL; | 1589 | context->filterkey = NULL; |
1599 | } | 1590 | } |
1600 | audit_set_context(current, context); | ||
1601 | } | 1591 | } |
1602 | 1592 | ||
1603 | static inline void handle_one(const struct inode *inode) | 1593 | static inline void handle_one(const struct inode *inode) |
1604 | { | 1594 | { |
1605 | #ifdef CONFIG_AUDIT_TREE | ||
1606 | struct audit_context *context; | 1595 | struct audit_context *context; |
1607 | struct audit_tree_refs *p; | 1596 | struct audit_tree_refs *p; |
1608 | struct audit_chunk *chunk; | 1597 | struct audit_chunk *chunk; |
@@ -1627,12 +1616,10 @@ static inline void handle_one(const struct inode *inode) | |||
1627 | return; | 1616 | return; |
1628 | } | 1617 | } |
1629 | put_tree_ref(context, chunk); | 1618 | put_tree_ref(context, chunk); |
1630 | #endif | ||
1631 | } | 1619 | } |
1632 | 1620 | ||
1633 | static void handle_path(const struct dentry *dentry) | 1621 | static void handle_path(const struct dentry *dentry) |
1634 | { | 1622 | { |
1635 | #ifdef CONFIG_AUDIT_TREE | ||
1636 | struct audit_context *context; | 1623 | struct audit_context *context; |
1637 | struct audit_tree_refs *p; | 1624 | struct audit_tree_refs *p; |
1638 | const struct dentry *d, *parent; | 1625 | const struct dentry *d, *parent; |
@@ -1685,7 +1672,6 @@ retry: | |||
1685 | return; | 1672 | return; |
1686 | } | 1673 | } |
1687 | rcu_read_unlock(); | 1674 | rcu_read_unlock(); |
1688 | #endif | ||
1689 | } | 1675 | } |
1690 | 1676 | ||
1691 | static struct audit_names *audit_alloc_name(struct audit_context *context, | 1677 | static struct audit_names *audit_alloc_name(struct audit_context *context, |
@@ -2035,7 +2021,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, | |||
2035 | uid = from_kuid(&init_user_ns, task_uid(current)); | 2021 | uid = from_kuid(&init_user_ns, task_uid(current)); |
2036 | oldloginuid = from_kuid(&init_user_ns, koldloginuid); | 2022 | oldloginuid = from_kuid(&init_user_ns, koldloginuid); |
2037 | loginuid = from_kuid(&init_user_ns, kloginuid), | 2023 | loginuid = from_kuid(&init_user_ns, kloginuid), |
2038 | tty = audit_get_tty(current); | 2024 | tty = audit_get_tty(); |
2039 | 2025 | ||
2040 | audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid); | 2026 | audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid); |
2041 | audit_log_task_context(ab); | 2027 | audit_log_task_context(ab); |
@@ -2056,7 +2042,6 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, | |||
2056 | */ | 2042 | */ |
2057 | int audit_set_loginuid(kuid_t loginuid) | 2043 | int audit_set_loginuid(kuid_t loginuid) |
2058 | { | 2044 | { |
2059 | struct task_struct *task = current; | ||
2060 | unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; | 2045 | unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; |
2061 | kuid_t oldloginuid; | 2046 | kuid_t oldloginuid; |
2062 | int rc; | 2047 | int rc; |
@@ -2075,8 +2060,8 @@ int audit_set_loginuid(kuid_t loginuid) | |||
2075 | sessionid = (unsigned int)atomic_inc_return(&session_id); | 2060 | sessionid = (unsigned int)atomic_inc_return(&session_id); |
2076 | } | 2061 | } |
2077 | 2062 | ||
2078 | task->sessionid = sessionid; | 2063 | current->sessionid = sessionid; |
2079 | task->loginuid = loginuid; | 2064 | current->loginuid = loginuid; |
2080 | out: | 2065 | out: |
2081 | audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); | 2066 | audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); |
2082 | return rc; | 2067 | return rc; |
@@ -2513,10 +2498,9 @@ void audit_seccomp_actions_logged(const char *names, const char *old_names, | |||
2513 | if (unlikely(!ab)) | 2498 | if (unlikely(!ab)) |
2514 | return; | 2499 | return; |
2515 | 2500 | ||
2516 | audit_log_format(ab, "op=seccomp-logging"); | 2501 | audit_log_format(ab, |
2517 | audit_log_format(ab, " actions=%s", names); | 2502 | "op=seccomp-logging actions=%s old-actions=%s res=%d", |
2518 | audit_log_format(ab, " old-actions=%s", old_names); | 2503 | names, old_names, res); |
2519 | audit_log_format(ab, " res=%d", res); | ||
2520 | audit_log_end(ab); | 2504 | audit_log_end(ab); |
2521 | } | 2505 | } |
2522 | 2506 | ||