#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/tracehook.h>
+#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/security.h>
return -ENOMEM;
tsec->task = task;
- tsec->osid = tsec->sid = SECINITSID_UNLABELED;
+ tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
task->security = tsec;
return 0;
static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
{
+ struct task_security_struct *psec = parent->security;
+ struct task_security_struct *csec = child->security;
int rc;
rc = secondary_ops->ptrace(parent,child);
if (rc)
return rc;
- return task_has_perm(parent, child, PROCESS__PTRACE);
+ rc = task_has_perm(parent, child, PROCESS__PTRACE);
+ /* Save the SID of the tracing process for later use in apply_creds. */
+ if (!(child->ptrace & PT_PTRACED) && !rc)
+ csec->ptrace_sid = psec->sid;
+ return rc;
}
static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
{
struct avc_audit_data ad;
struct file *file, *devnull = NULL;
- struct tty_struct *tty = current->signal->tty;
+ struct tty_struct *tty;
struct fdtable *fdt;
long j = -1;
+ int drop_tty = 0;
+ mutex_lock(&tty_mutex);
+ tty = get_current_tty();
if (tty) {
file_list_lock();
file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
struct inode *inode = file->f_dentry->d_inode;
if (inode_has_perm(current, inode,
FILE__READ | FILE__WRITE, NULL)) {
- /* Reset controlling tty. */
- current->signal->tty = NULL;
- current->signal->tty_old_pgrp = 0;
+ drop_tty = 1;
}
}
file_list_unlock();
+
+ /* Reset controlling tty. */
+ if (drop_tty)
+ proc_set_tty(current, NULL);
}
+ mutex_unlock(&tty_mutex);
/* Revalidate access to inherited open files. */
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and kill. */
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
- struct task_struct *t;
-
- rcu_read_lock();
- t = tracehook_tracer_task(current);
- if (unlikely(t == NULL))
- rcu_read_unlock();
- else {
- struct task_security_struct *sec = t->security;
- u32 ptsid = sec->sid;
- rcu_read_unlock();
-
- rc = avc_has_perm(ptsid, sid,
- SECCLASS_PROCESS,
- PROCESS__PTRACE, NULL);
- if (rc) {
- bsec->unsafe = 1;
- return;
- }
+ rc = avc_has_perm(tsec->ptrace_sid, sid,
+ SECCLASS_PROCESS, PROCESS__PTRACE,
+ NULL);
+ if (rc) {
+ bsec->unsafe = 1;
+ return;
}
}
tsec->sid = sid;
tsec2->keycreate_sid = tsec1->keycreate_sid;
tsec2->sockcreate_sid = tsec1->sockcreate_sid;
+ /* Retain ptracer SID across fork, if any.
+ This will be reset by the ptrace hook upon any
+ subsequent ptrace_attach operations. */
+ tsec2->ptrace_sid = tsec1->ptrace_sid;
+
return 0;
}
char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
- struct task_struct *tracer;
u32 sid = 0;
int error;
char *str = value;
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and fail. */
task_lock(p);
- rcu_read_lock();
- tracer = tracehook_tracer_task(p);
- if (tracer != NULL) {
- struct task_security_struct *ptsec = tracer->security;
- u32 ptsid = ptsec->sid;
- rcu_read_unlock();
- error = avc_has_perm_noaudit(ptsid, sid,
+ if (p->ptrace & PT_PTRACED) {
+ error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
SECCLASS_PROCESS,
PROCESS__PTRACE, &avd);
if (!error)
tsec->sid = sid;
task_unlock(p);
- avc_audit(ptsid, sid, SECCLASS_PROCESS,
+ avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
PROCESS__PTRACE, &avd, error, NULL);
if (error)
return error;
} else {
- rcu_read_unlock();
tsec->sid = sid;
task_unlock(p);
}