| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* audit.c -- Auditing support |
|---|
| 2 | 3 | * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. |
|---|
| 3 | 4 | * System-call specific features have moved to auditsc.c |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina. |
|---|
| 6 | 7 | * All Rights Reserved. |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 10 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | - * (at your option) any later version. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | | - * GNU General Public License for more details. |
|---|
| 17 | | - * |
|---|
| 18 | | - * You should have received a copy of the GNU General Public License |
|---|
| 19 | | - * along with this program; if not, write to the Free Software |
|---|
| 20 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 21 | 8 | * |
|---|
| 22 | 9 | * Written by Rickard E. (Rik) Faith <faith@redhat.com> |
|---|
| 23 | 10 | * |
|---|
| .. | .. |
|---|
| 60 | 47 | #include <linux/mutex.h> |
|---|
| 61 | 48 | #include <linux/gfp.h> |
|---|
| 62 | 49 | #include <linux/pid.h> |
|---|
| 63 | | -#include <linux/slab.h> |
|---|
| 64 | 50 | |
|---|
| 65 | 51 | #include <linux/audit.h> |
|---|
| 66 | 52 | |
|---|
| .. | .. |
|---|
| 116 | 102 | * This struct is RCU protected; you must either hold the RCU lock for reading |
|---|
| 117 | 103 | * or the associated spinlock for writing. |
|---|
| 118 | 104 | */ |
|---|
| 119 | | -static struct auditd_connection { |
|---|
| 105 | +struct auditd_connection { |
|---|
| 120 | 106 | struct pid *pid; |
|---|
| 121 | 107 | u32 portid; |
|---|
| 122 | 108 | struct net *net; |
|---|
| 123 | 109 | struct rcu_head rcu; |
|---|
| 124 | | -} *auditd_conn = NULL; |
|---|
| 110 | +}; |
|---|
| 111 | +static struct auditd_connection __rcu *auditd_conn; |
|---|
| 125 | 112 | static DEFINE_SPINLOCK(auditd_conn_lock); |
|---|
| 126 | 113 | |
|---|
| 127 | 114 | /* If audit_rate_limit is non-zero, limit the rate of sending audit records |
|---|
| .. | .. |
|---|
| 136 | 123 | static u32 audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; |
|---|
| 137 | 124 | |
|---|
| 138 | 125 | /* The identity of the user shutting down the audit system. */ |
|---|
| 139 | | -kuid_t audit_sig_uid = INVALID_UID; |
|---|
| 140 | | -pid_t audit_sig_pid = -1; |
|---|
| 141 | | -u32 audit_sig_sid = 0; |
|---|
| 126 | +static kuid_t audit_sig_uid = INVALID_UID; |
|---|
| 127 | +static pid_t audit_sig_pid = -1; |
|---|
| 128 | +static u32 audit_sig_sid; |
|---|
| 142 | 129 | |
|---|
| 143 | 130 | /* Records can be lost in several ways: |
|---|
| 144 | 131 | 0) [suppressed in audit_alloc] |
|---|
| .. | .. |
|---|
| 148 | 135 | 4) suppressed due to audit_backlog_limit |
|---|
| 149 | 136 | */ |
|---|
| 150 | 137 | static atomic_t audit_lost = ATOMIC_INIT(0); |
|---|
| 138 | + |
|---|
| 139 | +/* Monotonically increasing sum of time the kernel has spent |
|---|
| 140 | + * waiting while the backlog limit is exceeded. |
|---|
| 141 | + */ |
|---|
| 142 | +static atomic_t audit_backlog_wait_time_actual = ATOMIC_INIT(0); |
|---|
| 151 | 143 | |
|---|
| 152 | 144 | /* Hash for inode-based rules */ |
|---|
| 153 | 145 | struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; |
|---|
| .. | .. |
|---|
| 397 | 389 | struct audit_buffer *ab; |
|---|
| 398 | 390 | int rc = 0; |
|---|
| 399 | 391 | |
|---|
| 400 | | - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
|---|
| 392 | + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
|---|
| 401 | 393 | if (unlikely(!ab)) |
|---|
| 402 | 394 | return rc; |
|---|
| 403 | | - audit_log_format(ab, "%s=%u old=%u", function_name, new, old); |
|---|
| 395 | + audit_log_format(ab, "op=set %s=%u old=%u ", function_name, new, old); |
|---|
| 404 | 396 | audit_log_session_info(ab); |
|---|
| 405 | 397 | rc = audit_log_task_context(ab); |
|---|
| 406 | 398 | if (rc) |
|---|
| .. | .. |
|---|
| 866 | 858 | rc = kauditd_send_queue(sk, portid, |
|---|
| 867 | 859 | &audit_hold_queue, UNICAST_RETRIES, |
|---|
| 868 | 860 | NULL, kauditd_rehold_skb); |
|---|
| 869 | | - if (ac && rc < 0) { |
|---|
| 861 | + if (rc < 0) { |
|---|
| 870 | 862 | sk = NULL; |
|---|
| 871 | 863 | auditd_reset(ac); |
|---|
| 872 | 864 | goto main_queue; |
|---|
| .. | .. |
|---|
| 876 | 868 | rc = kauditd_send_queue(sk, portid, |
|---|
| 877 | 869 | &audit_retry_queue, UNICAST_RETRIES, |
|---|
| 878 | 870 | NULL, kauditd_hold_skb); |
|---|
| 879 | | - if (ac && rc < 0) { |
|---|
| 871 | + if (rc < 0) { |
|---|
| 880 | 872 | sk = NULL; |
|---|
| 881 | 873 | auditd_reset(ac); |
|---|
| 882 | 874 | goto main_queue; |
|---|
| .. | .. |
|---|
| 964 | 956 | if (!reply) |
|---|
| 965 | 957 | return; |
|---|
| 966 | 958 | |
|---|
| 967 | | - if (reply->skb) |
|---|
| 968 | | - kfree_skb(reply->skb); |
|---|
| 959 | + kfree_skb(reply->skb); |
|---|
| 969 | 960 | if (reply->net) |
|---|
| 970 | 961 | put_net(reply->net); |
|---|
| 971 | 962 | kfree(reply); |
|---|
| .. | .. |
|---|
| 1084 | 1075 | return err; |
|---|
| 1085 | 1076 | } |
|---|
| 1086 | 1077 | |
|---|
| 1087 | | -static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) |
|---|
| 1078 | +static void audit_log_common_recv_msg(struct audit_context *context, |
|---|
| 1079 | + struct audit_buffer **ab, u16 msg_type) |
|---|
| 1088 | 1080 | { |
|---|
| 1089 | 1081 | uid_t uid = from_kuid(&init_user_ns, current_uid()); |
|---|
| 1090 | 1082 | pid_t pid = task_tgid_nr(current); |
|---|
| .. | .. |
|---|
| 1094 | 1086 | return; |
|---|
| 1095 | 1087 | } |
|---|
| 1096 | 1088 | |
|---|
| 1097 | | - *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
|---|
| 1089 | + *ab = audit_log_start(context, GFP_KERNEL, msg_type); |
|---|
| 1098 | 1090 | if (unlikely(!*ab)) |
|---|
| 1099 | 1091 | return; |
|---|
| 1100 | | - audit_log_format(*ab, "pid=%d uid=%u", pid, uid); |
|---|
| 1092 | + audit_log_format(*ab, "pid=%d uid=%u ", pid, uid); |
|---|
| 1101 | 1093 | audit_log_session_info(*ab); |
|---|
| 1102 | 1094 | audit_log_task_context(*ab); |
|---|
| 1095 | +} |
|---|
| 1096 | + |
|---|
| 1097 | +static inline void audit_log_user_recv_msg(struct audit_buffer **ab, |
|---|
| 1098 | + u16 msg_type) |
|---|
| 1099 | +{ |
|---|
| 1100 | + audit_log_common_recv_msg(NULL, ab, msg_type); |
|---|
| 1103 | 1101 | } |
|---|
| 1104 | 1102 | |
|---|
| 1105 | 1103 | int is_audit_feature_set(int i) |
|---|
| .. | .. |
|---|
| 1126 | 1124 | |
|---|
| 1127 | 1125 | if (audit_enabled == AUDIT_OFF) |
|---|
| 1128 | 1126 | return; |
|---|
| 1127 | + |
|---|
| 1129 | 1128 | ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_FEATURE_CHANGE); |
|---|
| 1130 | 1129 | if (!ab) |
|---|
| 1131 | 1130 | return; |
|---|
| 1132 | | - audit_log_task_info(ab, current); |
|---|
| 1131 | + audit_log_task_info(ab); |
|---|
| 1133 | 1132 | audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", |
|---|
| 1134 | 1133 | audit_feature_names[which], !!old_feature, !!new_feature, |
|---|
| 1135 | 1134 | !!old_lock, !!new_lock, res); |
|---|
| .. | .. |
|---|
| 1228 | 1227 | case AUDIT_GET: { |
|---|
| 1229 | 1228 | struct audit_status s; |
|---|
| 1230 | 1229 | memset(&s, 0, sizeof(s)); |
|---|
| 1231 | | - s.enabled = audit_enabled; |
|---|
| 1232 | | - s.failure = audit_failure; |
|---|
| 1230 | + s.enabled = audit_enabled; |
|---|
| 1231 | + s.failure = audit_failure; |
|---|
| 1233 | 1232 | /* NOTE: use pid_vnr() so the PID is relative to the current |
|---|
| 1234 | 1233 | * namespace */ |
|---|
| 1235 | | - s.pid = auditd_pid_vnr(); |
|---|
| 1236 | | - s.rate_limit = audit_rate_limit; |
|---|
| 1237 | | - s.backlog_limit = audit_backlog_limit; |
|---|
| 1238 | | - s.lost = atomic_read(&audit_lost); |
|---|
| 1239 | | - s.backlog = skb_queue_len(&audit_queue); |
|---|
| 1240 | | - s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL; |
|---|
| 1241 | | - s.backlog_wait_time = audit_backlog_wait_time; |
|---|
| 1234 | + s.pid = auditd_pid_vnr(); |
|---|
| 1235 | + s.rate_limit = audit_rate_limit; |
|---|
| 1236 | + s.backlog_limit = audit_backlog_limit; |
|---|
| 1237 | + s.lost = atomic_read(&audit_lost); |
|---|
| 1238 | + s.backlog = skb_queue_len(&audit_queue); |
|---|
| 1239 | + s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL; |
|---|
| 1240 | + s.backlog_wait_time = audit_backlog_wait_time; |
|---|
| 1241 | + s.backlog_wait_time_actual = atomic_read(&audit_backlog_wait_time_actual); |
|---|
| 1242 | 1242 | audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s)); |
|---|
| 1243 | 1243 | break; |
|---|
| 1244 | 1244 | } |
|---|
| .. | .. |
|---|
| 1342 | 1342 | audit_log_config_change("lost", 0, lost, 1); |
|---|
| 1343 | 1343 | return lost; |
|---|
| 1344 | 1344 | } |
|---|
| 1345 | + if (s.mask == AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL) { |
|---|
| 1346 | + u32 actual = atomic_xchg(&audit_backlog_wait_time_actual, 0); |
|---|
| 1347 | + |
|---|
| 1348 | + audit_log_config_change("backlog_wait_time_actual", 0, actual, 1); |
|---|
| 1349 | + return actual; |
|---|
| 1350 | + } |
|---|
| 1345 | 1351 | break; |
|---|
| 1346 | 1352 | } |
|---|
| 1347 | 1353 | case AUDIT_GET_FEATURE: |
|---|
| .. | .. |
|---|
| 1375 | 1381 | if (err) |
|---|
| 1376 | 1382 | break; |
|---|
| 1377 | 1383 | } |
|---|
| 1378 | | - audit_log_common_recv_msg(&ab, msg_type); |
|---|
| 1384 | + audit_log_user_recv_msg(&ab, msg_type); |
|---|
| 1379 | 1385 | if (msg_type != AUDIT_USER_TTY) { |
|---|
| 1380 | 1386 | /* ensure NULL termination */ |
|---|
| 1381 | 1387 | str[data_len - 1] = '\0'; |
|---|
| .. | .. |
|---|
| 1396 | 1402 | if (data_len < sizeof(struct audit_rule_data)) |
|---|
| 1397 | 1403 | return -EINVAL; |
|---|
| 1398 | 1404 | if (audit_enabled == AUDIT_LOCKED) { |
|---|
| 1399 | | - audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); |
|---|
| 1400 | | - audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled); |
|---|
| 1405 | + audit_log_common_recv_msg(audit_context(), &ab, |
|---|
| 1406 | + AUDIT_CONFIG_CHANGE); |
|---|
| 1407 | + audit_log_format(ab, " op=%s audit_enabled=%d res=0", |
|---|
| 1408 | + msg_type == AUDIT_ADD_RULE ? |
|---|
| 1409 | + "add_rule" : "remove_rule", |
|---|
| 1410 | + audit_enabled); |
|---|
| 1401 | 1411 | audit_log_end(ab); |
|---|
| 1402 | 1412 | return -EPERM; |
|---|
| 1403 | 1413 | } |
|---|
| .. | .. |
|---|
| 1408 | 1418 | break; |
|---|
| 1409 | 1419 | case AUDIT_TRIM: |
|---|
| 1410 | 1420 | audit_trim_trees(); |
|---|
| 1411 | | - audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); |
|---|
| 1421 | + audit_log_common_recv_msg(audit_context(), &ab, |
|---|
| 1422 | + AUDIT_CONFIG_CHANGE); |
|---|
| 1412 | 1423 | audit_log_format(ab, " op=trim res=1"); |
|---|
| 1413 | 1424 | audit_log_end(ab); |
|---|
| 1414 | 1425 | break; |
|---|
| .. | .. |
|---|
| 1438 | 1449 | /* OK, here comes... */ |
|---|
| 1439 | 1450 | err = audit_tag_tree(old, new); |
|---|
| 1440 | 1451 | |
|---|
| 1441 | | - audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); |
|---|
| 1442 | | - |
|---|
| 1452 | + audit_log_common_recv_msg(audit_context(), &ab, |
|---|
| 1453 | + AUDIT_CONFIG_CHANGE); |
|---|
| 1443 | 1454 | audit_log_format(ab, " op=make_equiv old="); |
|---|
| 1444 | 1455 | audit_log_untrustedstring(ab, old); |
|---|
| 1445 | 1456 | audit_log_format(ab, " new="); |
|---|
| .. | .. |
|---|
| 1506 | 1517 | old.enabled = t & AUDIT_TTY_ENABLE; |
|---|
| 1507 | 1518 | old.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD); |
|---|
| 1508 | 1519 | |
|---|
| 1509 | | - audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); |
|---|
| 1520 | + audit_log_common_recv_msg(audit_context(), &ab, |
|---|
| 1521 | + AUDIT_CONFIG_CHANGE); |
|---|
| 1510 | 1522 | audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d" |
|---|
| 1511 | 1523 | " old-log_passwd=%d new-log_passwd=%d res=%d", |
|---|
| 1512 | 1524 | old.enabled, s.enabled, old.log_passwd, |
|---|
| .. | .. |
|---|
| 1568 | 1580 | } |
|---|
| 1569 | 1581 | } |
|---|
| 1570 | 1582 | |
|---|
| 1571 | | -/* Run custom bind function on netlink socket group connect or bind requests. */ |
|---|
| 1572 | | -static int audit_bind(struct net *net, int group) |
|---|
| 1583 | +/* Log information about who is connecting to the audit multicast socket */ |
|---|
| 1584 | +static void audit_log_multicast(int group, const char *op, int err) |
|---|
| 1573 | 1585 | { |
|---|
| 1574 | | - if (!capable(CAP_AUDIT_READ)) |
|---|
| 1575 | | - return -EPERM; |
|---|
| 1586 | + const struct cred *cred; |
|---|
| 1587 | + struct tty_struct *tty; |
|---|
| 1588 | + char comm[sizeof(current->comm)]; |
|---|
| 1589 | + struct audit_buffer *ab; |
|---|
| 1576 | 1590 | |
|---|
| 1577 | | - return 0; |
|---|
| 1591 | + if (!audit_enabled) |
|---|
| 1592 | + return; |
|---|
| 1593 | + |
|---|
| 1594 | + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_EVENT_LISTENER); |
|---|
| 1595 | + if (!ab) |
|---|
| 1596 | + return; |
|---|
| 1597 | + |
|---|
| 1598 | + cred = current_cred(); |
|---|
| 1599 | + tty = audit_get_tty(); |
|---|
| 1600 | + audit_log_format(ab, "pid=%u uid=%u auid=%u tty=%s ses=%u", |
|---|
| 1601 | + task_pid_nr(current), |
|---|
| 1602 | + from_kuid(&init_user_ns, cred->uid), |
|---|
| 1603 | + from_kuid(&init_user_ns, audit_get_loginuid(current)), |
|---|
| 1604 | + tty ? tty_name(tty) : "(none)", |
|---|
| 1605 | + audit_get_sessionid(current)); |
|---|
| 1606 | + audit_put_tty(tty); |
|---|
| 1607 | + audit_log_task_context(ab); /* subj= */ |
|---|
| 1608 | + audit_log_format(ab, " comm="); |
|---|
| 1609 | + audit_log_untrustedstring(ab, get_task_comm(comm, current)); |
|---|
| 1610 | + audit_log_d_path_exe(ab, current->mm); /* exe= */ |
|---|
| 1611 | + audit_log_format(ab, " nl-mcgrp=%d op=%s res=%d", group, op, !err); |
|---|
| 1612 | + audit_log_end(ab); |
|---|
| 1613 | +} |
|---|
| 1614 | + |
|---|
| 1615 | +/* Run custom bind function on netlink socket group connect or bind requests. */ |
|---|
| 1616 | +static int audit_multicast_bind(struct net *net, int group) |
|---|
| 1617 | +{ |
|---|
| 1618 | + int err = 0; |
|---|
| 1619 | + |
|---|
| 1620 | + if (!capable(CAP_AUDIT_READ)) |
|---|
| 1621 | + err = -EPERM; |
|---|
| 1622 | + audit_log_multicast(group, "connect", err); |
|---|
| 1623 | + return err; |
|---|
| 1624 | +} |
|---|
| 1625 | + |
|---|
| 1626 | +static void audit_multicast_unbind(struct net *net, int group) |
|---|
| 1627 | +{ |
|---|
| 1628 | + audit_log_multicast(group, "disconnect", 0); |
|---|
| 1578 | 1629 | } |
|---|
| 1579 | 1630 | |
|---|
| 1580 | 1631 | static int __net_init audit_net_init(struct net *net) |
|---|
| 1581 | 1632 | { |
|---|
| 1582 | 1633 | struct netlink_kernel_cfg cfg = { |
|---|
| 1583 | 1634 | .input = audit_receive, |
|---|
| 1584 | | - .bind = audit_bind, |
|---|
| 1635 | + .bind = audit_multicast_bind, |
|---|
| 1636 | + .unbind = audit_multicast_unbind, |
|---|
| 1585 | 1637 | .flags = NL_CFG_F_NONROOT_RECV, |
|---|
| 1586 | 1638 | .groups = AUDIT_NLGRP_MAX, |
|---|
| 1587 | 1639 | }; |
|---|
| .. | .. |
|---|
| 1796 | 1848 | { |
|---|
| 1797 | 1849 | struct audit_buffer *ab; |
|---|
| 1798 | 1850 | struct timespec64 t; |
|---|
| 1799 | | - unsigned int uninitialized_var(serial); |
|---|
| 1851 | + unsigned int serial; |
|---|
| 1800 | 1852 | |
|---|
| 1801 | 1853 | if (audit_initialized != AUDIT_INITIALIZED) |
|---|
| 1802 | 1854 | return NULL; |
|---|
| .. | .. |
|---|
| 1824 | 1876 | /* sleep if we are allowed and we haven't exhausted our |
|---|
| 1825 | 1877 | * backlog wait limit */ |
|---|
| 1826 | 1878 | if (gfpflags_allow_blocking(gfp_mask) && (stime > 0)) { |
|---|
| 1879 | + long rtime = stime; |
|---|
| 1880 | + |
|---|
| 1827 | 1881 | DECLARE_WAITQUEUE(wait, current); |
|---|
| 1828 | 1882 | |
|---|
| 1829 | 1883 | add_wait_queue_exclusive(&audit_backlog_wait, |
|---|
| 1830 | 1884 | &wait); |
|---|
| 1831 | 1885 | set_current_state(TASK_UNINTERRUPTIBLE); |
|---|
| 1832 | | - stime = schedule_timeout(stime); |
|---|
| 1886 | + stime = schedule_timeout(rtime); |
|---|
| 1887 | + atomic_add(rtime - stime, &audit_backlog_wait_time_actual); |
|---|
| 1833 | 1888 | remove_wait_queue(&audit_backlog_wait, &wait); |
|---|
| 1834 | 1889 | } else { |
|---|
| 1835 | 1890 | if (audit_rate_check() && printk_ratelimit()) |
|---|
| .. | .. |
|---|
| 2077 | 2132 | /* We will allow 11 spaces for ' (deleted)' to be appended */ |
|---|
| 2078 | 2133 | pathname = kmalloc(PATH_MAX+11, ab->gfp_mask); |
|---|
| 2079 | 2134 | if (!pathname) { |
|---|
| 2080 | | - audit_log_string(ab, "<no_memory>"); |
|---|
| 2135 | + audit_log_format(ab, "\"<no_memory>\""); |
|---|
| 2081 | 2136 | return; |
|---|
| 2082 | 2137 | } |
|---|
| 2083 | 2138 | p = d_path(path, pathname, PATH_MAX+11); |
|---|
| 2084 | 2139 | if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */ |
|---|
| 2085 | 2140 | /* FIXME: can we save some information here? */ |
|---|
| 2086 | | - audit_log_string(ab, "<too_long>"); |
|---|
| 2141 | + audit_log_format(ab, "\"<too_long>\""); |
|---|
| 2087 | 2142 | } else |
|---|
| 2088 | 2143 | audit_log_untrustedstring(ab, p); |
|---|
| 2089 | 2144 | kfree(pathname); |
|---|
| .. | .. |
|---|
| 2094 | 2149 | unsigned int sessionid = audit_get_sessionid(current); |
|---|
| 2095 | 2150 | uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current)); |
|---|
| 2096 | 2151 | |
|---|
| 2097 | | - audit_log_format(ab, " auid=%u ses=%u", auid, sessionid); |
|---|
| 2152 | + audit_log_format(ab, "auid=%u ses=%u", auid, sessionid); |
|---|
| 2098 | 2153 | } |
|---|
| 2099 | 2154 | |
|---|
| 2100 | 2155 | void audit_log_key(struct audit_buffer *ab, char *key) |
|---|
| .. | .. |
|---|
| 2104 | 2159 | audit_log_untrustedstring(ab, key); |
|---|
| 2105 | 2160 | else |
|---|
| 2106 | 2161 | audit_log_format(ab, "(null)"); |
|---|
| 2107 | | -} |
|---|
| 2108 | | - |
|---|
| 2109 | | -void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) |
|---|
| 2110 | | -{ |
|---|
| 2111 | | - int i; |
|---|
| 2112 | | - |
|---|
| 2113 | | - audit_log_format(ab, " %s=", prefix); |
|---|
| 2114 | | - CAP_FOR_EACH_U32(i) { |
|---|
| 2115 | | - audit_log_format(ab, "%08x", |
|---|
| 2116 | | - cap->cap[CAP_LAST_U32 - i]); |
|---|
| 2117 | | - } |
|---|
| 2118 | | -} |
|---|
| 2119 | | - |
|---|
| 2120 | | -static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) |
|---|
| 2121 | | -{ |
|---|
| 2122 | | - audit_log_cap(ab, "cap_fp", &name->fcap.permitted); |
|---|
| 2123 | | - audit_log_cap(ab, "cap_fi", &name->fcap.inheritable); |
|---|
| 2124 | | - audit_log_format(ab, " cap_fe=%d cap_fver=%x", |
|---|
| 2125 | | - name->fcap.fE, name->fcap_ver); |
|---|
| 2126 | | -} |
|---|
| 2127 | | - |
|---|
| 2128 | | -static inline int audit_copy_fcaps(struct audit_names *name, |
|---|
| 2129 | | - const struct dentry *dentry) |
|---|
| 2130 | | -{ |
|---|
| 2131 | | - struct cpu_vfs_cap_data caps; |
|---|
| 2132 | | - int rc; |
|---|
| 2133 | | - |
|---|
| 2134 | | - if (!dentry) |
|---|
| 2135 | | - return 0; |
|---|
| 2136 | | - |
|---|
| 2137 | | - rc = get_vfs_caps_from_disk(dentry, &caps); |
|---|
| 2138 | | - if (rc) |
|---|
| 2139 | | - return rc; |
|---|
| 2140 | | - |
|---|
| 2141 | | - name->fcap.permitted = caps.permitted; |
|---|
| 2142 | | - name->fcap.inheritable = caps.inheritable; |
|---|
| 2143 | | - name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); |
|---|
| 2144 | | - name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> |
|---|
| 2145 | | - VFS_CAP_REVISION_SHIFT; |
|---|
| 2146 | | - |
|---|
| 2147 | | - return 0; |
|---|
| 2148 | | -} |
|---|
| 2149 | | - |
|---|
| 2150 | | -/* Copy inode data into an audit_names. */ |
|---|
| 2151 | | -void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, |
|---|
| 2152 | | - struct inode *inode) |
|---|
| 2153 | | -{ |
|---|
| 2154 | | - name->ino = inode->i_ino; |
|---|
| 2155 | | - name->dev = inode->i_sb->s_dev; |
|---|
| 2156 | | - name->mode = inode->i_mode; |
|---|
| 2157 | | - name->uid = inode->i_uid; |
|---|
| 2158 | | - name->gid = inode->i_gid; |
|---|
| 2159 | | - name->rdev = inode->i_rdev; |
|---|
| 2160 | | - security_inode_getsecid(inode, &name->osid); |
|---|
| 2161 | | - audit_copy_fcaps(name, dentry); |
|---|
| 2162 | | -} |
|---|
| 2163 | | - |
|---|
| 2164 | | -/** |
|---|
| 2165 | | - * audit_log_name - produce AUDIT_PATH record from struct audit_names |
|---|
| 2166 | | - * @context: audit_context for the task |
|---|
| 2167 | | - * @n: audit_names structure with reportable details |
|---|
| 2168 | | - * @path: optional path to report instead of audit_names->name |
|---|
| 2169 | | - * @record_num: record number to report when handling a list of names |
|---|
| 2170 | | - * @call_panic: optional pointer to int that will be updated if secid fails |
|---|
| 2171 | | - */ |
|---|
| 2172 | | -void audit_log_name(struct audit_context *context, struct audit_names *n, |
|---|
| 2173 | | - const struct path *path, int record_num, int *call_panic) |
|---|
| 2174 | | -{ |
|---|
| 2175 | | - struct audit_buffer *ab; |
|---|
| 2176 | | - ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); |
|---|
| 2177 | | - if (!ab) |
|---|
| 2178 | | - return; |
|---|
| 2179 | | - |
|---|
| 2180 | | - audit_log_format(ab, "item=%d", record_num); |
|---|
| 2181 | | - |
|---|
| 2182 | | - if (path) |
|---|
| 2183 | | - audit_log_d_path(ab, " name=", path); |
|---|
| 2184 | | - else if (n->name) { |
|---|
| 2185 | | - switch (n->name_len) { |
|---|
| 2186 | | - case AUDIT_NAME_FULL: |
|---|
| 2187 | | - /* log the full path */ |
|---|
| 2188 | | - audit_log_format(ab, " name="); |
|---|
| 2189 | | - audit_log_untrustedstring(ab, n->name->name); |
|---|
| 2190 | | - break; |
|---|
| 2191 | | - case 0: |
|---|
| 2192 | | - /* name was specified as a relative path and the |
|---|
| 2193 | | - * directory component is the cwd */ |
|---|
| 2194 | | - audit_log_d_path(ab, " name=", &context->pwd); |
|---|
| 2195 | | - break; |
|---|
| 2196 | | - default: |
|---|
| 2197 | | - /* log the name's directory component */ |
|---|
| 2198 | | - audit_log_format(ab, " name="); |
|---|
| 2199 | | - audit_log_n_untrustedstring(ab, n->name->name, |
|---|
| 2200 | | - n->name_len); |
|---|
| 2201 | | - } |
|---|
| 2202 | | - } else |
|---|
| 2203 | | - audit_log_format(ab, " name=(null)"); |
|---|
| 2204 | | - |
|---|
| 2205 | | - if (n->ino != AUDIT_INO_UNSET) |
|---|
| 2206 | | - audit_log_format(ab, " inode=%lu" |
|---|
| 2207 | | - " dev=%02x:%02x mode=%#ho" |
|---|
| 2208 | | - " ouid=%u ogid=%u rdev=%02x:%02x", |
|---|
| 2209 | | - n->ino, |
|---|
| 2210 | | - MAJOR(n->dev), |
|---|
| 2211 | | - MINOR(n->dev), |
|---|
| 2212 | | - n->mode, |
|---|
| 2213 | | - from_kuid(&init_user_ns, n->uid), |
|---|
| 2214 | | - from_kgid(&init_user_ns, n->gid), |
|---|
| 2215 | | - MAJOR(n->rdev), |
|---|
| 2216 | | - MINOR(n->rdev)); |
|---|
| 2217 | | - if (n->osid != 0) { |
|---|
| 2218 | | - char *ctx = NULL; |
|---|
| 2219 | | - u32 len; |
|---|
| 2220 | | - if (security_secid_to_secctx( |
|---|
| 2221 | | - n->osid, &ctx, &len)) { |
|---|
| 2222 | | - audit_log_format(ab, " osid=%u", n->osid); |
|---|
| 2223 | | - if (call_panic) |
|---|
| 2224 | | - *call_panic = 2; |
|---|
| 2225 | | - } else { |
|---|
| 2226 | | - audit_log_format(ab, " obj=%s", ctx); |
|---|
| 2227 | | - security_release_secctx(ctx, len); |
|---|
| 2228 | | - } |
|---|
| 2229 | | - } |
|---|
| 2230 | | - |
|---|
| 2231 | | - /* log the audit_names record type */ |
|---|
| 2232 | | - audit_log_format(ab, " nametype="); |
|---|
| 2233 | | - switch(n->type) { |
|---|
| 2234 | | - case AUDIT_TYPE_NORMAL: |
|---|
| 2235 | | - audit_log_format(ab, "NORMAL"); |
|---|
| 2236 | | - break; |
|---|
| 2237 | | - case AUDIT_TYPE_PARENT: |
|---|
| 2238 | | - audit_log_format(ab, "PARENT"); |
|---|
| 2239 | | - break; |
|---|
| 2240 | | - case AUDIT_TYPE_CHILD_DELETE: |
|---|
| 2241 | | - audit_log_format(ab, "DELETE"); |
|---|
| 2242 | | - break; |
|---|
| 2243 | | - case AUDIT_TYPE_CHILD_CREATE: |
|---|
| 2244 | | - audit_log_format(ab, "CREATE"); |
|---|
| 2245 | | - break; |
|---|
| 2246 | | - default: |
|---|
| 2247 | | - audit_log_format(ab, "UNKNOWN"); |
|---|
| 2248 | | - break; |
|---|
| 2249 | | - } |
|---|
| 2250 | | - |
|---|
| 2251 | | - audit_log_fcaps(ab, n); |
|---|
| 2252 | | - audit_log_end(ab); |
|---|
| 2253 | 2162 | } |
|---|
| 2254 | 2163 | |
|---|
| 2255 | 2164 | int audit_log_task_context(struct audit_buffer *ab) |
|---|
| .. | .. |
|---|
| 2299 | 2208 | audit_log_format(ab, " exe=(null)"); |
|---|
| 2300 | 2209 | } |
|---|
| 2301 | 2210 | |
|---|
| 2302 | | -struct tty_struct *audit_get_tty(struct task_struct *tsk) |
|---|
| 2211 | +struct tty_struct *audit_get_tty(void) |
|---|
| 2303 | 2212 | { |
|---|
| 2304 | 2213 | struct tty_struct *tty = NULL; |
|---|
| 2305 | 2214 | unsigned long flags; |
|---|
| 2306 | 2215 | |
|---|
| 2307 | | - spin_lock_irqsave(&tsk->sighand->siglock, flags); |
|---|
| 2308 | | - if (tsk->signal) |
|---|
| 2309 | | - tty = tty_kref_get(tsk->signal->tty); |
|---|
| 2310 | | - spin_unlock_irqrestore(&tsk->sighand->siglock, flags); |
|---|
| 2216 | + spin_lock_irqsave(¤t->sighand->siglock, flags); |
|---|
| 2217 | + if (current->signal) |
|---|
| 2218 | + tty = tty_kref_get(current->signal->tty); |
|---|
| 2219 | + spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
|---|
| 2311 | 2220 | return tty; |
|---|
| 2312 | 2221 | } |
|---|
| 2313 | 2222 | |
|---|
| .. | .. |
|---|
| 2316 | 2225 | tty_kref_put(tty); |
|---|
| 2317 | 2226 | } |
|---|
| 2318 | 2227 | |
|---|
| 2319 | | -void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) |
|---|
| 2228 | +void audit_log_task_info(struct audit_buffer *ab) |
|---|
| 2320 | 2229 | { |
|---|
| 2321 | 2230 | const struct cred *cred; |
|---|
| 2322 | | - char comm[sizeof(tsk->comm)]; |
|---|
| 2231 | + char comm[sizeof(current->comm)]; |
|---|
| 2323 | 2232 | struct tty_struct *tty; |
|---|
| 2324 | 2233 | |
|---|
| 2325 | 2234 | if (!ab) |
|---|
| 2326 | 2235 | return; |
|---|
| 2327 | 2236 | |
|---|
| 2328 | | - /* tsk == current */ |
|---|
| 2329 | 2237 | cred = current_cred(); |
|---|
| 2330 | | - tty = audit_get_tty(tsk); |
|---|
| 2238 | + tty = audit_get_tty(); |
|---|
| 2331 | 2239 | audit_log_format(ab, |
|---|
| 2332 | 2240 | " ppid=%d pid=%d auid=%u uid=%u gid=%u" |
|---|
| 2333 | 2241 | " euid=%u suid=%u fsuid=%u" |
|---|
| 2334 | 2242 | " egid=%u sgid=%u fsgid=%u tty=%s ses=%u", |
|---|
| 2335 | | - task_ppid_nr(tsk), |
|---|
| 2336 | | - task_tgid_nr(tsk), |
|---|
| 2337 | | - from_kuid(&init_user_ns, audit_get_loginuid(tsk)), |
|---|
| 2243 | + task_ppid_nr(current), |
|---|
| 2244 | + task_tgid_nr(current), |
|---|
| 2245 | + from_kuid(&init_user_ns, audit_get_loginuid(current)), |
|---|
| 2338 | 2246 | from_kuid(&init_user_ns, cred->uid), |
|---|
| 2339 | 2247 | from_kgid(&init_user_ns, cred->gid), |
|---|
| 2340 | 2248 | from_kuid(&init_user_ns, cred->euid), |
|---|
| .. | .. |
|---|
| 2344 | 2252 | from_kgid(&init_user_ns, cred->sgid), |
|---|
| 2345 | 2253 | from_kgid(&init_user_ns, cred->fsgid), |
|---|
| 2346 | 2254 | tty ? tty_name(tty) : "(none)", |
|---|
| 2347 | | - audit_get_sessionid(tsk)); |
|---|
| 2255 | + audit_get_sessionid(current)); |
|---|
| 2348 | 2256 | audit_put_tty(tty); |
|---|
| 2349 | 2257 | audit_log_format(ab, " comm="); |
|---|
| 2350 | | - audit_log_untrustedstring(ab, get_task_comm(comm, tsk)); |
|---|
| 2351 | | - audit_log_d_path_exe(ab, tsk->mm); |
|---|
| 2258 | + audit_log_untrustedstring(ab, get_task_comm(comm, current)); |
|---|
| 2259 | + audit_log_d_path_exe(ab, current->mm); |
|---|
| 2352 | 2260 | audit_log_task_context(ab); |
|---|
| 2353 | 2261 | } |
|---|
| 2354 | 2262 | EXPORT_SYMBOL(audit_log_task_info); |
|---|
| 2355 | 2263 | |
|---|
| 2356 | 2264 | /** |
|---|
| 2357 | | - * audit_log_link_denied - report a link restriction denial |
|---|
| 2358 | | - * @operation: specific link operation |
|---|
| 2265 | + * audit_log_path_denied - report a path restriction denial |
|---|
| 2266 | + * @type: audit message type (AUDIT_ANOM_LINK, AUDIT_ANOM_CREAT, etc) |
|---|
| 2267 | + * @operation: specific operation name |
|---|
| 2359 | 2268 | */ |
|---|
| 2360 | | -void audit_log_link_denied(const char *operation) |
|---|
| 2269 | +void audit_log_path_denied(int type, const char *operation) |
|---|
| 2361 | 2270 | { |
|---|
| 2362 | 2271 | struct audit_buffer *ab; |
|---|
| 2363 | 2272 | |
|---|
| 2364 | 2273 | if (!audit_enabled || audit_dummy_context()) |
|---|
| 2365 | 2274 | return; |
|---|
| 2366 | 2275 | |
|---|
| 2367 | | - /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */ |
|---|
| 2368 | | - ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_ANOM_LINK); |
|---|
| 2276 | + /* Generate log with subject, operation, outcome. */ |
|---|
| 2277 | + ab = audit_log_start(audit_context(), GFP_KERNEL, type); |
|---|
| 2369 | 2278 | if (!ab) |
|---|
| 2370 | 2279 | return; |
|---|
| 2371 | 2280 | audit_log_format(ab, "op=%s", operation); |
|---|
| 2372 | | - audit_log_task_info(ab, current); |
|---|
| 2281 | + audit_log_task_info(ab); |
|---|
| 2373 | 2282 | audit_log_format(ab, " res=0"); |
|---|
| 2374 | 2283 | audit_log_end(ab); |
|---|
| 2375 | 2284 | } |
|---|
| 2376 | 2285 | |
|---|
| 2286 | +/* global counter which is incremented every time something logs in */ |
|---|
| 2287 | +static atomic_t session_id = ATOMIC_INIT(0); |
|---|
| 2288 | + |
|---|
| 2289 | +static int audit_set_loginuid_perm(kuid_t loginuid) |
|---|
| 2290 | +{ |
|---|
| 2291 | + /* if we are unset, we don't need privs */ |
|---|
| 2292 | + if (!audit_loginuid_set(current)) |
|---|
| 2293 | + return 0; |
|---|
| 2294 | + /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/ |
|---|
| 2295 | + if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE)) |
|---|
| 2296 | + return -EPERM; |
|---|
| 2297 | + /* it is set, you need permission */ |
|---|
| 2298 | + if (!capable(CAP_AUDIT_CONTROL)) |
|---|
| 2299 | + return -EPERM; |
|---|
| 2300 | + /* reject if this is not an unset and we don't allow that */ |
|---|
| 2301 | + if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) |
|---|
| 2302 | + && uid_valid(loginuid)) |
|---|
| 2303 | + return -EPERM; |
|---|
| 2304 | + return 0; |
|---|
| 2305 | +} |
|---|
| 2306 | + |
|---|
| 2307 | +static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, |
|---|
| 2308 | + unsigned int oldsessionid, |
|---|
| 2309 | + unsigned int sessionid, int rc) |
|---|
| 2310 | +{ |
|---|
| 2311 | + struct audit_buffer *ab; |
|---|
| 2312 | + uid_t uid, oldloginuid, loginuid; |
|---|
| 2313 | + struct tty_struct *tty; |
|---|
| 2314 | + |
|---|
| 2315 | + if (!audit_enabled) |
|---|
| 2316 | + return; |
|---|
| 2317 | + |
|---|
| 2318 | + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_LOGIN); |
|---|
| 2319 | + if (!ab) |
|---|
| 2320 | + return; |
|---|
| 2321 | + |
|---|
| 2322 | + uid = from_kuid(&init_user_ns, task_uid(current)); |
|---|
| 2323 | + oldloginuid = from_kuid(&init_user_ns, koldloginuid); |
|---|
| 2324 | + loginuid = from_kuid(&init_user_ns, kloginuid), |
|---|
| 2325 | + tty = audit_get_tty(); |
|---|
| 2326 | + |
|---|
| 2327 | + audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid); |
|---|
| 2328 | + audit_log_task_context(ab); |
|---|
| 2329 | + audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", |
|---|
| 2330 | + oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", |
|---|
| 2331 | + oldsessionid, sessionid, !rc); |
|---|
| 2332 | + audit_put_tty(tty); |
|---|
| 2333 | + audit_log_end(ab); |
|---|
| 2334 | +} |
|---|
| 2335 | + |
|---|
| 2336 | +/** |
|---|
| 2337 | + * audit_set_loginuid - set current task's loginuid |
|---|
| 2338 | + * @loginuid: loginuid value |
|---|
| 2339 | + * |
|---|
| 2340 | + * Returns 0. |
|---|
| 2341 | + * |
|---|
| 2342 | + * Called (set) from fs/proc/base.c::proc_loginuid_write(). |
|---|
| 2343 | + */ |
|---|
| 2344 | +int audit_set_loginuid(kuid_t loginuid) |
|---|
| 2345 | +{ |
|---|
| 2346 | + unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; |
|---|
| 2347 | + kuid_t oldloginuid; |
|---|
| 2348 | + int rc; |
|---|
| 2349 | + |
|---|
| 2350 | + oldloginuid = audit_get_loginuid(current); |
|---|
| 2351 | + oldsessionid = audit_get_sessionid(current); |
|---|
| 2352 | + |
|---|
| 2353 | + rc = audit_set_loginuid_perm(loginuid); |
|---|
| 2354 | + if (rc) |
|---|
| 2355 | + goto out; |
|---|
| 2356 | + |
|---|
| 2357 | + /* are we setting or clearing? */ |
|---|
| 2358 | + if (uid_valid(loginuid)) { |
|---|
| 2359 | + sessionid = (unsigned int)atomic_inc_return(&session_id); |
|---|
| 2360 | + if (unlikely(sessionid == AUDIT_SID_UNSET)) |
|---|
| 2361 | + sessionid = (unsigned int)atomic_inc_return(&session_id); |
|---|
| 2362 | + } |
|---|
| 2363 | + |
|---|
| 2364 | + current->sessionid = sessionid; |
|---|
| 2365 | + current->loginuid = loginuid; |
|---|
| 2366 | +out: |
|---|
| 2367 | + audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); |
|---|
| 2368 | + return rc; |
|---|
| 2369 | +} |
|---|
| 2370 | + |
|---|
| 2371 | +/** |
|---|
| 2372 | + * audit_signal_info - record signal info for shutting down audit subsystem |
|---|
| 2373 | + * @sig: signal value |
|---|
| 2374 | + * @t: task being signaled |
|---|
| 2375 | + * |
|---|
| 2376 | + * If the audit subsystem is being terminated, record the task (pid) |
|---|
| 2377 | + * and uid that is doing that. |
|---|
| 2378 | + */ |
|---|
| 2379 | +int audit_signal_info(int sig, struct task_struct *t) |
|---|
| 2380 | +{ |
|---|
| 2381 | + kuid_t uid = current_uid(), auid; |
|---|
| 2382 | + |
|---|
| 2383 | + if (auditd_test_task(t) && |
|---|
| 2384 | + (sig == SIGTERM || sig == SIGHUP || |
|---|
| 2385 | + sig == SIGUSR1 || sig == SIGUSR2)) { |
|---|
| 2386 | + audit_sig_pid = task_tgid_nr(current); |
|---|
| 2387 | + auid = audit_get_loginuid(current); |
|---|
| 2388 | + if (uid_valid(auid)) |
|---|
| 2389 | + audit_sig_uid = auid; |
|---|
| 2390 | + else |
|---|
| 2391 | + audit_sig_uid = uid; |
|---|
| 2392 | + security_task_getsecid(current, &audit_sig_sid); |
|---|
| 2393 | + } |
|---|
| 2394 | + |
|---|
| 2395 | + return audit_signal_info_syscall(t); |
|---|
| 2396 | +} |
|---|
| 2397 | + |
|---|
| 2377 | 2398 | /** |
|---|
| 2378 | 2399 | * audit_log_end - end one audit record |
|---|
| 2379 | 2400 | * @ab: the audit_buffer |
|---|