diff --git a/include/linux/audit.h b/include/linux/audit.h index 773e30df11ee..f93ce78cecbb 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -91,6 +91,7 @@ #define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */ #define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */ #define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */ +#define AUDIT_OBJ_PID 1318 /* ptrace target */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ @@ -352,6 +353,8 @@ extern void __audit_inode(const char *name, const struct inode *inode); extern void __audit_inode_child(const char *dname, const struct inode *inode, const struct inode *parent); extern void __audit_inode_update(const struct inode *inode); +extern void __audit_ptrace(struct task_struct *t); + static inline int audit_dummy_context(void) { void *p = current->audit_context; @@ -377,6 +380,12 @@ static inline void audit_inode_update(const struct inode *inode) { __audit_inode_update(inode); } +static inline void audit_ptrace(struct task_struct *t) +{ + if (unlikely(!audit_dummy_context())) + __audit_ptrace(t); +} + /* Private API (for audit.c only) */ extern unsigned int audit_serial(void); extern void auditsc_get_stamp(struct audit_context *ctx, @@ -477,6 +486,7 @@ extern int audit_n_rules; #define audit_mq_timedreceive(d,l,p,t) ({ 0; }) #define audit_mq_notify(d,n) ({ 0; }) #define audit_mq_getsetattr(d,s) ({ 0; }) +#define audit_ptrace(t) ((void)0) #define audit_n_rules 0 #endif diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 628c7ac590a0..2243c559bc03 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -209,6 +209,9 @@ struct audit_context { unsigned long personality; int arch; + pid_t target_pid; + u32 target_sid; + #if AUDIT_DEBUG int put_count; int ino_count; @@ -973,6 +976,23 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts audit_log_end(ab); } + if (context->target_pid) { + ab =audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); + if (ab) { + char *s = NULL, *t; + u32 len; + if (selinux_sid_to_string(context->target_sid, + &s, &len)) + t = "(none)"; + else + t = s; + audit_log_format(ab, "opid=%d obj=%s", + context->target_pid, t); + audit_log_end(ab); + kfree(s); + } + } + if (context->pwd && context->pwdmnt) { ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); if (ab) { @@ -1193,6 +1213,7 @@ void audit_syscall_exit(int valid, long return_code) } else { audit_free_names(context); audit_free_aux(context); + context->target_pid = 0; kfree(context->filterkey); context->filterkey = NULL; tsk->audit_context = context; @@ -1880,6 +1901,14 @@ int audit_sockaddr(int len, void *a) return 0; } +void __audit_ptrace(struct task_struct *t) +{ + struct audit_context *context = current->audit_context; + + context->target_pid = t->pid; + selinux_get_task_sid(t, &context->target_sid); +} + /** * audit_avc_path - record the granting or denial of permissions * @dentry: dentry to record diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 4d50e06fd745..ad7949a589dd 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task) { int retval; + audit_ptrace(task); + retval = -EPERM; if (task->pid <= 1) goto out;