📄 auditsc.c
字号:
rcu_read_lock(); if (!list_empty(list)) { int word = AUDIT_WORD(ctx->major); int bit = AUDIT_BIT(ctx->major); list_for_each_entry_rcu(e, list, list) { if ((e->rule.mask[word] & bit) == bit && audit_filter_rules(tsk, &e->rule, ctx, NULL, &state)) { rcu_read_unlock(); return state; } } } rcu_read_unlock(); return AUDIT_BUILD_CONTEXT;}/* At syscall exit time, this filter is called if any audit_names[] have been * collected during syscall processing. We only check rules in sublists at hash * buckets applicable to the inode numbers in audit_names[]. * Regarding audit_state, same rules apply as for audit_filter_syscall(). */enum audit_state audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx){ int i; struct audit_entry *e; enum audit_state state; if (audit_pid && tsk->tgid == audit_pid) return AUDIT_DISABLED; rcu_read_lock(); for (i = 0; i < ctx->name_count; i++) { int word = AUDIT_WORD(ctx->major); int bit = AUDIT_BIT(ctx->major); struct audit_names *n = &ctx->names[i]; int h = audit_hash_ino((u32)n->ino); struct list_head *list = &audit_inode_hash[h]; if (list_empty(list)) continue; list_for_each_entry_rcu(e, list, list) { if ((e->rule.mask[word] & bit) == bit && audit_filter_rules(tsk, &e->rule, ctx, n, &state)) { rcu_read_unlock(); return state; } } } rcu_read_unlock(); return AUDIT_BUILD_CONTEXT;}void audit_set_auditable(struct audit_context *ctx){ ctx->auditable = 1;}static inline struct audit_context *audit_get_context(struct task_struct *tsk, int return_valid, int return_code){ struct audit_context *context = tsk->audit_context; if (likely(!context)) return NULL; context->return_valid = return_valid; context->return_code = return_code; if (context->in_syscall && !context->dummy && !context->auditable) { enum audit_state state; state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); if (state == AUDIT_RECORD_CONTEXT) { context->auditable = 1; goto get_context; } state = audit_filter_inodes(tsk, context); if (state == AUDIT_RECORD_CONTEXT) context->auditable = 1; }get_context: tsk->audit_context = NULL; return context;}static inline void audit_free_names(struct audit_context *context){ int i;#if AUDIT_DEBUG == 2 if (context->auditable ||context->put_count + context->ino_count != context->name_count) { printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" " name_count=%d put_count=%d" " ino_count=%d [NOT freeing]\n", __FILE__, __LINE__, context->serial, context->major, context->in_syscall, context->name_count, context->put_count, context->ino_count); for (i = 0; i < context->name_count; i++) { printk(KERN_ERR "names[%d] = %p = %s\n", i, context->names[i].name, context->names[i].name ?: "(null)"); } dump_stack(); return; }#endif#if AUDIT_DEBUG context->put_count = 0; context->ino_count = 0;#endif for (i = 0; i < context->name_count; i++) { if (context->names[i].name && context->names[i].name_put) __putname(context->names[i].name); } context->name_count = 0; if (context->pwd) dput(context->pwd); if (context->pwdmnt) mntput(context->pwdmnt); context->pwd = NULL; context->pwdmnt = NULL;}static inline void audit_free_aux(struct audit_context *context){ struct audit_aux_data *aux; while ((aux = context->aux)) { if (aux->type == AUDIT_AVC_PATH) { struct audit_aux_data_path *axi = (void *)aux; dput(axi->dentry); mntput(axi->mnt); } context->aux = aux->next; kfree(aux); } while ((aux = context->aux_pids)) { context->aux_pids = aux->next; kfree(aux); }}static inline void audit_zero_context(struct audit_context *context, enum audit_state state){ uid_t loginuid = context->loginuid; memset(context, 0, sizeof(*context)); context->state = state; context->loginuid = loginuid;}static inline struct audit_context *audit_alloc_context(enum audit_state state){ struct audit_context *context; if (!(context = kmalloc(sizeof(*context), GFP_KERNEL))) return NULL; audit_zero_context(context, state); return context;}/** * audit_alloc - allocate an audit context block for a task * @tsk: task * * Filter on the task information and allocate a per-task audit context * if necessary. Doing so turns on system call auditing for the * specified task. This is called from copy_process, so no lock is * needed. */int audit_alloc(struct task_struct *tsk){ struct audit_context *context; enum audit_state state; if (likely(!audit_enabled)) return 0; /* Return if not auditing. */ state = audit_filter_task(tsk); if (likely(state == AUDIT_DISABLED)) return 0; if (!(context = audit_alloc_context(state))) { audit_log_lost("out of memory in audit_alloc"); return -ENOMEM; } /* Preserve login uid */ context->loginuid = -1; if (current->audit_context) context->loginuid = current->audit_context->loginuid; tsk->audit_context = context; set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); return 0;}static inline void audit_free_context(struct audit_context *context){ struct audit_context *previous; int count = 0; do { previous = context->previous; if (previous || (count && count < 10)) { ++count; printk(KERN_ERR "audit(:%d): major=%d name_count=%d:" " freeing multiple contexts (%d)\n", context->serial, context->major, context->name_count, count); } audit_free_names(context); audit_free_aux(context); kfree(context->filterkey); kfree(context); context = previous; } while (context); if (count >= 10) printk(KERN_ERR "audit: freed %d contexts\n", count);}void audit_log_task_context(struct audit_buffer *ab){ char *ctx = NULL; unsigned len; int error; u32 sid; selinux_get_task_sid(current, &sid); if (!sid) return; error = selinux_sid_to_string(sid, &ctx, &len); if (error) { if (error != -EINVAL) goto error_path; return; } audit_log_format(ab, " subj=%s", ctx); kfree(ctx); return;error_path: audit_panic("error in audit_log_task_context"); return;}EXPORT_SYMBOL(audit_log_task_context);static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk){ char name[sizeof(tsk->comm)]; struct mm_struct *mm = tsk->mm; struct vm_area_struct *vma; /* tsk == current */ get_task_comm(name, tsk); audit_log_format(ab, " comm="); audit_log_untrustedstring(ab, name); if (mm) { down_read(&mm->mmap_sem); vma = mm->mmap; while (vma) { if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { audit_log_d_path(ab, "exe=", vma->vm_file->f_path.dentry, vma->vm_file->f_path.mnt); break; } vma = vma->vm_next; } up_read(&mm->mmap_sem); } audit_log_task_context(ab);}static int audit_log_pid_context(struct audit_context *context, pid_t pid, u32 sid){ struct audit_buffer *ab; char *s = NULL; u32 len; int rc = 0; ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); if (!ab) return 1; if (selinux_sid_to_string(sid, &s, &len)) { audit_log_format(ab, "opid=%d obj=(none)", pid); rc = 1; } else audit_log_format(ab, "opid=%d obj=%s", pid, s); audit_log_end(ab); kfree(s); return rc;}static void audit_log_exit(struct audit_context *context, struct task_struct *tsk){ int i, call_panic = 0; struct audit_buffer *ab; struct audit_aux_data *aux; const char *tty; /* tsk == current */ context->pid = tsk->pid; if (!context->ppid) context->ppid = sys_getppid(); context->uid = tsk->uid; context->gid = tsk->gid; context->euid = tsk->euid; context->suid = tsk->suid; context->fsuid = tsk->fsuid; context->egid = tsk->egid; context->sgid = tsk->sgid; context->fsgid = tsk->fsgid; context->personality = tsk->personality; ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); if (!ab) return; /* audit_panic has been called */ audit_log_format(ab, "arch=%x syscall=%d", context->arch, context->major); if (context->personality != PER_LINUX) audit_log_format(ab, " per=%lx", context->personality); if (context->return_valid) audit_log_format(ab, " success=%s exit=%ld", (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", context->return_code); mutex_lock(&tty_mutex); read_lock(&tasklist_lock); if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) tty = tsk->signal->tty->name; else tty = "(none)"; read_unlock(&tasklist_lock); audit_log_format(ab, " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" " ppid=%d pid=%d auid=%u uid=%u gid=%u" " euid=%u suid=%u fsuid=%u" " egid=%u sgid=%u fsgid=%u tty=%s", context->argv[0], context->argv[1], context->argv[2], context->argv[3], context->name_count, context->ppid, context->pid, context->loginuid, context->uid, context->gid, context->euid, context->suid, context->fsuid, context->egid, context->sgid, context->fsgid, tty); mutex_unlock(&tty_mutex); audit_log_task_info(ab, tsk); if (context->filterkey) { audit_log_format(ab, " key="); audit_log_untrustedstring(ab, context->filterkey); } else audit_log_format(ab, " key=(null)"); audit_log_end(ab); for (aux = context->aux; aux; aux = aux->next) { ab = audit_log_start(context, GFP_KERNEL, aux->type); if (!ab) continue; /* audit_panic has been called */ switch (aux->type) { case AUDIT_MQ_OPEN: { struct audit_aux_data_mq_open *axi = (void *)aux; audit_log_format(ab, "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld " "mq_msgsize=%ld mq_curmsgs=%ld", axi->oflag, axi->mode, axi->attr.mq_flags, axi->attr.mq_maxmsg, axi->attr.mq_msgsize, axi->attr.mq_curmsgs); break; } case AUDIT_MQ_SENDRECV: { struct audit_aux_data_mq_sendrecv *axi = (void *)aux; audit_log_format(ab, "mqdes=%d msg_len=%zd msg_prio=%u " "abs_timeout_sec=%ld abs_timeout_nsec=%ld", axi->mqdes, axi->msg_len, axi->msg_prio, axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec); break; } case AUDIT_MQ_NOTIFY: { struct audit_aux_data_mq_notify *axi = (void *)aux; audit_log_format(ab, "mqdes=%d sigev_signo=%d", axi->mqdes, axi->notification.sigev_signo); break; } case AUDIT_MQ_GETSETATTR: { struct audit_aux_data_mq_getsetattr *axi = (void *)aux; audit_log_format(ab, "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld " "mq_curmsgs=%ld ", axi->mqdes, axi->mqstat.mq_flags, axi->mqstat.mq_maxmsg, axi->mqstat.mq_msgsize, axi->mqstat.mq_curmsgs); break; } case AUDIT_IPC: { struct audit_aux_data_ipcctl *axi = (void *)aux; audit_log_format(ab, "ouid=%u ogid=%u mode=%x", axi->uid, axi->gid, axi->mode); if (axi->osid != 0) { char *ctx = NULL; u32 len; if (selinux_sid_to_string( axi->osid, &ctx, &len)) { audit_log_format(ab, " osid=%u", axi->osid); call_panic = 1; } else audit_log_format(ab, " obj=%s", ctx); kfree(ctx); } break; } case AUDIT_IPC_SET_PERM: { struct audit_aux_data_ipcctl *axi = (void *)aux; audit_log_format(ab, "qbytes=%lx ouid=%u ogid=%u mode=%x", axi->qbytes, axi->uid, axi->gid, axi->mode); break; } case AUDIT_EXECVE: { struct audit_aux_data_execve *axi = (void *)aux; int i; const char *p; for (i = 0, p = axi->mem; i < axi->argc; i++) { audit_log_format(ab, "a%d=", i); p = audit_log_untrustedstring(ab, p); audit_log_format(ab, "\n"); } break; } case AUDIT_SOCKETCALL: { int i; struct audit_aux_data_socketcall *axs = (void *)aux; audit_log_format(ab, "nargs=%d", axs->nargs); for (i=0; i<axs->nargs; i++) audit_log_format(ab, " a%d=%lx", i, axs->args[i]); break; } case AUDIT_SOCKADDR: { struct audit_aux_data_sockaddr *axs = (void *)aux; audit_log_format(ab, "saddr="); audit_log_hex(ab, axs->a, axs->len); break; } case AUDIT_AVC_PATH: { struct audit_aux_data_path *axi = (void *)aux; audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); break; } case AUDIT_FD_PAIR: { struct audit_aux_data_fd_pair *axs = (void *)aux; audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]); break; } } audit_log_end(ab); } for (aux = context->aux_pids; aux; aux = aux->next) { struct audit_aux_data_pids *axs = (void *)aux; int i; for (i = 0; i < axs->pid_count; i++) if (audit_log_pid_context(context, axs->target_pid[i], axs->target_sid[i])) call_panic = 1; } if (context->target_pid && audit_log_pid_context(context, context->target_pid, context->target_sid)) call_panic = 1; if (context->pwd && context->pwdmnt) { ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); if (ab) { audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt); audit_log_end(ab); } } for (i = 0; i < context->name_count; i++) { struct audit_names *n = &context->names[i]; ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -