diff options
Diffstat (limited to 'kernel/auditsc.c')
| -rw-r--r-- | kernel/auditsc.c | 254 |
1 files changed, 199 insertions, 55 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 9ebd96fda295..105147631753 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -85,6 +85,9 @@ extern int audit_enabled; | |||
| 85 | /* Indicates that audit should log the full pathname. */ | 85 | /* Indicates that audit should log the full pathname. */ |
| 86 | #define AUDIT_NAME_FULL -1 | 86 | #define AUDIT_NAME_FULL -1 |
| 87 | 87 | ||
| 88 | /* number of audit rules */ | ||
| 89 | int audit_n_rules; | ||
| 90 | |||
| 88 | /* When fs/namei.c:getname() is called, we store the pointer in name and | 91 | /* When fs/namei.c:getname() is called, we store the pointer in name and |
| 89 | * we don't let putname() free it (instead we free all of the saved | 92 | * we don't let putname() free it (instead we free all of the saved |
| 90 | * pointers at syscall exit time). | 93 | * pointers at syscall exit time). |
| @@ -174,6 +177,7 @@ struct audit_aux_data_path { | |||
| 174 | 177 | ||
| 175 | /* The per-task audit context. */ | 178 | /* The per-task audit context. */ |
| 176 | struct audit_context { | 179 | struct audit_context { |
| 180 | int dummy; /* must be the first element */ | ||
| 177 | int in_syscall; /* 1 if task is in a syscall */ | 181 | int in_syscall; /* 1 if task is in a syscall */ |
| 178 | enum audit_state state; | 182 | enum audit_state state; |
| 179 | unsigned int serial; /* serial number for record */ | 183 | unsigned int serial; /* serial number for record */ |
| @@ -186,6 +190,7 @@ struct audit_context { | |||
| 186 | int auditable; /* 1 if record should be written */ | 190 | int auditable; /* 1 if record should be written */ |
| 187 | int name_count; | 191 | int name_count; |
| 188 | struct audit_names names[AUDIT_NAMES]; | 192 | struct audit_names names[AUDIT_NAMES]; |
| 193 | char * filterkey; /* key for rule that triggered record */ | ||
| 189 | struct dentry * pwd; | 194 | struct dentry * pwd; |
| 190 | struct vfsmount * pwdmnt; | 195 | struct vfsmount * pwdmnt; |
| 191 | struct audit_context *previous; /* For nested syscalls */ | 196 | struct audit_context *previous; /* For nested syscalls */ |
| @@ -204,6 +209,54 @@ struct audit_context { | |||
| 204 | #endif | 209 | #endif |
| 205 | }; | 210 | }; |
| 206 | 211 | ||
| 212 | #define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE]) | ||
| 213 | static inline int open_arg(int flags, int mask) | ||
| 214 | { | ||
| 215 | int n = ACC_MODE(flags); | ||
| 216 | if (flags & (O_TRUNC | O_CREAT)) | ||
| 217 | n |= AUDIT_PERM_WRITE; | ||
| 218 | return n & mask; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int audit_match_perm(struct audit_context *ctx, int mask) | ||
| 222 | { | ||
| 223 | unsigned n = ctx->major; | ||
| 224 | switch (audit_classify_syscall(ctx->arch, n)) { | ||
| 225 | case 0: /* native */ | ||
| 226 | if ((mask & AUDIT_PERM_WRITE) && | ||
| 227 | audit_match_class(AUDIT_CLASS_WRITE, n)) | ||
| 228 | return 1; | ||
| 229 | if ((mask & AUDIT_PERM_READ) && | ||
| 230 | audit_match_class(AUDIT_CLASS_READ, n)) | ||
| 231 | return 1; | ||
| 232 | if ((mask & AUDIT_PERM_ATTR) && | ||
| 233 | audit_match_class(AUDIT_CLASS_CHATTR, n)) | ||
| 234 | return 1; | ||
| 235 | return 0; | ||
| 236 | case 1: /* 32bit on biarch */ | ||
| 237 | if ((mask & AUDIT_PERM_WRITE) && | ||
| 238 | audit_match_class(AUDIT_CLASS_WRITE_32, n)) | ||
| 239 | return 1; | ||
| 240 | if ((mask & AUDIT_PERM_READ) && | ||
| 241 | audit_match_class(AUDIT_CLASS_READ_32, n)) | ||
| 242 | return 1; | ||
| 243 | if ((mask & AUDIT_PERM_ATTR) && | ||
| 244 | audit_match_class(AUDIT_CLASS_CHATTR_32, n)) | ||
| 245 | return 1; | ||
| 246 | return 0; | ||
| 247 | case 2: /* open */ | ||
| 248 | return mask & ACC_MODE(ctx->argv[1]); | ||
| 249 | case 3: /* openat */ | ||
| 250 | return mask & ACC_MODE(ctx->argv[2]); | ||
| 251 | case 4: /* socketcall */ | ||
| 252 | return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND); | ||
| 253 | case 5: /* execve */ | ||
| 254 | return mask & AUDIT_PERM_EXEC; | ||
| 255 | default: | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 207 | /* Determine if any context name data matches a rule's watch data */ | 260 | /* Determine if any context name data matches a rule's watch data */ |
| 208 | /* Compare a task_struct with an audit_rule. Return 1 on match, 0 | 261 | /* Compare a task_struct with an audit_rule. Return 1 on match, 0 |
| 209 | * otherwise. */ | 262 | * otherwise. */ |
| @@ -320,11 +373,11 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 320 | if (ctx) | 373 | if (ctx) |
| 321 | result = audit_comparator(ctx->loginuid, f->op, f->val); | 374 | result = audit_comparator(ctx->loginuid, f->op, f->val); |
| 322 | break; | 375 | break; |
| 323 | case AUDIT_SE_USER: | 376 | case AUDIT_SUBJ_USER: |
| 324 | case AUDIT_SE_ROLE: | 377 | case AUDIT_SUBJ_ROLE: |
| 325 | case AUDIT_SE_TYPE: | 378 | case AUDIT_SUBJ_TYPE: |
| 326 | case AUDIT_SE_SEN: | 379 | case AUDIT_SUBJ_SEN: |
| 327 | case AUDIT_SE_CLR: | 380 | case AUDIT_SUBJ_CLR: |
| 328 | /* NOTE: this may return negative values indicating | 381 | /* NOTE: this may return negative values indicating |
| 329 | a temporary error. We simply treat this as a | 382 | a temporary error. We simply treat this as a |
| 330 | match for now to avoid losing information that | 383 | match for now to avoid losing information that |
| @@ -332,7 +385,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 332 | logged upon error */ | 385 | logged upon error */ |
| 333 | if (f->se_rule) { | 386 | if (f->se_rule) { |
| 334 | if (need_sid) { | 387 | if (need_sid) { |
| 335 | selinux_task_ctxid(tsk, &sid); | 388 | selinux_get_task_sid(tsk, &sid); |
| 336 | need_sid = 0; | 389 | need_sid = 0; |
| 337 | } | 390 | } |
| 338 | result = selinux_audit_rule_match(sid, f->type, | 391 | result = selinux_audit_rule_match(sid, f->type, |
| @@ -341,6 +394,46 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 341 | ctx); | 394 | ctx); |
| 342 | } | 395 | } |
| 343 | break; | 396 | break; |
| 397 | case AUDIT_OBJ_USER: | ||
| 398 | case AUDIT_OBJ_ROLE: | ||
| 399 | case AUDIT_OBJ_TYPE: | ||
| 400 | case AUDIT_OBJ_LEV_LOW: | ||
| 401 | case AUDIT_OBJ_LEV_HIGH: | ||
| 402 | /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR | ||
| 403 | also applies here */ | ||
| 404 | if (f->se_rule) { | ||
| 405 | /* Find files that match */ | ||
| 406 | if (name) { | ||
| 407 | result = selinux_audit_rule_match( | ||
| 408 | name->osid, f->type, f->op, | ||
| 409 | f->se_rule, ctx); | ||
| 410 | } else if (ctx) { | ||
| 411 | for (j = 0; j < ctx->name_count; j++) { | ||
| 412 | if (selinux_audit_rule_match( | ||
| 413 | ctx->names[j].osid, | ||
| 414 | f->type, f->op, | ||
| 415 | f->se_rule, ctx)) { | ||
| 416 | ++result; | ||
| 417 | break; | ||
| 418 | } | ||
| 419 | } | ||
| 420 | } | ||
| 421 | /* Find ipc objects that match */ | ||
| 422 | if (ctx) { | ||
| 423 | struct audit_aux_data *aux; | ||
| 424 | for (aux = ctx->aux; aux; | ||
| 425 | aux = aux->next) { | ||
| 426 | if (aux->type == AUDIT_IPC) { | ||
| 427 | struct audit_aux_data_ipcctl *axi = (void *)aux; | ||
| 428 | if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) { | ||
| 429 | ++result; | ||
| 430 | break; | ||
| 431 | } | ||
| 432 | } | ||
| 433 | } | ||
| 434 | } | ||
| 435 | } | ||
| 436 | break; | ||
| 344 | case AUDIT_ARG0: | 437 | case AUDIT_ARG0: |
| 345 | case AUDIT_ARG1: | 438 | case AUDIT_ARG1: |
| 346 | case AUDIT_ARG2: | 439 | case AUDIT_ARG2: |
| @@ -348,11 +441,20 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 348 | if (ctx) | 441 | if (ctx) |
| 349 | result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); | 442 | result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); |
| 350 | break; | 443 | break; |
| 444 | case AUDIT_FILTERKEY: | ||
| 445 | /* ignore this field for filtering */ | ||
| 446 | result = 1; | ||
| 447 | break; | ||
| 448 | case AUDIT_PERM: | ||
| 449 | result = audit_match_perm(ctx, f->val); | ||
| 450 | break; | ||
| 351 | } | 451 | } |
| 352 | 452 | ||
| 353 | if (!result) | 453 | if (!result) |
| 354 | return 0; | 454 | return 0; |
| 355 | } | 455 | } |
| 456 | if (rule->filterkey) | ||
| 457 | ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); | ||
| 356 | switch (rule->action) { | 458 | switch (rule->action) { |
| 357 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; | 459 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; |
| 358 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; | 460 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; |
| @@ -467,7 +569,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
| 467 | context->return_valid = return_valid; | 569 | context->return_valid = return_valid; |
| 468 | context->return_code = return_code; | 570 | context->return_code = return_code; |
| 469 | 571 | ||
| 470 | if (context->in_syscall && !context->auditable) { | 572 | if (context->in_syscall && !context->dummy && !context->auditable) { |
| 471 | enum audit_state state; | 573 | enum audit_state state; |
| 472 | 574 | ||
| 473 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); | 575 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); |
| @@ -483,17 +585,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
| 483 | } | 585 | } |
| 484 | 586 | ||
| 485 | get_context: | 587 | get_context: |
| 486 | context->pid = tsk->pid; | 588 | |
| 487 | context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ | ||
| 488 | context->uid = tsk->uid; | ||
| 489 | context->gid = tsk->gid; | ||
| 490 | context->euid = tsk->euid; | ||
| 491 | context->suid = tsk->suid; | ||
| 492 | context->fsuid = tsk->fsuid; | ||
| 493 | context->egid = tsk->egid; | ||
| 494 | context->sgid = tsk->sgid; | ||
| 495 | context->fsgid = tsk->fsgid; | ||
| 496 | context->personality = tsk->personality; | ||
| 497 | tsk->audit_context = NULL; | 589 | tsk->audit_context = NULL; |
| 498 | return context; | 590 | return context; |
| 499 | } | 591 | } |
| @@ -627,6 +719,7 @@ static inline void audit_free_context(struct audit_context *context) | |||
| 627 | } | 719 | } |
| 628 | audit_free_names(context); | 720 | audit_free_names(context); |
| 629 | audit_free_aux(context); | 721 | audit_free_aux(context); |
| 722 | kfree(context->filterkey); | ||
| 630 | kfree(context); | 723 | kfree(context); |
| 631 | context = previous; | 724 | context = previous; |
| 632 | } while (context); | 725 | } while (context); |
| @@ -658,8 +751,7 @@ static void audit_log_task_context(struct audit_buffer *ab) | |||
| 658 | return; | 751 | return; |
| 659 | 752 | ||
| 660 | error_path: | 753 | error_path: |
| 661 | if (ctx) | 754 | kfree(ctx); |
| 662 | kfree(ctx); | ||
| 663 | audit_panic("error in audit_log_task_context"); | 755 | audit_panic("error in audit_log_task_context"); |
| 664 | return; | 756 | return; |
| 665 | } | 757 | } |
| @@ -702,6 +794,17 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 702 | const char *tty; | 794 | const char *tty; |
| 703 | 795 | ||
| 704 | /* tsk == current */ | 796 | /* tsk == current */ |
| 797 | context->pid = tsk->pid; | ||
| 798 | context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ | ||
| 799 | context->uid = tsk->uid; | ||
| 800 | context->gid = tsk->gid; | ||
| 801 | context->euid = tsk->euid; | ||
| 802 | context->suid = tsk->suid; | ||
| 803 | context->fsuid = tsk->fsuid; | ||
| 804 | context->egid = tsk->egid; | ||
| 805 | context->sgid = tsk->sgid; | ||
| 806 | context->fsgid = tsk->fsgid; | ||
| 807 | context->personality = tsk->personality; | ||
| 705 | 808 | ||
| 706 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); | 809 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); |
| 707 | if (!ab) | 810 | if (!ab) |
| @@ -714,6 +817,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 714 | audit_log_format(ab, " success=%s exit=%ld", | 817 | audit_log_format(ab, " success=%s exit=%ld", |
| 715 | (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", | 818 | (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", |
| 716 | context->return_code); | 819 | context->return_code); |
| 820 | |||
| 821 | mutex_lock(&tty_mutex); | ||
| 717 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) | 822 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) |
| 718 | tty = tsk->signal->tty->name; | 823 | tty = tsk->signal->tty->name; |
| 719 | else | 824 | else |
| @@ -735,7 +840,15 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 735 | context->gid, | 840 | context->gid, |
| 736 | context->euid, context->suid, context->fsuid, | 841 | context->euid, context->suid, context->fsuid, |
| 737 | context->egid, context->sgid, context->fsgid, tty); | 842 | context->egid, context->sgid, context->fsgid, tty); |
| 843 | |||
| 844 | mutex_unlock(&tty_mutex); | ||
| 845 | |||
| 738 | audit_log_task_info(ab, tsk); | 846 | audit_log_task_info(ab, tsk); |
| 847 | if (context->filterkey) { | ||
| 848 | audit_log_format(ab, " key="); | ||
| 849 | audit_log_untrustedstring(ab, context->filterkey); | ||
| 850 | } else | ||
| 851 | audit_log_format(ab, " key=(null)"); | ||
| 739 | audit_log_end(ab); | 852 | audit_log_end(ab); |
| 740 | 853 | ||
| 741 | for (aux = context->aux; aux; aux = aux->next) { | 854 | for (aux = context->aux; aux; aux = aux->next) { |
| @@ -790,7 +903,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 790 | if (axi->osid != 0) { | 903 | if (axi->osid != 0) { |
| 791 | char *ctx = NULL; | 904 | char *ctx = NULL; |
| 792 | u32 len; | 905 | u32 len; |
| 793 | if (selinux_ctxid_to_string( | 906 | if (selinux_sid_to_string( |
| 794 | axi->osid, &ctx, &len)) { | 907 | axi->osid, &ctx, &len)) { |
| 795 | audit_log_format(ab, " osid=%u", | 908 | audit_log_format(ab, " osid=%u", |
| 796 | axi->osid); | 909 | axi->osid); |
| @@ -897,7 +1010,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 897 | if (n->osid != 0) { | 1010 | if (n->osid != 0) { |
| 898 | char *ctx = NULL; | 1011 | char *ctx = NULL; |
| 899 | u32 len; | 1012 | u32 len; |
| 900 | if (selinux_ctxid_to_string( | 1013 | if (selinux_sid_to_string( |
| 901 | n->osid, &ctx, &len)) { | 1014 | n->osid, &ctx, &len)) { |
| 902 | audit_log_format(ab, " osid=%u", n->osid); | 1015 | audit_log_format(ab, " osid=%u", n->osid); |
| 903 | call_panic = 2; | 1016 | call_panic = 2; |
| @@ -1014,7 +1127,8 @@ void audit_syscall_entry(int arch, int major, | |||
| 1014 | context->argv[3] = a4; | 1127 | context->argv[3] = a4; |
| 1015 | 1128 | ||
| 1016 | state = context->state; | 1129 | state = context->state; |
| 1017 | if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT) | 1130 | context->dummy = !audit_n_rules; |
| 1131 | if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)) | ||
| 1018 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); | 1132 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); |
| 1019 | if (likely(state == AUDIT_DISABLED)) | 1133 | if (likely(state == AUDIT_DISABLED)) |
| 1020 | return; | 1134 | return; |
| @@ -1061,6 +1175,8 @@ void audit_syscall_exit(int valid, long return_code) | |||
| 1061 | } else { | 1175 | } else { |
| 1062 | audit_free_names(context); | 1176 | audit_free_names(context); |
| 1063 | audit_free_aux(context); | 1177 | audit_free_aux(context); |
| 1178 | kfree(context->filterkey); | ||
| 1179 | context->filterkey = NULL; | ||
| 1064 | tsk->audit_context = context; | 1180 | tsk->audit_context = context; |
| 1065 | } | 1181 | } |
| 1066 | } | 1182 | } |
| @@ -1145,14 +1261,18 @@ void audit_putname(const char *name) | |||
| 1145 | #endif | 1261 | #endif |
| 1146 | } | 1262 | } |
| 1147 | 1263 | ||
| 1148 | static void audit_inode_context(int idx, const struct inode *inode) | 1264 | /* Copy inode data into an audit_names. */ |
| 1265 | static void audit_copy_inode(struct audit_names *name, const struct inode *inode) | ||
| 1149 | { | 1266 | { |
| 1150 | struct audit_context *context = current->audit_context; | 1267 | name->ino = inode->i_ino; |
| 1151 | 1268 | name->dev = inode->i_sb->s_dev; | |
| 1152 | selinux_get_inode_sid(inode, &context->names[idx].osid); | 1269 | name->mode = inode->i_mode; |
| 1270 | name->uid = inode->i_uid; | ||
| 1271 | name->gid = inode->i_gid; | ||
| 1272 | name->rdev = inode->i_rdev; | ||
| 1273 | selinux_get_inode_sid(inode, &name->osid); | ||
| 1153 | } | 1274 | } |
| 1154 | 1275 | ||
| 1155 | |||
| 1156 | /** | 1276 | /** |
| 1157 | * audit_inode - store the inode and device from a lookup | 1277 | * audit_inode - store the inode and device from a lookup |
| 1158 | * @name: name being audited | 1278 | * @name: name being audited |
| @@ -1186,20 +1306,14 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
| 1186 | ++context->ino_count; | 1306 | ++context->ino_count; |
| 1187 | #endif | 1307 | #endif |
| 1188 | } | 1308 | } |
| 1189 | context->names[idx].ino = inode->i_ino; | 1309 | audit_copy_inode(&context->names[idx], inode); |
| 1190 | context->names[idx].dev = inode->i_sb->s_dev; | ||
| 1191 | context->names[idx].mode = inode->i_mode; | ||
| 1192 | context->names[idx].uid = inode->i_uid; | ||
| 1193 | context->names[idx].gid = inode->i_gid; | ||
| 1194 | context->names[idx].rdev = inode->i_rdev; | ||
| 1195 | audit_inode_context(idx, inode); | ||
| 1196 | } | 1310 | } |
| 1197 | 1311 | ||
| 1198 | /** | 1312 | /** |
| 1199 | * audit_inode_child - collect inode info for created/removed objects | 1313 | * audit_inode_child - collect inode info for created/removed objects |
| 1200 | * @dname: inode's dentry name | 1314 | * @dname: inode's dentry name |
| 1201 | * @inode: inode being audited | 1315 | * @inode: inode being audited |
| 1202 | * @pino: inode number of dentry parent | 1316 | * @parent: inode of dentry parent |
| 1203 | * | 1317 | * |
| 1204 | * For syscalls that create or remove filesystem objects, audit_inode | 1318 | * For syscalls that create or remove filesystem objects, audit_inode |
| 1205 | * can only collect information for the filesystem object's parent. | 1319 | * can only collect information for the filesystem object's parent. |
| @@ -1210,7 +1324,7 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
| 1210 | * unsuccessful attempts. | 1324 | * unsuccessful attempts. |
| 1211 | */ | 1325 | */ |
| 1212 | void __audit_inode_child(const char *dname, const struct inode *inode, | 1326 | void __audit_inode_child(const char *dname, const struct inode *inode, |
| 1213 | unsigned long pino) | 1327 | const struct inode *parent) |
| 1214 | { | 1328 | { |
| 1215 | int idx; | 1329 | int idx; |
| 1216 | struct audit_context *context = current->audit_context; | 1330 | struct audit_context *context = current->audit_context; |
| @@ -1224,7 +1338,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, | |||
| 1224 | if (!dname) | 1338 | if (!dname) |
| 1225 | goto update_context; | 1339 | goto update_context; |
| 1226 | for (idx = 0; idx < context->name_count; idx++) | 1340 | for (idx = 0; idx < context->name_count; idx++) |
| 1227 | if (context->names[idx].ino == pino) { | 1341 | if (context->names[idx].ino == parent->i_ino) { |
| 1228 | const char *name = context->names[idx].name; | 1342 | const char *name = context->names[idx].name; |
| 1229 | 1343 | ||
| 1230 | if (!name) | 1344 | if (!name) |
| @@ -1248,16 +1362,47 @@ update_context: | |||
| 1248 | context->names[idx].name_len = AUDIT_NAME_FULL; | 1362 | context->names[idx].name_len = AUDIT_NAME_FULL; |
| 1249 | context->names[idx].name_put = 0; /* don't call __putname() */ | 1363 | context->names[idx].name_put = 0; /* don't call __putname() */ |
| 1250 | 1364 | ||
| 1251 | if (inode) { | 1365 | if (!inode) |
| 1252 | context->names[idx].ino = inode->i_ino; | 1366 | context->names[idx].ino = (unsigned long)-1; |
| 1253 | context->names[idx].dev = inode->i_sb->s_dev; | 1367 | else |
| 1254 | context->names[idx].mode = inode->i_mode; | 1368 | audit_copy_inode(&context->names[idx], inode); |
| 1255 | context->names[idx].uid = inode->i_uid; | 1369 | |
| 1256 | context->names[idx].gid = inode->i_gid; | 1370 | /* A parent was not found in audit_names, so copy the inode data for the |
| 1257 | context->names[idx].rdev = inode->i_rdev; | 1371 | * provided parent. */ |
| 1258 | audit_inode_context(idx, inode); | 1372 | if (!found_name) { |
| 1259 | } else | 1373 | idx = context->name_count++; |
| 1260 | context->names[idx].ino = (unsigned long)-1; | 1374 | #if AUDIT_DEBUG |
| 1375 | context->ino_count++; | ||
| 1376 | #endif | ||
| 1377 | audit_copy_inode(&context->names[idx], parent); | ||
| 1378 | } | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | /** | ||
| 1382 | * audit_inode_update - update inode info for last collected name | ||
| 1383 | * @inode: inode being audited | ||
| 1384 | * | ||
| 1385 | * When open() is called on an existing object with the O_CREAT flag, the inode | ||
| 1386 | * data audit initially collects is incorrect. This additional hook ensures | ||
| 1387 | * audit has the inode data for the actual object to be opened. | ||
| 1388 | */ | ||
| 1389 | void __audit_inode_update(const struct inode *inode) | ||
| 1390 | { | ||
| 1391 | struct audit_context *context = current->audit_context; | ||
| 1392 | int idx; | ||
| 1393 | |||
| 1394 | if (!context->in_syscall || !inode) | ||
| 1395 | return; | ||
| 1396 | |||
| 1397 | if (context->name_count == 0) { | ||
| 1398 | context->name_count++; | ||
| 1399 | #if AUDIT_DEBUG | ||
| 1400 | context->ino_count++; | ||
| 1401 | #endif | ||
| 1402 | } | ||
| 1403 | idx = context->name_count - 1; | ||
| 1404 | |||
| 1405 | audit_copy_inode(&context->names[idx], inode); | ||
| 1261 | } | 1406 | } |
| 1262 | 1407 | ||
| 1263 | /** | 1408 | /** |
| @@ -1367,7 +1512,7 @@ int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr) | |||
| 1367 | * @mqdes: MQ descriptor | 1512 | * @mqdes: MQ descriptor |
| 1368 | * @msg_len: Message length | 1513 | * @msg_len: Message length |
| 1369 | * @msg_prio: Message priority | 1514 | * @msg_prio: Message priority |
| 1370 | * @abs_timeout: Message timeout in absolute time | 1515 | * @u_abs_timeout: Message timeout in absolute time |
| 1371 | * | 1516 | * |
| 1372 | * Returns 0 for success or NULL context or < 0 on error. | 1517 | * Returns 0 for success or NULL context or < 0 on error. |
| 1373 | */ | 1518 | */ |
| @@ -1409,8 +1554,8 @@ int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, | |||
| 1409 | * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive | 1554 | * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive |
| 1410 | * @mqdes: MQ descriptor | 1555 | * @mqdes: MQ descriptor |
| 1411 | * @msg_len: Message length | 1556 | * @msg_len: Message length |
| 1412 | * @msg_prio: Message priority | 1557 | * @u_msg_prio: Message priority |
| 1413 | * @abs_timeout: Message timeout in absolute time | 1558 | * @u_abs_timeout: Message timeout in absolute time |
| 1414 | * | 1559 | * |
| 1415 | * Returns 0 for success or NULL context or < 0 on error. | 1560 | * Returns 0 for success or NULL context or < 0 on error. |
| 1416 | */ | 1561 | */ |
| @@ -1558,7 +1703,6 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp) | |||
| 1558 | * @uid: msgq user id | 1703 | * @uid: msgq user id |
| 1559 | * @gid: msgq group id | 1704 | * @gid: msgq group id |
| 1560 | * @mode: msgq mode (permissions) | 1705 | * @mode: msgq mode (permissions) |
| 1561 | * @ipcp: in-kernel IPC permissions | ||
| 1562 | * | 1706 | * |
| 1563 | * Returns 0 for success or NULL context or < 0 on error. | 1707 | * Returns 0 for success or NULL context or < 0 on error. |
| 1564 | */ | 1708 | */ |
| @@ -1589,7 +1733,7 @@ int audit_bprm(struct linux_binprm *bprm) | |||
| 1589 | unsigned long p, next; | 1733 | unsigned long p, next; |
| 1590 | void *to; | 1734 | void *to; |
| 1591 | 1735 | ||
| 1592 | if (likely(!audit_enabled || !context)) | 1736 | if (likely(!audit_enabled || !context || context->dummy)) |
| 1593 | return 0; | 1737 | return 0; |
| 1594 | 1738 | ||
| 1595 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, | 1739 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, |
| @@ -1627,7 +1771,7 @@ int audit_socketcall(int nargs, unsigned long *args) | |||
| 1627 | struct audit_aux_data_socketcall *ax; | 1771 | struct audit_aux_data_socketcall *ax; |
| 1628 | struct audit_context *context = current->audit_context; | 1772 | struct audit_context *context = current->audit_context; |
| 1629 | 1773 | ||
| 1630 | if (likely(!context)) | 1774 | if (likely(!context || context->dummy)) |
| 1631 | return 0; | 1775 | return 0; |
| 1632 | 1776 | ||
| 1633 | ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); | 1777 | ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); |
| @@ -1655,7 +1799,7 @@ int audit_sockaddr(int len, void *a) | |||
| 1655 | struct audit_aux_data_sockaddr *ax; | 1799 | struct audit_aux_data_sockaddr *ax; |
| 1656 | struct audit_context *context = current->audit_context; | 1800 | struct audit_context *context = current->audit_context; |
| 1657 | 1801 | ||
| 1658 | if (likely(!context)) | 1802 | if (likely(!context || context->dummy)) |
| 1659 | return 0; | 1803 | return 0; |
| 1660 | 1804 | ||
| 1661 | ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); | 1805 | ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); |
