diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 14 | ||||
-rw-r--r-- | kernel/auditsc.c | 19 | ||||
-rw-r--r-- | kernel/signal.c | 7 |
3 files changed, 38 insertions, 2 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 9c4f1af0c79..6f344b44d3d 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -68,7 +68,7 @@ static int audit_failure = AUDIT_FAIL_PRINTK; /* If audit records are to be written to the netlink socket, audit_pid * contains the (non-zero) pid. */ -static int audit_pid; +int audit_pid; /* If audit_limit is non-zero, limit the rate of sending audit records * to that number per second. This prevents DoS attacks, but results in @@ -79,6 +79,10 @@ static int audit_rate_limit; static int audit_backlog_limit = 64; static atomic_t audit_backlog = ATOMIC_INIT(0); +/* The identity of the user shutting down the audit system. */ +uid_t audit_sig_uid = -1; +pid_t audit_sig_pid = -1; + /* Records can be lost in several ways: 0) [suppressed in audit_alloc] 1) out of memory in audit_log_start [kmalloc of struct audit_buffer] @@ -321,6 +325,7 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type) case AUDIT_SET: case AUDIT_ADD: case AUDIT_DEL: + case AUDIT_SIGNAL_INFO: if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL)) err = -EPERM; break; @@ -344,6 +349,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; uid_t loginuid; /* loginuid of sender */ + struct audit_sig_info sig_data; err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type); if (err) @@ -419,6 +425,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = -EOPNOTSUPP; #endif break; + case AUDIT_SIGNAL_INFO: + sig_data.uid = audit_sig_uid; + sig_data.pid = audit_sig_pid; + audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, + 0, 0, &sig_data, sizeof(sig_data)); + break; default: err = -EINVAL; break; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 37b3ac94bc4..f1bf66510cd 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1056,3 +1056,22 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) context->aux = (void *)ax; return 0; } + +void audit_signal_info(int sig, struct task_struct *t) +{ + extern pid_t audit_sig_pid; + extern uid_t audit_sig_uid; + extern int audit_pid; + + if (unlikely(audit_pid && t->pid == audit_pid)) { + if (sig == SIGTERM || sig == SIGHUP) { + struct audit_context *ctx = current->audit_context; + audit_sig_pid = current->pid; + if (ctx) + audit_sig_uid = ctx->loginuid; + else + audit_sig_uid = current->uid; + } + } +} + diff --git a/kernel/signal.c b/kernel/signal.c index 8f3debc77c5..293e189d8bc 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -24,6 +24,7 @@ #include <linux/ptrace.h> #include <linux/posix-timers.h> #include <linux/signal.h> +#include <linux/audit.h> #include <asm/param.h> #include <asm/uaccess.h> #include <asm/unistd.h> @@ -658,7 +659,11 @@ static int check_kill_permission(int sig, struct siginfo *info, && (current->uid ^ t->suid) && (current->uid ^ t->uid) && !capable(CAP_KILL)) return error; - return security_task_kill(t, info, sig); + + error = security_task_kill(t, info, sig); + if (!error) + audit_signal_info(sig, t); /* Let audit system see the signal */ + return error; } /* forward decl */ |