| .. | .. |
|---|
| 75 | 75 | #include <linux/uaccess.h> |
|---|
| 76 | 76 | #include <linux/fsnotify_backend.h> |
|---|
| 77 | 77 | #include <uapi/linux/limits.h> |
|---|
| 78 | +#include <uapi/linux/netfilter/nf_tables.h> |
|---|
| 78 | 79 | |
|---|
| 79 | 80 | #include "audit.h" |
|---|
| 80 | 81 | |
|---|
| .. | .. |
|---|
| 128 | 129 | struct audit_tree_refs { |
|---|
| 129 | 130 | struct audit_tree_refs *next; |
|---|
| 130 | 131 | struct audit_chunk *c[31]; |
|---|
| 132 | +}; |
|---|
| 133 | + |
|---|
| 134 | +struct audit_nfcfgop_tab { |
|---|
| 135 | + enum audit_nfcfgop op; |
|---|
| 136 | + const char *s; |
|---|
| 137 | +}; |
|---|
| 138 | + |
|---|
| 139 | +static const struct audit_nfcfgop_tab audit_nfcfgs[] = { |
|---|
| 140 | + { AUDIT_XT_OP_REGISTER, "xt_register" }, |
|---|
| 141 | + { AUDIT_XT_OP_REPLACE, "xt_replace" }, |
|---|
| 142 | + { AUDIT_XT_OP_UNREGISTER, "xt_unregister" }, |
|---|
| 143 | + { AUDIT_NFT_OP_TABLE_REGISTER, "nft_register_table" }, |
|---|
| 144 | + { AUDIT_NFT_OP_TABLE_UNREGISTER, "nft_unregister_table" }, |
|---|
| 145 | + { AUDIT_NFT_OP_CHAIN_REGISTER, "nft_register_chain" }, |
|---|
| 146 | + { AUDIT_NFT_OP_CHAIN_UNREGISTER, "nft_unregister_chain" }, |
|---|
| 147 | + { AUDIT_NFT_OP_RULE_REGISTER, "nft_register_rule" }, |
|---|
| 148 | + { AUDIT_NFT_OP_RULE_UNREGISTER, "nft_unregister_rule" }, |
|---|
| 149 | + { AUDIT_NFT_OP_SET_REGISTER, "nft_register_set" }, |
|---|
| 150 | + { AUDIT_NFT_OP_SET_UNREGISTER, "nft_unregister_set" }, |
|---|
| 151 | + { AUDIT_NFT_OP_SETELEM_REGISTER, "nft_register_setelem" }, |
|---|
| 152 | + { AUDIT_NFT_OP_SETELEM_UNREGISTER, "nft_unregister_setelem" }, |
|---|
| 153 | + { AUDIT_NFT_OP_GEN_REGISTER, "nft_register_gen" }, |
|---|
| 154 | + { AUDIT_NFT_OP_OBJ_REGISTER, "nft_register_obj" }, |
|---|
| 155 | + { AUDIT_NFT_OP_OBJ_UNREGISTER, "nft_unregister_obj" }, |
|---|
| 156 | + { AUDIT_NFT_OP_OBJ_RESET, "nft_reset_obj" }, |
|---|
| 157 | + { AUDIT_NFT_OP_FLOWTABLE_REGISTER, "nft_register_flowtable" }, |
|---|
| 158 | + { AUDIT_NFT_OP_FLOWTABLE_UNREGISTER, "nft_unregister_flowtable" }, |
|---|
| 159 | + { AUDIT_NFT_OP_INVALID, "nft_invalid" }, |
|---|
| 131 | 160 | }; |
|---|
| 132 | 161 | |
|---|
| 133 | 162 | static int audit_match_perm(struct audit_context *ctx, int mask) |
|---|
| .. | .. |
|---|
| 200 | 229 | * References in it _are_ dropped - at the same time we free/drop aux stuff. |
|---|
| 201 | 230 | */ |
|---|
| 202 | 231 | |
|---|
| 203 | | -#ifdef CONFIG_AUDIT_TREE |
|---|
| 204 | 232 | static void audit_set_auditable(struct audit_context *ctx) |
|---|
| 205 | 233 | { |
|---|
| 206 | 234 | if (!ctx->prio) { |
|---|
| .. | .. |
|---|
| 245 | 273 | ctx->tree_count = 31; |
|---|
| 246 | 274 | return 1; |
|---|
| 247 | 275 | } |
|---|
| 248 | | -#endif |
|---|
| 249 | 276 | |
|---|
| 250 | 277 | static void unroll_tree_refs(struct audit_context *ctx, |
|---|
| 251 | 278 | struct audit_tree_refs *p, int count) |
|---|
| 252 | 279 | { |
|---|
| 253 | | -#ifdef CONFIG_AUDIT_TREE |
|---|
| 254 | 280 | struct audit_tree_refs *q; |
|---|
| 255 | 281 | int n; |
|---|
| 256 | 282 | if (!p) { |
|---|
| .. | .. |
|---|
| 274 | 300 | } |
|---|
| 275 | 301 | ctx->trees = p; |
|---|
| 276 | 302 | ctx->tree_count = count; |
|---|
| 277 | | -#endif |
|---|
| 278 | 303 | } |
|---|
| 279 | 304 | |
|---|
| 280 | 305 | static void free_tree_refs(struct audit_context *ctx) |
|---|
| .. | .. |
|---|
| 288 | 313 | |
|---|
| 289 | 314 | static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) |
|---|
| 290 | 315 | { |
|---|
| 291 | | -#ifdef CONFIG_AUDIT_TREE |
|---|
| 292 | 316 | struct audit_tree_refs *p; |
|---|
| 293 | 317 | int n; |
|---|
| 294 | 318 | if (!tree) |
|---|
| .. | .. |
|---|
| 305 | 329 | if (audit_tree_match(p->c[n], tree)) |
|---|
| 306 | 330 | return 1; |
|---|
| 307 | 331 | } |
|---|
| 308 | | -#endif |
|---|
| 309 | 332 | return 0; |
|---|
| 310 | 333 | } |
|---|
| 311 | 334 | |
|---|
| .. | .. |
|---|
| 607 | 630 | } |
|---|
| 608 | 631 | break; |
|---|
| 609 | 632 | case AUDIT_WATCH: |
|---|
| 610 | | - if (name) |
|---|
| 611 | | - result = audit_watch_compare(rule->watch, name->ino, name->dev); |
|---|
| 633 | + if (name) { |
|---|
| 634 | + result = audit_watch_compare(rule->watch, |
|---|
| 635 | + name->ino, |
|---|
| 636 | + name->dev); |
|---|
| 637 | + if (f->op == Audit_not_equal) |
|---|
| 638 | + result = !result; |
|---|
| 639 | + } |
|---|
| 612 | 640 | break; |
|---|
| 613 | 641 | case AUDIT_DIR: |
|---|
| 614 | | - if (ctx) |
|---|
| 642 | + if (ctx) { |
|---|
| 615 | 643 | result = match_tree_refs(ctx, rule->tree); |
|---|
| 644 | + if (f->op == Audit_not_equal) |
|---|
| 645 | + result = !result; |
|---|
| 646 | + } |
|---|
| 616 | 647 | break; |
|---|
| 617 | 648 | case AUDIT_LOGINUID: |
|---|
| 618 | 649 | result = audit_uid_comparator(audit_get_loginuid(tsk), |
|---|
| .. | .. |
|---|
| 620 | 651 | break; |
|---|
| 621 | 652 | case AUDIT_LOGINUID_SET: |
|---|
| 622 | 653 | result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val); |
|---|
| 654 | + break; |
|---|
| 655 | + case AUDIT_SADDR_FAM: |
|---|
| 656 | + if (ctx && ctx->sockaddr) |
|---|
| 657 | + result = audit_comparator(ctx->sockaddr->ss_family, |
|---|
| 658 | + f->op, f->val); |
|---|
| 623 | 659 | break; |
|---|
| 624 | 660 | case AUDIT_SUBJ_USER: |
|---|
| 625 | 661 | case AUDIT_SUBJ_ROLE: |
|---|
| .. | .. |
|---|
| 637 | 673 | need_sid = 0; |
|---|
| 638 | 674 | } |
|---|
| 639 | 675 | result = security_audit_rule_match(sid, f->type, |
|---|
| 640 | | - f->op, |
|---|
| 641 | | - f->lsm_rule, |
|---|
| 642 | | - ctx); |
|---|
| 676 | + f->op, |
|---|
| 677 | + f->lsm_rule); |
|---|
| 643 | 678 | } |
|---|
| 644 | 679 | break; |
|---|
| 645 | 680 | case AUDIT_OBJ_USER: |
|---|
| .. | .. |
|---|
| 653 | 688 | /* Find files that match */ |
|---|
| 654 | 689 | if (name) { |
|---|
| 655 | 690 | result = security_audit_rule_match( |
|---|
| 656 | | - name->osid, f->type, f->op, |
|---|
| 657 | | - f->lsm_rule, ctx); |
|---|
| 691 | + name->osid, |
|---|
| 692 | + f->type, |
|---|
| 693 | + f->op, |
|---|
| 694 | + f->lsm_rule); |
|---|
| 658 | 695 | } else if (ctx) { |
|---|
| 659 | 696 | list_for_each_entry(n, &ctx->names_list, list) { |
|---|
| 660 | | - if (security_audit_rule_match(n->osid, f->type, |
|---|
| 661 | | - f->op, f->lsm_rule, |
|---|
| 662 | | - ctx)) { |
|---|
| 697 | + if (security_audit_rule_match( |
|---|
| 698 | + n->osid, |
|---|
| 699 | + f->type, |
|---|
| 700 | + f->op, |
|---|
| 701 | + f->lsm_rule)) { |
|---|
| 663 | 702 | ++result; |
|---|
| 664 | 703 | break; |
|---|
| 665 | 704 | } |
|---|
| .. | .. |
|---|
| 670 | 709 | break; |
|---|
| 671 | 710 | if (security_audit_rule_match(ctx->ipc.osid, |
|---|
| 672 | 711 | f->type, f->op, |
|---|
| 673 | | - f->lsm_rule, ctx)) |
|---|
| 712 | + f->lsm_rule)) |
|---|
| 674 | 713 | ++result; |
|---|
| 675 | 714 | } |
|---|
| 676 | 715 | break; |
|---|
| .. | .. |
|---|
| 687 | 726 | break; |
|---|
| 688 | 727 | case AUDIT_PERM: |
|---|
| 689 | 728 | result = audit_match_perm(ctx, f->val); |
|---|
| 729 | + if (f->op == Audit_not_equal) |
|---|
| 730 | + result = !result; |
|---|
| 690 | 731 | break; |
|---|
| 691 | 732 | case AUDIT_FILETYPE: |
|---|
| 692 | 733 | result = audit_match_filetype(ctx, f->val); |
|---|
| 734 | + if (f->op == Audit_not_equal) |
|---|
| 735 | + result = !result; |
|---|
| 693 | 736 | break; |
|---|
| 694 | 737 | case AUDIT_FIELD_COMPARE: |
|---|
| 695 | 738 | result = audit_field_compare(tsk, cred, f, ctx, name); |
|---|
| .. | .. |
|---|
| 774 | 817 | return AUDIT_DISABLED; |
|---|
| 775 | 818 | |
|---|
| 776 | 819 | rcu_read_lock(); |
|---|
| 777 | | - if (!list_empty(list)) { |
|---|
| 778 | | - list_for_each_entry_rcu(e, list, list) { |
|---|
| 779 | | - if (audit_in_mask(&e->rule, ctx->major) && |
|---|
| 780 | | - audit_filter_rules(tsk, &e->rule, ctx, NULL, |
|---|
| 781 | | - &state, false)) { |
|---|
| 782 | | - rcu_read_unlock(); |
|---|
| 783 | | - ctx->current_state = state; |
|---|
| 784 | | - return state; |
|---|
| 785 | | - } |
|---|
| 820 | + list_for_each_entry_rcu(e, list, list) { |
|---|
| 821 | + if (audit_in_mask(&e->rule, ctx->major) && |
|---|
| 822 | + audit_filter_rules(tsk, &e->rule, ctx, NULL, |
|---|
| 823 | + &state, false)) { |
|---|
| 824 | + rcu_read_unlock(); |
|---|
| 825 | + ctx->current_state = state; |
|---|
| 826 | + return state; |
|---|
| 786 | 827 | } |
|---|
| 787 | 828 | } |
|---|
| 788 | 829 | rcu_read_unlock(); |
|---|
| .. | .. |
|---|
| 801 | 842 | struct audit_entry *e; |
|---|
| 802 | 843 | enum audit_state state; |
|---|
| 803 | 844 | |
|---|
| 804 | | - if (list_empty(list)) |
|---|
| 805 | | - return 0; |
|---|
| 806 | | - |
|---|
| 807 | 845 | list_for_each_entry_rcu(e, list, list) { |
|---|
| 808 | 846 | if (audit_in_mask(&e->rule, ctx->major) && |
|---|
| 809 | 847 | audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) { |
|---|
| .. | .. |
|---|
| 811 | 849 | return 1; |
|---|
| 812 | 850 | } |
|---|
| 813 | 851 | } |
|---|
| 814 | | - |
|---|
| 815 | 852 | return 0; |
|---|
| 816 | 853 | } |
|---|
| 817 | 854 | |
|---|
| .. | .. |
|---|
| 836 | 873 | rcu_read_unlock(); |
|---|
| 837 | 874 | } |
|---|
| 838 | 875 | |
|---|
| 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 | 876 | static inline void audit_proctitle_free(struct audit_context *context) |
|---|
| 878 | 877 | { |
|---|
| 879 | 878 | kfree(context->proctitle.value); |
|---|
| .. | .. |
|---|
| 881 | 880 | context->proctitle.len = 0; |
|---|
| 882 | 881 | } |
|---|
| 883 | 882 | |
|---|
| 883 | +static inline void audit_free_module(struct audit_context *context) |
|---|
| 884 | +{ |
|---|
| 885 | + if (context->type == AUDIT_KERN_MODULE) { |
|---|
| 886 | + kfree(context->module.name); |
|---|
| 887 | + context->module.name = NULL; |
|---|
| 888 | + } |
|---|
| 889 | +} |
|---|
| 884 | 890 | static inline void audit_free_names(struct audit_context *context) |
|---|
| 885 | 891 | { |
|---|
| 886 | 892 | struct audit_names *n, *next; |
|---|
| .. | .. |
|---|
| 964 | 970 | |
|---|
| 965 | 971 | static inline void audit_free_context(struct audit_context *context) |
|---|
| 966 | 972 | { |
|---|
| 973 | + audit_free_module(context); |
|---|
| 967 | 974 | audit_free_names(context); |
|---|
| 968 | 975 | unroll_tree_refs(context, NULL, 0); |
|---|
| 969 | 976 | free_tree_refs(context); |
|---|
| .. | .. |
|---|
| 1180 | 1187 | kfree(buf_head); |
|---|
| 1181 | 1188 | } |
|---|
| 1182 | 1189 | |
|---|
| 1190 | +static void audit_log_cap(struct audit_buffer *ab, char *prefix, |
|---|
| 1191 | + kernel_cap_t *cap) |
|---|
| 1192 | +{ |
|---|
| 1193 | + int i; |
|---|
| 1194 | + |
|---|
| 1195 | + if (cap_isclear(*cap)) { |
|---|
| 1196 | + audit_log_format(ab, " %s=0", prefix); |
|---|
| 1197 | + return; |
|---|
| 1198 | + } |
|---|
| 1199 | + audit_log_format(ab, " %s=", prefix); |
|---|
| 1200 | + CAP_FOR_EACH_U32(i) |
|---|
| 1201 | + audit_log_format(ab, "%08x", cap->cap[CAP_LAST_U32 - i]); |
|---|
| 1202 | +} |
|---|
| 1203 | + |
|---|
| 1204 | +static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) |
|---|
| 1205 | +{ |
|---|
| 1206 | + if (name->fcap_ver == -1) { |
|---|
| 1207 | + audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?"); |
|---|
| 1208 | + return; |
|---|
| 1209 | + } |
|---|
| 1210 | + audit_log_cap(ab, "cap_fp", &name->fcap.permitted); |
|---|
| 1211 | + audit_log_cap(ab, "cap_fi", &name->fcap.inheritable); |
|---|
| 1212 | + audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d", |
|---|
| 1213 | + name->fcap.fE, name->fcap_ver, |
|---|
| 1214 | + from_kuid(&init_user_ns, name->fcap.rootid)); |
|---|
| 1215 | +} |
|---|
| 1216 | + |
|---|
| 1217 | +static void audit_log_time(struct audit_context *context, struct audit_buffer **ab) |
|---|
| 1218 | +{ |
|---|
| 1219 | + const struct audit_ntp_data *ntp = &context->time.ntp_data; |
|---|
| 1220 | + const struct timespec64 *tk = &context->time.tk_injoffset; |
|---|
| 1221 | + static const char * const ntp_name[] = { |
|---|
| 1222 | + "offset", |
|---|
| 1223 | + "freq", |
|---|
| 1224 | + "status", |
|---|
| 1225 | + "tai", |
|---|
| 1226 | + "tick", |
|---|
| 1227 | + "adjust", |
|---|
| 1228 | + }; |
|---|
| 1229 | + int type; |
|---|
| 1230 | + |
|---|
| 1231 | + if (context->type == AUDIT_TIME_ADJNTPVAL) { |
|---|
| 1232 | + for (type = 0; type < AUDIT_NTP_NVALS; type++) { |
|---|
| 1233 | + if (ntp->vals[type].newval != ntp->vals[type].oldval) { |
|---|
| 1234 | + if (!*ab) { |
|---|
| 1235 | + *ab = audit_log_start(context, |
|---|
| 1236 | + GFP_KERNEL, |
|---|
| 1237 | + AUDIT_TIME_ADJNTPVAL); |
|---|
| 1238 | + if (!*ab) |
|---|
| 1239 | + return; |
|---|
| 1240 | + } |
|---|
| 1241 | + audit_log_format(*ab, "op=%s old=%lli new=%lli", |
|---|
| 1242 | + ntp_name[type], |
|---|
| 1243 | + ntp->vals[type].oldval, |
|---|
| 1244 | + ntp->vals[type].newval); |
|---|
| 1245 | + audit_log_end(*ab); |
|---|
| 1246 | + *ab = NULL; |
|---|
| 1247 | + } |
|---|
| 1248 | + } |
|---|
| 1249 | + } |
|---|
| 1250 | + if (tk->tv_sec != 0 || tk->tv_nsec != 0) { |
|---|
| 1251 | + if (!*ab) { |
|---|
| 1252 | + *ab = audit_log_start(context, GFP_KERNEL, |
|---|
| 1253 | + AUDIT_TIME_INJOFFSET); |
|---|
| 1254 | + if (!*ab) |
|---|
| 1255 | + return; |
|---|
| 1256 | + } |
|---|
| 1257 | + audit_log_format(*ab, "sec=%lli nsec=%li", |
|---|
| 1258 | + (long long)tk->tv_sec, tk->tv_nsec); |
|---|
| 1259 | + audit_log_end(*ab); |
|---|
| 1260 | + *ab = NULL; |
|---|
| 1261 | + } |
|---|
| 1262 | +} |
|---|
| 1263 | + |
|---|
| 1183 | 1264 | static void show_special(struct audit_context *context, int *call_panic) |
|---|
| 1184 | 1265 | { |
|---|
| 1185 | 1266 | struct audit_buffer *ab; |
|---|
| .. | .. |
|---|
| 1281 | 1362 | audit_log_format(ab, "name="); |
|---|
| 1282 | 1363 | if (context->module.name) { |
|---|
| 1283 | 1364 | audit_log_untrustedstring(ab, context->module.name); |
|---|
| 1284 | | - kfree(context->module.name); |
|---|
| 1285 | 1365 | } else |
|---|
| 1286 | 1366 | audit_log_format(ab, "(null)"); |
|---|
| 1287 | 1367 | |
|---|
| 1368 | + break; |
|---|
| 1369 | + case AUDIT_TIME_ADJNTPVAL: |
|---|
| 1370 | + case AUDIT_TIME_INJOFFSET: |
|---|
| 1371 | + /* this call deviates from the rest, eating the buffer */ |
|---|
| 1372 | + audit_log_time(context, &ab); |
|---|
| 1288 | 1373 | break; |
|---|
| 1289 | 1374 | } |
|---|
| 1290 | 1375 | audit_log_end(ab); |
|---|
| .. | .. |
|---|
| 1302 | 1387 | return len; |
|---|
| 1303 | 1388 | } |
|---|
| 1304 | 1389 | |
|---|
| 1305 | | -static void audit_log_proctitle(struct task_struct *tsk, |
|---|
| 1306 | | - struct audit_context *context) |
|---|
| 1390 | +/* |
|---|
| 1391 | + * audit_log_name - produce AUDIT_PATH record from struct audit_names |
|---|
| 1392 | + * @context: audit_context for the task |
|---|
| 1393 | + * @n: audit_names structure with reportable details |
|---|
| 1394 | + * @path: optional path to report instead of audit_names->name |
|---|
| 1395 | + * @record_num: record number to report when handling a list of names |
|---|
| 1396 | + * @call_panic: optional pointer to int that will be updated if secid fails |
|---|
| 1397 | + */ |
|---|
| 1398 | +static void audit_log_name(struct audit_context *context, struct audit_names *n, |
|---|
| 1399 | + const struct path *path, int record_num, int *call_panic) |
|---|
| 1400 | +{ |
|---|
| 1401 | + struct audit_buffer *ab; |
|---|
| 1402 | + |
|---|
| 1403 | + ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); |
|---|
| 1404 | + if (!ab) |
|---|
| 1405 | + return; |
|---|
| 1406 | + |
|---|
| 1407 | + audit_log_format(ab, "item=%d", record_num); |
|---|
| 1408 | + |
|---|
| 1409 | + if (path) |
|---|
| 1410 | + audit_log_d_path(ab, " name=", path); |
|---|
| 1411 | + else if (n->name) { |
|---|
| 1412 | + switch (n->name_len) { |
|---|
| 1413 | + case AUDIT_NAME_FULL: |
|---|
| 1414 | + /* log the full path */ |
|---|
| 1415 | + audit_log_format(ab, " name="); |
|---|
| 1416 | + audit_log_untrustedstring(ab, n->name->name); |
|---|
| 1417 | + break; |
|---|
| 1418 | + case 0: |
|---|
| 1419 | + /* name was specified as a relative path and the |
|---|
| 1420 | + * directory component is the cwd |
|---|
| 1421 | + */ |
|---|
| 1422 | + audit_log_d_path(ab, " name=", &context->pwd); |
|---|
| 1423 | + break; |
|---|
| 1424 | + default: |
|---|
| 1425 | + /* log the name's directory component */ |
|---|
| 1426 | + audit_log_format(ab, " name="); |
|---|
| 1427 | + audit_log_n_untrustedstring(ab, n->name->name, |
|---|
| 1428 | + n->name_len); |
|---|
| 1429 | + } |
|---|
| 1430 | + } else |
|---|
| 1431 | + audit_log_format(ab, " name=(null)"); |
|---|
| 1432 | + |
|---|
| 1433 | + if (n->ino != AUDIT_INO_UNSET) |
|---|
| 1434 | + audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x", |
|---|
| 1435 | + n->ino, |
|---|
| 1436 | + MAJOR(n->dev), |
|---|
| 1437 | + MINOR(n->dev), |
|---|
| 1438 | + n->mode, |
|---|
| 1439 | + from_kuid(&init_user_ns, n->uid), |
|---|
| 1440 | + from_kgid(&init_user_ns, n->gid), |
|---|
| 1441 | + MAJOR(n->rdev), |
|---|
| 1442 | + MINOR(n->rdev)); |
|---|
| 1443 | + if (n->osid != 0) { |
|---|
| 1444 | + char *ctx = NULL; |
|---|
| 1445 | + u32 len; |
|---|
| 1446 | + |
|---|
| 1447 | + if (security_secid_to_secctx( |
|---|
| 1448 | + n->osid, &ctx, &len)) { |
|---|
| 1449 | + audit_log_format(ab, " osid=%u", n->osid); |
|---|
| 1450 | + if (call_panic) |
|---|
| 1451 | + *call_panic = 2; |
|---|
| 1452 | + } else { |
|---|
| 1453 | + audit_log_format(ab, " obj=%s", ctx); |
|---|
| 1454 | + security_release_secctx(ctx, len); |
|---|
| 1455 | + } |
|---|
| 1456 | + } |
|---|
| 1457 | + |
|---|
| 1458 | + /* log the audit_names record type */ |
|---|
| 1459 | + switch (n->type) { |
|---|
| 1460 | + case AUDIT_TYPE_NORMAL: |
|---|
| 1461 | + audit_log_format(ab, " nametype=NORMAL"); |
|---|
| 1462 | + break; |
|---|
| 1463 | + case AUDIT_TYPE_PARENT: |
|---|
| 1464 | + audit_log_format(ab, " nametype=PARENT"); |
|---|
| 1465 | + break; |
|---|
| 1466 | + case AUDIT_TYPE_CHILD_DELETE: |
|---|
| 1467 | + audit_log_format(ab, " nametype=DELETE"); |
|---|
| 1468 | + break; |
|---|
| 1469 | + case AUDIT_TYPE_CHILD_CREATE: |
|---|
| 1470 | + audit_log_format(ab, " nametype=CREATE"); |
|---|
| 1471 | + break; |
|---|
| 1472 | + default: |
|---|
| 1473 | + audit_log_format(ab, " nametype=UNKNOWN"); |
|---|
| 1474 | + break; |
|---|
| 1475 | + } |
|---|
| 1476 | + |
|---|
| 1477 | + audit_log_fcaps(ab, n); |
|---|
| 1478 | + audit_log_end(ab); |
|---|
| 1479 | +} |
|---|
| 1480 | + |
|---|
| 1481 | +static void audit_log_proctitle(void) |
|---|
| 1307 | 1482 | { |
|---|
| 1308 | 1483 | int res; |
|---|
| 1309 | 1484 | char *buf; |
|---|
| 1310 | 1485 | char *msg = "(null)"; |
|---|
| 1311 | 1486 | int len = strlen(msg); |
|---|
| 1487 | + struct audit_context *context = audit_context(); |
|---|
| 1312 | 1488 | struct audit_buffer *ab; |
|---|
| 1489 | + |
|---|
| 1490 | + if (!context || context->dummy) |
|---|
| 1491 | + return; |
|---|
| 1313 | 1492 | |
|---|
| 1314 | 1493 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); |
|---|
| 1315 | 1494 | if (!ab) |
|---|
| .. | .. |
|---|
| 1323 | 1502 | if (!buf) |
|---|
| 1324 | 1503 | goto out; |
|---|
| 1325 | 1504 | /* Historically called this from procfs naming */ |
|---|
| 1326 | | - res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN); |
|---|
| 1505 | + res = get_cmdline(current, buf, MAX_PROCTITLE_AUDIT_LEN); |
|---|
| 1327 | 1506 | if (res == 0) { |
|---|
| 1328 | 1507 | kfree(buf); |
|---|
| 1329 | 1508 | goto out; |
|---|
| .. | .. |
|---|
| 1343 | 1522 | audit_log_end(ab); |
|---|
| 1344 | 1523 | } |
|---|
| 1345 | 1524 | |
|---|
| 1346 | | -static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
|---|
| 1525 | +static void audit_log_exit(void) |
|---|
| 1347 | 1526 | { |
|---|
| 1348 | 1527 | int i, call_panic = 0; |
|---|
| 1528 | + struct audit_context *context = audit_context(); |
|---|
| 1349 | 1529 | struct audit_buffer *ab; |
|---|
| 1350 | 1530 | struct audit_aux_data *aux; |
|---|
| 1351 | 1531 | struct audit_names *n; |
|---|
| 1352 | 1532 | |
|---|
| 1353 | | - /* tsk == current */ |
|---|
| 1354 | | - context->personality = tsk->personality; |
|---|
| 1533 | + context->personality = current->personality; |
|---|
| 1355 | 1534 | |
|---|
| 1356 | 1535 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); |
|---|
| 1357 | 1536 | if (!ab) |
|---|
| .. | .. |
|---|
| 1373 | 1552 | context->argv[3], |
|---|
| 1374 | 1553 | context->name_count); |
|---|
| 1375 | 1554 | |
|---|
| 1376 | | - audit_log_task_info(ab, tsk); |
|---|
| 1555 | + audit_log_task_info(ab); |
|---|
| 1377 | 1556 | audit_log_key(ab, context->filterkey); |
|---|
| 1378 | 1557 | audit_log_end(ab); |
|---|
| 1379 | 1558 | |
|---|
| .. | .. |
|---|
| 1399 | 1578 | audit_log_cap(ab, "pi", &axs->new_pcap.inheritable); |
|---|
| 1400 | 1579 | audit_log_cap(ab, "pe", &axs->new_pcap.effective); |
|---|
| 1401 | 1580 | audit_log_cap(ab, "pa", &axs->new_pcap.ambient); |
|---|
| 1581 | + audit_log_format(ab, " frootid=%d", |
|---|
| 1582 | + from_kuid(&init_user_ns, |
|---|
| 1583 | + axs->fcap.rootid)); |
|---|
| 1402 | 1584 | break; } |
|---|
| 1403 | 1585 | |
|---|
| 1404 | 1586 | } |
|---|
| .. | .. |
|---|
| 1462 | 1644 | audit_log_name(context, n, NULL, i++, &call_panic); |
|---|
| 1463 | 1645 | } |
|---|
| 1464 | 1646 | |
|---|
| 1465 | | - audit_log_proctitle(tsk, context); |
|---|
| 1647 | + audit_log_proctitle(); |
|---|
| 1466 | 1648 | |
|---|
| 1467 | 1649 | /* Send end of event record to help user space know we are finished */ |
|---|
| 1468 | 1650 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); |
|---|
| .. | .. |
|---|
| 1480 | 1662 | */ |
|---|
| 1481 | 1663 | void __audit_free(struct task_struct *tsk) |
|---|
| 1482 | 1664 | { |
|---|
| 1483 | | - struct audit_context *context; |
|---|
| 1665 | + struct audit_context *context = tsk->audit_context; |
|---|
| 1484 | 1666 | |
|---|
| 1485 | | - context = audit_take_context(tsk, 0, 0); |
|---|
| 1486 | 1667 | if (!context) |
|---|
| 1487 | 1668 | return; |
|---|
| 1488 | 1669 | |
|---|
| 1489 | | - /* Check for system calls that do not go through the exit |
|---|
| 1490 | | - * function (e.g., exit_group), then free context block. |
|---|
| 1491 | | - * We use GFP_ATOMIC here because we might be doing this |
|---|
| 1492 | | - * in the context of the idle thread */ |
|---|
| 1493 | | - /* that can happen only if we are called from do_exit() */ |
|---|
| 1494 | | - if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) |
|---|
| 1495 | | - audit_log_exit(context, tsk); |
|---|
| 1496 | 1670 | if (!list_empty(&context->killed_trees)) |
|---|
| 1497 | | - audit_kill_trees(&context->killed_trees); |
|---|
| 1671 | + audit_kill_trees(context); |
|---|
| 1498 | 1672 | |
|---|
| 1673 | + /* We are called either by do_exit() or the fork() error handling code; |
|---|
| 1674 | + * in the former case tsk == current and in the latter tsk is a |
|---|
| 1675 | + * random task_struct that doesn't doesn't have any meaningful data we |
|---|
| 1676 | + * need to log via audit_log_exit(). |
|---|
| 1677 | + */ |
|---|
| 1678 | + if (tsk == current && !context->dummy && context->in_syscall) { |
|---|
| 1679 | + context->return_valid = 0; |
|---|
| 1680 | + context->return_code = 0; |
|---|
| 1681 | + |
|---|
| 1682 | + audit_filter_syscall(tsk, context, |
|---|
| 1683 | + &audit_filter_list[AUDIT_FILTER_EXIT]); |
|---|
| 1684 | + audit_filter_inodes(tsk, context); |
|---|
| 1685 | + if (context->current_state == AUDIT_RECORD_CONTEXT) |
|---|
| 1686 | + audit_log_exit(); |
|---|
| 1687 | + } |
|---|
| 1688 | + |
|---|
| 1689 | + audit_set_context(tsk, NULL); |
|---|
| 1499 | 1690 | audit_free_context(context); |
|---|
| 1500 | 1691 | } |
|---|
| 1501 | 1692 | |
|---|
| .. | .. |
|---|
| 1537 | 1728 | return; |
|---|
| 1538 | 1729 | } |
|---|
| 1539 | 1730 | |
|---|
| 1540 | | - context->arch = syscall_get_arch(); |
|---|
| 1731 | + context->arch = syscall_get_arch(current); |
|---|
| 1541 | 1732 | context->major = major; |
|---|
| 1542 | 1733 | context->argv[0] = a1; |
|---|
| 1543 | 1734 | context->argv[1] = a2; |
|---|
| .. | .. |
|---|
| 1565 | 1756 | { |
|---|
| 1566 | 1757 | struct audit_context *context; |
|---|
| 1567 | 1758 | |
|---|
| 1568 | | - if (success) |
|---|
| 1569 | | - success = AUDITSC_SUCCESS; |
|---|
| 1570 | | - else |
|---|
| 1571 | | - success = AUDITSC_FAILURE; |
|---|
| 1572 | | - |
|---|
| 1573 | | - context = audit_take_context(current, success, return_code); |
|---|
| 1759 | + context = audit_context(); |
|---|
| 1574 | 1760 | if (!context) |
|---|
| 1575 | 1761 | return; |
|---|
| 1576 | 1762 | |
|---|
| 1577 | | - if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) |
|---|
| 1578 | | - audit_log_exit(context, current); |
|---|
| 1763 | + if (!list_empty(&context->killed_trees)) |
|---|
| 1764 | + audit_kill_trees(context); |
|---|
| 1765 | + |
|---|
| 1766 | + if (!context->dummy && context->in_syscall) { |
|---|
| 1767 | + if (success) |
|---|
| 1768 | + context->return_valid = AUDITSC_SUCCESS; |
|---|
| 1769 | + else |
|---|
| 1770 | + context->return_valid = AUDITSC_FAILURE; |
|---|
| 1771 | + |
|---|
| 1772 | + /* |
|---|
| 1773 | + * we need to fix up the return code in the audit logs if the |
|---|
| 1774 | + * actual return codes are later going to be fixed up by the |
|---|
| 1775 | + * arch specific signal handlers |
|---|
| 1776 | + * |
|---|
| 1777 | + * This is actually a test for: |
|---|
| 1778 | + * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) || |
|---|
| 1779 | + * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK) |
|---|
| 1780 | + * |
|---|
| 1781 | + * but is faster than a bunch of || |
|---|
| 1782 | + */ |
|---|
| 1783 | + if (unlikely(return_code <= -ERESTARTSYS) && |
|---|
| 1784 | + (return_code >= -ERESTART_RESTARTBLOCK) && |
|---|
| 1785 | + (return_code != -ENOIOCTLCMD)) |
|---|
| 1786 | + context->return_code = -EINTR; |
|---|
| 1787 | + else |
|---|
| 1788 | + context->return_code = return_code; |
|---|
| 1789 | + |
|---|
| 1790 | + audit_filter_syscall(current, context, |
|---|
| 1791 | + &audit_filter_list[AUDIT_FILTER_EXIT]); |
|---|
| 1792 | + audit_filter_inodes(current, context); |
|---|
| 1793 | + if (context->current_state == AUDIT_RECORD_CONTEXT) |
|---|
| 1794 | + audit_log_exit(); |
|---|
| 1795 | + } |
|---|
| 1579 | 1796 | |
|---|
| 1580 | 1797 | context->in_syscall = 0; |
|---|
| 1581 | 1798 | context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; |
|---|
| 1582 | 1799 | |
|---|
| 1583 | | - if (!list_empty(&context->killed_trees)) |
|---|
| 1584 | | - audit_kill_trees(&context->killed_trees); |
|---|
| 1585 | | - |
|---|
| 1800 | + audit_free_module(context); |
|---|
| 1586 | 1801 | audit_free_names(context); |
|---|
| 1587 | 1802 | unroll_tree_refs(context, NULL, 0); |
|---|
| 1588 | 1803 | audit_free_aux(context); |
|---|
| .. | .. |
|---|
| 1597 | 1812 | kfree(context->filterkey); |
|---|
| 1598 | 1813 | context->filterkey = NULL; |
|---|
| 1599 | 1814 | } |
|---|
| 1600 | | - audit_set_context(current, context); |
|---|
| 1601 | 1815 | } |
|---|
| 1602 | 1816 | |
|---|
| 1603 | 1817 | static inline void handle_one(const struct inode *inode) |
|---|
| 1604 | 1818 | { |
|---|
| 1605 | | -#ifdef CONFIG_AUDIT_TREE |
|---|
| 1606 | 1819 | struct audit_context *context; |
|---|
| 1607 | 1820 | struct audit_tree_refs *p; |
|---|
| 1608 | 1821 | struct audit_chunk *chunk; |
|---|
| .. | .. |
|---|
| 1627 | 1840 | return; |
|---|
| 1628 | 1841 | } |
|---|
| 1629 | 1842 | put_tree_ref(context, chunk); |
|---|
| 1630 | | -#endif |
|---|
| 1631 | 1843 | } |
|---|
| 1632 | 1844 | |
|---|
| 1633 | 1845 | static void handle_path(const struct dentry *dentry) |
|---|
| 1634 | 1846 | { |
|---|
| 1635 | | -#ifdef CONFIG_AUDIT_TREE |
|---|
| 1636 | 1847 | struct audit_context *context; |
|---|
| 1637 | 1848 | struct audit_tree_refs *p; |
|---|
| 1638 | 1849 | const struct dentry *d, *parent; |
|---|
| .. | .. |
|---|
| 1685 | 1896 | return; |
|---|
| 1686 | 1897 | } |
|---|
| 1687 | 1898 | rcu_read_unlock(); |
|---|
| 1688 | | -#endif |
|---|
| 1689 | 1899 | } |
|---|
| 1690 | 1900 | |
|---|
| 1691 | 1901 | static struct audit_names *audit_alloc_name(struct audit_context *context, |
|---|
| .. | .. |
|---|
| 1736 | 1946 | return NULL; |
|---|
| 1737 | 1947 | } |
|---|
| 1738 | 1948 | |
|---|
| 1949 | +inline void _audit_getcwd(struct audit_context *context) |
|---|
| 1950 | +{ |
|---|
| 1951 | + if (!context->pwd.dentry) |
|---|
| 1952 | + get_fs_pwd(current->fs, &context->pwd); |
|---|
| 1953 | +} |
|---|
| 1954 | + |
|---|
| 1955 | +void __audit_getcwd(void) |
|---|
| 1956 | +{ |
|---|
| 1957 | + struct audit_context *context = audit_context(); |
|---|
| 1958 | + |
|---|
| 1959 | + if (context->in_syscall) |
|---|
| 1960 | + _audit_getcwd(context); |
|---|
| 1961 | +} |
|---|
| 1962 | + |
|---|
| 1739 | 1963 | /** |
|---|
| 1740 | 1964 | * __audit_getname - add a name to the list |
|---|
| 1741 | 1965 | * @name: name to add |
|---|
| .. | .. |
|---|
| 1760 | 1984 | name->aname = n; |
|---|
| 1761 | 1985 | name->refcnt++; |
|---|
| 1762 | 1986 | |
|---|
| 1763 | | - if (!context->pwd.dentry) |
|---|
| 1764 | | - get_fs_pwd(current->fs, &context->pwd); |
|---|
| 1987 | + _audit_getcwd(context); |
|---|
| 1988 | +} |
|---|
| 1989 | + |
|---|
| 1990 | +static inline int audit_copy_fcaps(struct audit_names *name, |
|---|
| 1991 | + const struct dentry *dentry) |
|---|
| 1992 | +{ |
|---|
| 1993 | + struct cpu_vfs_cap_data caps; |
|---|
| 1994 | + int rc; |
|---|
| 1995 | + |
|---|
| 1996 | + if (!dentry) |
|---|
| 1997 | + return 0; |
|---|
| 1998 | + |
|---|
| 1999 | + rc = get_vfs_caps_from_disk(dentry, &caps); |
|---|
| 2000 | + if (rc) |
|---|
| 2001 | + return rc; |
|---|
| 2002 | + |
|---|
| 2003 | + name->fcap.permitted = caps.permitted; |
|---|
| 2004 | + name->fcap.inheritable = caps.inheritable; |
|---|
| 2005 | + name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); |
|---|
| 2006 | + name->fcap.rootid = caps.rootid; |
|---|
| 2007 | + name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> |
|---|
| 2008 | + VFS_CAP_REVISION_SHIFT; |
|---|
| 2009 | + |
|---|
| 2010 | + return 0; |
|---|
| 2011 | +} |
|---|
| 2012 | + |
|---|
| 2013 | +/* Copy inode data into an audit_names. */ |
|---|
| 2014 | +static void audit_copy_inode(struct audit_names *name, |
|---|
| 2015 | + const struct dentry *dentry, |
|---|
| 2016 | + struct inode *inode, unsigned int flags) |
|---|
| 2017 | +{ |
|---|
| 2018 | + name->ino = inode->i_ino; |
|---|
| 2019 | + name->dev = inode->i_sb->s_dev; |
|---|
| 2020 | + name->mode = inode->i_mode; |
|---|
| 2021 | + name->uid = inode->i_uid; |
|---|
| 2022 | + name->gid = inode->i_gid; |
|---|
| 2023 | + name->rdev = inode->i_rdev; |
|---|
| 2024 | + security_inode_getsecid(inode, &name->osid); |
|---|
| 2025 | + if (flags & AUDIT_INODE_NOEVAL) { |
|---|
| 2026 | + name->fcap_ver = -1; |
|---|
| 2027 | + return; |
|---|
| 2028 | + } |
|---|
| 2029 | + audit_copy_fcaps(name, dentry); |
|---|
| 1765 | 2030 | } |
|---|
| 1766 | 2031 | |
|---|
| 1767 | 2032 | /** |
|---|
| .. | .. |
|---|
| 1777 | 2042 | struct inode *inode = d_backing_inode(dentry); |
|---|
| 1778 | 2043 | struct audit_names *n; |
|---|
| 1779 | 2044 | bool parent = flags & AUDIT_INODE_PARENT; |
|---|
| 2045 | + struct audit_entry *e; |
|---|
| 2046 | + struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS]; |
|---|
| 2047 | + int i; |
|---|
| 1780 | 2048 | |
|---|
| 1781 | 2049 | if (!context->in_syscall) |
|---|
| 1782 | 2050 | return; |
|---|
| 2051 | + |
|---|
| 2052 | + rcu_read_lock(); |
|---|
| 2053 | + list_for_each_entry_rcu(e, list, list) { |
|---|
| 2054 | + for (i = 0; i < e->rule.field_count; i++) { |
|---|
| 2055 | + struct audit_field *f = &e->rule.fields[i]; |
|---|
| 2056 | + |
|---|
| 2057 | + if (f->type == AUDIT_FSTYPE |
|---|
| 2058 | + && audit_comparator(inode->i_sb->s_magic, |
|---|
| 2059 | + f->op, f->val) |
|---|
| 2060 | + && e->rule.action == AUDIT_NEVER) { |
|---|
| 2061 | + rcu_read_unlock(); |
|---|
| 2062 | + return; |
|---|
| 2063 | + } |
|---|
| 2064 | + } |
|---|
| 2065 | + } |
|---|
| 2066 | + rcu_read_unlock(); |
|---|
| 1783 | 2067 | |
|---|
| 1784 | 2068 | if (!name) |
|---|
| 1785 | 2069 | goto out_alloc; |
|---|
| .. | .. |
|---|
| 1846 | 2130 | n->type = AUDIT_TYPE_NORMAL; |
|---|
| 1847 | 2131 | } |
|---|
| 1848 | 2132 | handle_path(dentry); |
|---|
| 1849 | | - audit_copy_inode(n, dentry, inode); |
|---|
| 2133 | + audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL); |
|---|
| 1850 | 2134 | } |
|---|
| 1851 | 2135 | |
|---|
| 1852 | 2136 | void __audit_file(const struct file *file) |
|---|
| .. | .. |
|---|
| 1874 | 2158 | { |
|---|
| 1875 | 2159 | struct audit_context *context = audit_context(); |
|---|
| 1876 | 2160 | struct inode *inode = d_backing_inode(dentry); |
|---|
| 1877 | | - const char *dname = dentry->d_name.name; |
|---|
| 2161 | + const struct qstr *dname = &dentry->d_name; |
|---|
| 1878 | 2162 | struct audit_names *n, *found_parent = NULL, *found_child = NULL; |
|---|
| 1879 | 2163 | struct audit_entry *e; |
|---|
| 1880 | 2164 | struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS]; |
|---|
| .. | .. |
|---|
| 1884 | 2168 | return; |
|---|
| 1885 | 2169 | |
|---|
| 1886 | 2170 | rcu_read_lock(); |
|---|
| 1887 | | - if (!list_empty(list)) { |
|---|
| 1888 | | - list_for_each_entry_rcu(e, list, list) { |
|---|
| 1889 | | - for (i = 0; i < e->rule.field_count; i++) { |
|---|
| 1890 | | - struct audit_field *f = &e->rule.fields[i]; |
|---|
| 2171 | + list_for_each_entry_rcu(e, list, list) { |
|---|
| 2172 | + for (i = 0; i < e->rule.field_count; i++) { |
|---|
| 2173 | + struct audit_field *f = &e->rule.fields[i]; |
|---|
| 1891 | 2174 | |
|---|
| 1892 | | - if (f->type == AUDIT_FSTYPE) { |
|---|
| 1893 | | - if (audit_comparator(parent->i_sb->s_magic, |
|---|
| 1894 | | - f->op, f->val)) { |
|---|
| 1895 | | - if (e->rule.action == AUDIT_NEVER) { |
|---|
| 1896 | | - rcu_read_unlock(); |
|---|
| 1897 | | - return; |
|---|
| 1898 | | - } |
|---|
| 1899 | | - } |
|---|
| 1900 | | - } |
|---|
| 2175 | + if (f->type == AUDIT_FSTYPE |
|---|
| 2176 | + && audit_comparator(parent->i_sb->s_magic, |
|---|
| 2177 | + f->op, f->val) |
|---|
| 2178 | + && e->rule.action == AUDIT_NEVER) { |
|---|
| 2179 | + rcu_read_unlock(); |
|---|
| 2180 | + return; |
|---|
| 1901 | 2181 | } |
|---|
| 1902 | 2182 | } |
|---|
| 1903 | 2183 | } |
|---|
| .. | .. |
|---|
| 1923 | 2203 | } |
|---|
| 1924 | 2204 | } |
|---|
| 1925 | 2205 | |
|---|
| 2206 | + cond_resched(); |
|---|
| 2207 | + |
|---|
| 1926 | 2208 | /* is there a matching child entry? */ |
|---|
| 1927 | 2209 | list_for_each_entry(n, &context->names_list, list) { |
|---|
| 1928 | 2210 | /* can only match entries that have a name */ |
|---|
| .. | .. |
|---|
| 1930 | 2212 | (n->type != type && n->type != AUDIT_TYPE_UNKNOWN)) |
|---|
| 1931 | 2213 | continue; |
|---|
| 1932 | 2214 | |
|---|
| 1933 | | - if (!strcmp(dname, n->name->name) || |
|---|
| 2215 | + if (!strcmp(dname->name, n->name->name) || |
|---|
| 1934 | 2216 | !audit_compare_dname_path(dname, n->name->name, |
|---|
| 1935 | 2217 | found_parent ? |
|---|
| 1936 | 2218 | found_parent->name_len : |
|---|
| .. | .. |
|---|
| 1947 | 2229 | n = audit_alloc_name(context, AUDIT_TYPE_PARENT); |
|---|
| 1948 | 2230 | if (!n) |
|---|
| 1949 | 2231 | return; |
|---|
| 1950 | | - audit_copy_inode(n, NULL, parent); |
|---|
| 2232 | + audit_copy_inode(n, NULL, parent, 0); |
|---|
| 1951 | 2233 | } |
|---|
| 1952 | 2234 | |
|---|
| 1953 | 2235 | if (!found_child) { |
|---|
| .. | .. |
|---|
| 1966 | 2248 | } |
|---|
| 1967 | 2249 | |
|---|
| 1968 | 2250 | if (inode) |
|---|
| 1969 | | - audit_copy_inode(found_child, dentry, inode); |
|---|
| 2251 | + audit_copy_inode(found_child, dentry, inode, 0); |
|---|
| 1970 | 2252 | else |
|---|
| 1971 | 2253 | found_child->ino = AUDIT_INO_UNSET; |
|---|
| 1972 | 2254 | } |
|---|
| .. | .. |
|---|
| 1995 | 2277 | ctx->current_state = AUDIT_RECORD_CONTEXT; |
|---|
| 1996 | 2278 | } |
|---|
| 1997 | 2279 | return 1; |
|---|
| 1998 | | -} |
|---|
| 1999 | | - |
|---|
| 2000 | | -/* global counter which is incremented every time something logs in */ |
|---|
| 2001 | | -static atomic_t session_id = ATOMIC_INIT(0); |
|---|
| 2002 | | - |
|---|
| 2003 | | -static int audit_set_loginuid_perm(kuid_t loginuid) |
|---|
| 2004 | | -{ |
|---|
| 2005 | | - /* if we are unset, we don't need privs */ |
|---|
| 2006 | | - if (!audit_loginuid_set(current)) |
|---|
| 2007 | | - return 0; |
|---|
| 2008 | | - /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/ |
|---|
| 2009 | | - if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE)) |
|---|
| 2010 | | - return -EPERM; |
|---|
| 2011 | | - /* it is set, you need permission */ |
|---|
| 2012 | | - if (!capable(CAP_AUDIT_CONTROL)) |
|---|
| 2013 | | - return -EPERM; |
|---|
| 2014 | | - /* reject if this is not an unset and we don't allow that */ |
|---|
| 2015 | | - if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) && uid_valid(loginuid)) |
|---|
| 2016 | | - return -EPERM; |
|---|
| 2017 | | - return 0; |
|---|
| 2018 | | -} |
|---|
| 2019 | | - |
|---|
| 2020 | | -static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, |
|---|
| 2021 | | - unsigned int oldsessionid, unsigned int sessionid, |
|---|
| 2022 | | - int rc) |
|---|
| 2023 | | -{ |
|---|
| 2024 | | - struct audit_buffer *ab; |
|---|
| 2025 | | - uid_t uid, oldloginuid, loginuid; |
|---|
| 2026 | | - struct tty_struct *tty; |
|---|
| 2027 | | - |
|---|
| 2028 | | - if (!audit_enabled) |
|---|
| 2029 | | - return; |
|---|
| 2030 | | - |
|---|
| 2031 | | - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); |
|---|
| 2032 | | - if (!ab) |
|---|
| 2033 | | - return; |
|---|
| 2034 | | - |
|---|
| 2035 | | - uid = from_kuid(&init_user_ns, task_uid(current)); |
|---|
| 2036 | | - oldloginuid = from_kuid(&init_user_ns, koldloginuid); |
|---|
| 2037 | | - loginuid = from_kuid(&init_user_ns, kloginuid), |
|---|
| 2038 | | - tty = audit_get_tty(current); |
|---|
| 2039 | | - |
|---|
| 2040 | | - audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid); |
|---|
| 2041 | | - audit_log_task_context(ab); |
|---|
| 2042 | | - audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d", |
|---|
| 2043 | | - oldloginuid, loginuid, tty ? tty_name(tty) : "(none)", |
|---|
| 2044 | | - oldsessionid, sessionid, !rc); |
|---|
| 2045 | | - audit_put_tty(tty); |
|---|
| 2046 | | - audit_log_end(ab); |
|---|
| 2047 | | -} |
|---|
| 2048 | | - |
|---|
| 2049 | | -/** |
|---|
| 2050 | | - * audit_set_loginuid - set current task's audit_context loginuid |
|---|
| 2051 | | - * @loginuid: loginuid value |
|---|
| 2052 | | - * |
|---|
| 2053 | | - * Returns 0. |
|---|
| 2054 | | - * |
|---|
| 2055 | | - * Called (set) from fs/proc/base.c::proc_loginuid_write(). |
|---|
| 2056 | | - */ |
|---|
| 2057 | | -int audit_set_loginuid(kuid_t loginuid) |
|---|
| 2058 | | -{ |
|---|
| 2059 | | - struct task_struct *task = current; |
|---|
| 2060 | | - unsigned int oldsessionid, sessionid = AUDIT_SID_UNSET; |
|---|
| 2061 | | - kuid_t oldloginuid; |
|---|
| 2062 | | - int rc; |
|---|
| 2063 | | - |
|---|
| 2064 | | - oldloginuid = audit_get_loginuid(current); |
|---|
| 2065 | | - oldsessionid = audit_get_sessionid(current); |
|---|
| 2066 | | - |
|---|
| 2067 | | - rc = audit_set_loginuid_perm(loginuid); |
|---|
| 2068 | | - if (rc) |
|---|
| 2069 | | - goto out; |
|---|
| 2070 | | - |
|---|
| 2071 | | - /* are we setting or clearing? */ |
|---|
| 2072 | | - if (uid_valid(loginuid)) { |
|---|
| 2073 | | - sessionid = (unsigned int)atomic_inc_return(&session_id); |
|---|
| 2074 | | - if (unlikely(sessionid == AUDIT_SID_UNSET)) |
|---|
| 2075 | | - sessionid = (unsigned int)atomic_inc_return(&session_id); |
|---|
| 2076 | | - } |
|---|
| 2077 | | - |
|---|
| 2078 | | - task->sessionid = sessionid; |
|---|
| 2079 | | - task->loginuid = loginuid; |
|---|
| 2080 | | -out: |
|---|
| 2081 | | - audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); |
|---|
| 2082 | | - return rc; |
|---|
| 2083 | 2280 | } |
|---|
| 2084 | 2281 | |
|---|
| 2085 | 2282 | /** |
|---|
| .. | .. |
|---|
| 2276 | 2473 | } |
|---|
| 2277 | 2474 | |
|---|
| 2278 | 2475 | /** |
|---|
| 2279 | | - * audit_signal_info - record signal info for shutting down audit subsystem |
|---|
| 2280 | | - * @sig: signal value |
|---|
| 2476 | + * audit_signal_info_syscall - record signal info for syscalls |
|---|
| 2281 | 2477 | * @t: task being signaled |
|---|
| 2282 | 2478 | * |
|---|
| 2283 | 2479 | * If the audit subsystem is being terminated, record the task (pid) |
|---|
| 2284 | 2480 | * and uid that is doing that. |
|---|
| 2285 | 2481 | */ |
|---|
| 2286 | | -int audit_signal_info(int sig, struct task_struct *t) |
|---|
| 2482 | +int audit_signal_info_syscall(struct task_struct *t) |
|---|
| 2287 | 2483 | { |
|---|
| 2288 | 2484 | struct audit_aux_data_pids *axp; |
|---|
| 2289 | 2485 | struct audit_context *ctx = audit_context(); |
|---|
| 2290 | | - kuid_t uid = current_uid(), auid, t_uid = task_uid(t); |
|---|
| 2291 | | - |
|---|
| 2292 | | - if (auditd_test_task(t) && |
|---|
| 2293 | | - (sig == SIGTERM || sig == SIGHUP || |
|---|
| 2294 | | - sig == SIGUSR1 || sig == SIGUSR2)) { |
|---|
| 2295 | | - audit_sig_pid = task_tgid_nr(current); |
|---|
| 2296 | | - auid = audit_get_loginuid(current); |
|---|
| 2297 | | - if (uid_valid(auid)) |
|---|
| 2298 | | - audit_sig_uid = auid; |
|---|
| 2299 | | - else |
|---|
| 2300 | | - audit_sig_uid = uid; |
|---|
| 2301 | | - security_task_getsecid(current, &audit_sig_sid); |
|---|
| 2302 | | - } |
|---|
| 2486 | + kuid_t t_uid = task_uid(t); |
|---|
| 2303 | 2487 | |
|---|
| 2304 | 2488 | if (!audit_signals || audit_dummy_context()) |
|---|
| 2305 | 2489 | return 0; |
|---|
| .. | .. |
|---|
| 2370 | 2554 | ax->fcap.permitted = vcaps.permitted; |
|---|
| 2371 | 2555 | ax->fcap.inheritable = vcaps.inheritable; |
|---|
| 2372 | 2556 | ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); |
|---|
| 2557 | + ax->fcap.rootid = vcaps.rootid; |
|---|
| 2373 | 2558 | ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; |
|---|
| 2374 | 2559 | |
|---|
| 2375 | 2560 | ax->old_pcap.permitted = old->cap_permitted; |
|---|
| .. | .. |
|---|
| 2426 | 2611 | audit_log(audit_context(), GFP_KERNEL, |
|---|
| 2427 | 2612 | AUDIT_FANOTIFY, "resp=%u", response); |
|---|
| 2428 | 2613 | } |
|---|
| 2614 | + |
|---|
| 2615 | +void __audit_tk_injoffset(struct timespec64 offset) |
|---|
| 2616 | +{ |
|---|
| 2617 | + struct audit_context *context = audit_context(); |
|---|
| 2618 | + |
|---|
| 2619 | + /* only set type if not already set by NTP */ |
|---|
| 2620 | + if (!context->type) |
|---|
| 2621 | + context->type = AUDIT_TIME_INJOFFSET; |
|---|
| 2622 | + memcpy(&context->time.tk_injoffset, &offset, sizeof(offset)); |
|---|
| 2623 | +} |
|---|
| 2624 | + |
|---|
| 2625 | +void __audit_ntp_log(const struct audit_ntp_data *ad) |
|---|
| 2626 | +{ |
|---|
| 2627 | + struct audit_context *context = audit_context(); |
|---|
| 2628 | + int type; |
|---|
| 2629 | + |
|---|
| 2630 | + for (type = 0; type < AUDIT_NTP_NVALS; type++) |
|---|
| 2631 | + if (ad->vals[type].newval != ad->vals[type].oldval) { |
|---|
| 2632 | + /* unconditionally set type, overwriting TK */ |
|---|
| 2633 | + context->type = AUDIT_TIME_ADJNTPVAL; |
|---|
| 2634 | + memcpy(&context->time.ntp_data, ad, sizeof(*ad)); |
|---|
| 2635 | + break; |
|---|
| 2636 | + } |
|---|
| 2637 | +} |
|---|
| 2638 | + |
|---|
| 2639 | +void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries, |
|---|
| 2640 | + enum audit_nfcfgop op, gfp_t gfp) |
|---|
| 2641 | +{ |
|---|
| 2642 | + struct audit_buffer *ab; |
|---|
| 2643 | + char comm[sizeof(current->comm)]; |
|---|
| 2644 | + |
|---|
| 2645 | + ab = audit_log_start(audit_context(), gfp, AUDIT_NETFILTER_CFG); |
|---|
| 2646 | + if (!ab) |
|---|
| 2647 | + return; |
|---|
| 2648 | + audit_log_format(ab, "table=%s family=%u entries=%u op=%s", |
|---|
| 2649 | + name, af, nentries, audit_nfcfgs[op].s); |
|---|
| 2650 | + |
|---|
| 2651 | + audit_log_format(ab, " pid=%u", task_pid_nr(current)); |
|---|
| 2652 | + audit_log_task_context(ab); /* subj= */ |
|---|
| 2653 | + audit_log_format(ab, " comm="); |
|---|
| 2654 | + audit_log_untrustedstring(ab, get_task_comm(comm, current)); |
|---|
| 2655 | + audit_log_end(ab); |
|---|
| 2656 | +} |
|---|
| 2657 | +EXPORT_SYMBOL_GPL(__audit_log_nfcfg); |
|---|
| 2429 | 2658 | |
|---|
| 2430 | 2659 | static void audit_log_task(struct audit_buffer *ab) |
|---|
| 2431 | 2660 | { |
|---|
| .. | .. |
|---|
| 2495 | 2724 | return; |
|---|
| 2496 | 2725 | audit_log_task(ab); |
|---|
| 2497 | 2726 | audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x", |
|---|
| 2498 | | - signr, syscall_get_arch(), syscall, |
|---|
| 2727 | + signr, syscall_get_arch(current), syscall, |
|---|
| 2499 | 2728 | in_compat_syscall(), KSTK_EIP(current), code); |
|---|
| 2500 | 2729 | audit_log_end(ab); |
|---|
| 2501 | 2730 | } |
|---|
| .. | .. |
|---|
| 2513 | 2742 | if (unlikely(!ab)) |
|---|
| 2514 | 2743 | return; |
|---|
| 2515 | 2744 | |
|---|
| 2516 | | - audit_log_format(ab, "op=seccomp-logging"); |
|---|
| 2517 | | - audit_log_format(ab, " actions=%s", names); |
|---|
| 2518 | | - audit_log_format(ab, " old-actions=%s", old_names); |
|---|
| 2519 | | - audit_log_format(ab, " res=%d", res); |
|---|
| 2745 | + audit_log_format(ab, |
|---|
| 2746 | + "op=seccomp-logging actions=%s old-actions=%s res=%d", |
|---|
| 2747 | + names, old_names, res); |
|---|
| 2520 | 2748 | audit_log_end(ab); |
|---|
| 2521 | 2749 | } |
|---|
| 2522 | 2750 | |
|---|