Well, introduce utrace_set_caps() and utrace_get_caps(). See the next patch
which converts ptrace to use these helpers.

Note that these helpers are xxx_caps(int caps), not xxx_cred(struct cred*).
This is ugly, but capable() can't use cred* and always assumes current.

---

 include/linux/utrace.h |    3 +++
 kernel/utrace.c        |   28 ++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

--- RHEL6/include/linux/utrace.h~4_SET_CREDS    2010-07-07 00:48:09.000000000 
+0200
+++ RHEL6/include/linux/utrace.h        2010-07-07 02:37:10.000000000 +0200
@@ -624,6 +624,9 @@ int __must_check utrace_finish_examine(s
                                       struct utrace_engine *,
                                       struct utrace_examiner *);
 
+int utrace_set_caps(struct task_struct *, struct utrace_engine *, int);
+int utrace_get_caps(struct utrace_engine *);
+
 /**
  * utrace_control_pid - control a thread being traced by a tracing engine
  * @pid:               thread to affect
--- RHEL6/kernel/utrace.c~4_SET_CREDS   2010-07-07 00:48:09.000000000 +0200
+++ RHEL6/kernel/utrace.c       2010-07-07 02:41:31.000000000 +0200
@@ -2457,10 +2457,38 @@ void task_utrace_proc_status(struct seq_
        seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags);
 }
 
+/*
+ * The caller must ensure we can't race with exec.
+ */
+int utrace_set_caps(struct task_struct *target, struct utrace_engine *engine,
+                       int caps)
+{
+       struct utrace *utrace = get_utrace_lock(target, engine, true);
+
+       if (unlikely(IS_ERR(utrace)))
+               return PTR_ERR(utrace);
+
+       engine->flags &= ~ENGINE_LSM_MASK;
+       engine->flags |= caps ? ENGINE_LSM_TRACE_CAP : ENGINE_LSM_TRACE;
+       spin_unlock(&utrace->lock);
+
+       return 0;
+}
+
+int utrace_get_caps(struct utrace_engine *engine)
+{
+       return engine->flags & ENGINE_LSM_TRACE_CAP;
+}
+
 int utrace_unsafe_exec(struct task_struct *task)
 {
+       struct utrace *utrace = task_utrace_struct(task);
        int unsafe = 0;
 
+       /* Recalc ->utrace_flags. We can optimize this later */
+       spin_lock(&utrace->lock);
+       utrace_reset(task, utrace);
+
        if (task->utrace_flags & ENGINE_LSM_TRACE)
                unsafe = LSM_UNSAFE_PTRACE;
        else if (task->utrace_flags & ENGINE_LSM_TRACE_CAP)

Reply via email to