aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/audit.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-07 15:20:11 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-07 15:20:11 -0500
commitbe37f21a08ce65c7632c7f45e1755a4b07f278a0 (patch)
tree5f61b71e21dd809ea558ad195d06b7ebd4fb49c5 /kernel/audit.c
parent3ac96c30ccfa802501dd2f4941e4508ea54b0b8a (diff)
parent131d34cb07957151c369366b158690057d2bce5e (diff)
Merge tag 'audit-pr-20190305' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit
Pull audit updates from Paul Moore: "A lucky 13 audit patches for v5.1. Despite the rather large diffstat, most of the changes are from two bug fix patches that move code from one Kconfig option to another. Beyond that bit of churn, the remaining changes are largely cleanups and bug-fixes as we slowly march towards container auditing. It isn't all boring though, we do have a couple of new things: file capabilities v3 support, and expanded support for filtering on filesystems to solve problems with remote filesystems. All changes pass the audit-testsuite. Please merge for v5.1" * tag 'audit-pr-20190305' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit: audit: mark expected switch fall-through audit: hide auditsc_get_stamp and audit_serial prototypes audit: join tty records to their syscall audit: remove audit_context when CONFIG_ AUDIT and not AUDITSYSCALL audit: remove unused actx param from audit_rule_match audit: ignore fcaps on umount audit: clean up AUDITSYSCALL prototypes and stubs audit: more filter PATH records keyed on filesystem magic audit: add support for fcaps v3 audit: move loginuid and sessionid from CONFIG_AUDITSYSCALL to CONFIG_AUDIT audit: add syscall information to CONFIG_CHANGE records audit: hand taken context to audit_kill_trees for syscall logging audit: give a clue what CONFIG_CHANGE op was involved
Diffstat (limited to 'kernel/audit.c')
-rw-r--r--kernel/audit.c267
1 files changed, 109 insertions, 158 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index 632d36059556..c89ea48c70a6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -396,10 +396,10 @@ static int audit_log_config_change(char *function_name, u32 new, u32 old,
396 struct audit_buffer *ab; 396 struct audit_buffer *ab;
397 int rc = 0; 397 int rc = 0;
398 398
399 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); 399 ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_CONFIG_CHANGE);
400 if (unlikely(!ab)) 400 if (unlikely(!ab))
401 return rc; 401 return rc;
402 audit_log_format(ab, "%s=%u old=%u ", function_name, new, old); 402 audit_log_format(ab, "op=set %s=%u old=%u ", function_name, new, old);
403 audit_log_session_info(ab); 403 audit_log_session_info(ab);
404 rc = audit_log_task_context(ab); 404 rc = audit_log_task_context(ab);
405 if (rc) 405 if (rc)
@@ -1053,7 +1053,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
1053 return err; 1053 return err;
1054} 1054}
1055 1055
1056static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) 1056static void audit_log_common_recv_msg(struct audit_context *context,
1057 struct audit_buffer **ab, u16 msg_type)
1057{ 1058{
1058 uid_t uid = from_kuid(&init_user_ns, current_uid()); 1059 uid_t uid = from_kuid(&init_user_ns, current_uid());
1059 pid_t pid = task_tgid_nr(current); 1060 pid_t pid = task_tgid_nr(current);
@@ -1063,7 +1064,7 @@ static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type)
1063 return; 1064 return;
1064 } 1065 }
1065 1066
1066 *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); 1067 *ab = audit_log_start(context, GFP_KERNEL, msg_type);
1067 if (unlikely(!*ab)) 1068 if (unlikely(!*ab))
1068 return; 1069 return;
1069 audit_log_format(*ab, "pid=%d uid=%u ", pid, uid); 1070 audit_log_format(*ab, "pid=%d uid=%u ", pid, uid);
@@ -1071,6 +1072,12 @@ static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type)
1071 audit_log_task_context(*ab); 1072 audit_log_task_context(*ab);
1072} 1073}
1073 1074
1075static inline void audit_log_user_recv_msg(struct audit_buffer **ab,
1076 u16 msg_type)
1077{
1078 audit_log_common_recv_msg(NULL, ab, msg_type);
1079}
1080
1074int is_audit_feature_set(int i) 1081int is_audit_feature_set(int i)
1075{ 1082{
1076 return af.features & AUDIT_FEATURE_TO_MASK(i); 1083 return af.features & AUDIT_FEATURE_TO_MASK(i);
@@ -1338,7 +1345,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1338 if (err) 1345 if (err)
1339 break; 1346 break;
1340 } 1347 }
1341 audit_log_common_recv_msg(&ab, msg_type); 1348 audit_log_user_recv_msg(&ab, msg_type);
1342 if (msg_type != AUDIT_USER_TTY) 1349 if (msg_type != AUDIT_USER_TTY)
1343 audit_log_format(ab, " msg='%.*s'", 1350 audit_log_format(ab, " msg='%.*s'",
1344 AUDIT_MESSAGE_TEXT_MAX, 1351 AUDIT_MESSAGE_TEXT_MAX,
@@ -1361,8 +1368,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1361 if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) 1368 if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
1362 return -EINVAL; 1369 return -EINVAL;
1363 if (audit_enabled == AUDIT_LOCKED) { 1370 if (audit_enabled == AUDIT_LOCKED) {
1364 audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); 1371 audit_log_common_recv_msg(audit_context(), &ab,
1365 audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled); 1372 AUDIT_CONFIG_CHANGE);
1373 audit_log_format(ab, " op=%s audit_enabled=%d res=0",
1374 msg_type == AUDIT_ADD_RULE ?
1375 "add_rule" : "remove_rule",
1376 audit_enabled);
1366 audit_log_end(ab); 1377 audit_log_end(ab);
1367 return -EPERM; 1378 return -EPERM;
1368 } 1379 }
@@ -1373,7 +1384,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1373 break; 1384 break;
1374 case AUDIT_TRIM: 1385 case AUDIT_TRIM:
1375 audit_trim_trees(); 1386 audit_trim_trees();
1376 audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); 1387 audit_log_common_recv_msg(audit_context(), &ab,
1388 AUDIT_CONFIG_CHANGE);
1377 audit_log_format(ab, " op=trim res=1"); 1389 audit_log_format(ab, " op=trim res=1");
1378 audit_log_end(ab); 1390 audit_log_end(ab);
1379 break; 1391 break;
@@ -1403,8 +1415,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1403 /* OK, here comes... */ 1415 /* OK, here comes... */
1404 err = audit_tag_tree(old, new); 1416 err = audit_tag_tree(old, new);
1405 1417
1406 audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); 1418 audit_log_common_recv_msg(audit_context(), &ab,
1407 1419 AUDIT_CONFIG_CHANGE);
1408 audit_log_format(ab, " op=make_equiv old="); 1420 audit_log_format(ab, " op=make_equiv old=");
1409 audit_log_untrustedstring(ab, old); 1421 audit_log_untrustedstring(ab, old);
1410 audit_log_format(ab, " new="); 1422 audit_log_format(ab, " new=");
@@ -1471,7 +1483,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1471 old.enabled = t & AUDIT_TTY_ENABLE; 1483 old.enabled = t & AUDIT_TTY_ENABLE;
1472 old.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD); 1484 old.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD);
1473 1485
1474 audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); 1486 audit_log_common_recv_msg(audit_context(), &ab,
1487 AUDIT_CONFIG_CHANGE);
1475 audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d" 1488 audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d"
1476 " old-log_passwd=%d new-log_passwd=%d res=%d", 1489 " old-log_passwd=%d new-log_passwd=%d res=%d",
1477 old.enabled, s.enabled, old.log_passwd, 1490 old.enabled, s.enabled, old.log_passwd,
@@ -2054,153 +2067,6 @@ void audit_log_key(struct audit_buffer *ab, char *key)
2054 audit_log_format(ab, "(null)"); 2067 audit_log_format(ab, "(null)");
2055} 2068}
2056 2069
2057void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
2058{
2059 int i;
2060
2061 if (cap_isclear(*cap)) {
2062 audit_log_format(ab, " %s=0", prefix);
2063 return;
2064 }
2065 audit_log_format(ab, " %s=", prefix);
2066 CAP_FOR_EACH_U32(i)
2067 audit_log_format(ab, "%08x", cap->cap[CAP_LAST_U32 - i]);
2068}
2069
2070static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
2071{
2072 audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
2073 audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
2074 audit_log_format(ab, " cap_fe=%d cap_fver=%x",
2075 name->fcap.fE, name->fcap_ver);
2076}
2077
2078static inline int audit_copy_fcaps(struct audit_names *name,
2079 const struct dentry *dentry)
2080{
2081 struct cpu_vfs_cap_data caps;
2082 int rc;
2083
2084 if (!dentry)
2085 return 0;
2086
2087 rc = get_vfs_caps_from_disk(dentry, &caps);
2088 if (rc)
2089 return rc;
2090
2091 name->fcap.permitted = caps.permitted;
2092 name->fcap.inheritable = caps.inheritable;
2093 name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
2094 name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >>
2095 VFS_CAP_REVISION_SHIFT;
2096
2097 return 0;
2098}
2099
2100/* Copy inode data into an audit_names. */
2101void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
2102 struct inode *inode)
2103{
2104 name->ino = inode->i_ino;
2105 name->dev = inode->i_sb->s_dev;
2106 name->mode = inode->i_mode;
2107 name->uid = inode->i_uid;
2108 name->gid = inode->i_gid;
2109 name->rdev = inode->i_rdev;
2110 security_inode_getsecid(inode, &name->osid);
2111 audit_copy_fcaps(name, dentry);
2112}
2113
2114/**
2115 * audit_log_name - produce AUDIT_PATH record from struct audit_names
2116 * @context: audit_context for the task
2117 * @n: audit_names structure with reportable details
2118 * @path: optional path to report instead of audit_names->name
2119 * @record_num: record number to report when handling a list of names
2120 * @call_panic: optional pointer to int that will be updated if secid fails
2121 */
2122void audit_log_name(struct audit_context *context, struct audit_names *n,
2123 const struct path *path, int record_num, int *call_panic)
2124{
2125 struct audit_buffer *ab;
2126 ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
2127 if (!ab)
2128 return;
2129
2130 audit_log_format(ab, "item=%d", record_num);
2131
2132 if (path)
2133 audit_log_d_path(ab, " name=", path);
2134 else if (n->name) {
2135 switch (n->name_len) {
2136 case AUDIT_NAME_FULL:
2137 /* log the full path */
2138 audit_log_format(ab, " name=");
2139 audit_log_untrustedstring(ab, n->name->name);
2140 break;
2141 case 0:
2142 /* name was specified as a relative path and the
2143 * directory component is the cwd */
2144 audit_log_d_path(ab, " name=", &context->pwd);
2145 break;
2146 default:
2147 /* log the name's directory component */
2148 audit_log_format(ab, " name=");
2149 audit_log_n_untrustedstring(ab, n->name->name,
2150 n->name_len);
2151 }
2152 } else
2153 audit_log_format(ab, " name=(null)");
2154
2155 if (n->ino != AUDIT_INO_UNSET)
2156 audit_log_format(ab, " inode=%lu"
2157 " dev=%02x:%02x mode=%#ho"
2158 " ouid=%u ogid=%u rdev=%02x:%02x",
2159 n->ino,
2160 MAJOR(n->dev),
2161 MINOR(n->dev),
2162 n->mode,
2163 from_kuid(&init_user_ns, n->uid),
2164 from_kgid(&init_user_ns, n->gid),
2165 MAJOR(n->rdev),
2166 MINOR(n->rdev));
2167 if (n->osid != 0) {
2168 char *ctx = NULL;
2169 u32 len;
2170 if (security_secid_to_secctx(
2171 n->osid, &ctx, &len)) {
2172 audit_log_format(ab, " osid=%u", n->osid);
2173 if (call_panic)
2174 *call_panic = 2;
2175 } else {
2176 audit_log_format(ab, " obj=%s", ctx);
2177 security_release_secctx(ctx, len);
2178 }
2179 }
2180
2181 /* log the audit_names record type */
2182 switch(n->type) {
2183 case AUDIT_TYPE_NORMAL:
2184 audit_log_format(ab, " nametype=NORMAL");
2185 break;
2186 case AUDIT_TYPE_PARENT:
2187 audit_log_format(ab, " nametype=PARENT");
2188 break;
2189 case AUDIT_TYPE_CHILD_DELETE:
2190 audit_log_format(ab, " nametype=DELETE");
2191 break;
2192 case AUDIT_TYPE_CHILD_CREATE:
2193 audit_log_format(ab, " nametype=CREATE");
2194 break;
2195 default:
2196 audit_log_format(ab, " nametype=UNKNOWN");
2197 break;
2198 }
2199
2200 audit_log_fcaps(ab, n);
2201 audit_log_end(ab);
2202}
2203
2204int audit_log_task_context(struct audit_buffer *ab) 2070int audit_log_task_context(struct audit_buffer *ab)
2205{ 2071{
2206 char *ctx = NULL; 2072 char *ctx = NULL;
@@ -2322,6 +2188,91 @@ void audit_log_link_denied(const char *operation)
2322 audit_log_end(ab); 2188 audit_log_end(ab);
2323} 2189}
2324 2190
2191/* global counter which is incremented every time something logs in */
2192static atomic_t session_id = ATOMIC_INIT(0);
2193
2194static int audit_set_loginuid_perm(kuid_t loginuid)
2195{
2196 /* if we are unset, we don't need privs */
2197 if (!audit_loginuid_set(current))
2198 return 0;
2199 /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/
2200 if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE))
2201 return -EPERM;
2202 /* it is set, you need permission */
2203 if (!capable(CAP_AUDIT_CONTROL))
2204 return -EPERM;
2205 /* reject if this is not an unset and we don't allow that */
2206 if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID)
2207 && uid_valid(loginuid))
2208 return -EPERM;
2209 return 0;
2210}
2211
2212static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid,
2213 unsigned int oldsessionid,
2214 unsigned int sessionid, int rc)
2215{
2216 struct audit_buffer *ab;
2217 uid_t uid, oldloginuid, loginuid;
2218 struct tty_struct *tty;
2219
2220 if (!audit_enabled)
2221 return;
2222
2223 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
2224 if (!ab)
2225 return;
2226
2227 uid = from_kuid(&init_user_ns, task_uid(current));
2228 oldloginuid = from_kuid(&init_user_ns, koldloginuid);
2229 loginuid = from_kuid(&init_user_ns, kloginuid),
2230 tty = audit_get_tty();
2231
2232 audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid);
2233 audit_log_task_context(ab);
2234 audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d",
2235 oldloginuid, loginuid, tty ? tty_name(tty) : "(none)",
2236 oldsessionid, sessionid, !rc);
2237 audit_put_tty(tty);
2238 audit_log_end(ab);
2239}
2240
2241/**
2242 * audit_set_loginuid - set current task's loginuid
2243 * @loginuid: loginuid value
2244 *
2245 * Returns 0.
2246 *
2247 * Called (set) from fs/proc/base.c::proc_loginuid_write().
2248 */
2249int audit_set_loginuid(kuid_t loginuid)
2250{
2251 unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET;
2252 kuid_t oldloginuid;
2253 int rc;
2254
2255 oldloginuid = audit_get_loginuid(current);
2256 oldsessionid = audit_get_sessionid(current);
2257
2258 rc = audit_set_loginuid_perm(loginuid);
2259 if (rc)
2260 goto out;
2261
2262 /* are we setting or clearing? */
2263 if (uid_valid(loginuid)) {
2264 sessionid = (unsigned int)atomic_inc_return(&session_id);
2265 if (unlikely(sessionid == AUDIT_SID_UNSET))
2266 sessionid = (unsigned int)atomic_inc_return(&session_id);
2267 }
2268
2269 current->sessionid = sessionid;
2270 current->loginuid = loginuid;
2271out:
2272 audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
2273 return rc;
2274}
2275
2325/** 2276/**
2326 * audit_log_end - end one audit record 2277 * audit_log_end - end one audit record
2327 * @ab: the audit_buffer 2278 * @ab: the audit_buffer