CRED: Use RCU to access another task's creds and to release a task's own creds
[linux-3.10.git] / drivers / connector / cn_proc.c
index 354c1ff..c5afc98 100644 (file)
@@ -106,6 +106,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
        struct proc_event *ev;
        __u8 buffer[CN_PROC_MSG_SIZE];
        struct timespec ts;
+       const struct cred *cred;
 
        if (atomic_read(&proc_event_num_listeners) < 1)
                return;
@@ -115,14 +116,19 @@ void proc_id_connector(struct task_struct *task, int which_id)
        ev->what = which_id;
        ev->event_data.id.process_pid = task->pid;
        ev->event_data.id.process_tgid = task->tgid;
+       rcu_read_lock();
+       cred = __task_cred(task);
        if (which_id == PROC_EVENT_UID) {
-               ev->event_data.id.r.ruid = task->cred->uid;
-               ev->event_data.id.e.euid = task->cred->euid;
+               ev->event_data.id.r.ruid = cred->uid;
+               ev->event_data.id.e.euid = cred->euid;
        } else if (which_id == PROC_EVENT_GID) {
-               ev->event_data.id.r.rgid = task->cred->gid;
-               ev->event_data.id.e.egid = task->cred->egid;
-       } else
+               ev->event_data.id.r.rgid = cred->gid;
+               ev->event_data.id.e.egid = cred->egid;
+       } else {
+               rcu_read_unlock();
                return;
+       }
+       rcu_read_unlock();
        get_seq(&msg->seq, &ev->cpu);
        ktime_get_ts(&ts); /* get high res monotonic timestamp */
        put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);