Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / fs / proc / base.c
index 0d3a4d1..51be1ce 100644 (file)
@@ -216,7 +216,7 @@ static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
 
 struct mm_struct *mm_for_maps(struct task_struct *task)
 {
-       return mm_access(task, PTRACE_MODE_READ);
+       return mm_access(task, PTRACE_MODE_READ_FSCREDS);
 }
 
 static int proc_pid_cmdline(struct task_struct *task, char * buffer)
@@ -288,7 +288,7 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
        wchan = get_wchan(task);
 
        if (lookup_symbol_name(wchan, symname) < 0)
-               if (!ptrace_may_access(task, PTRACE_MODE_READ))
+               if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
                        return 0;
                else
                        return sprintf(buffer, "%lu", wchan);
@@ -302,7 +302,7 @@ static int lock_trace(struct task_struct *task)
        int err = mutex_lock_killable(&task->signal->cred_guard_mutex);
        if (err)
                return err;
-       if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
+       if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) {
                mutex_unlock(&task->signal->cred_guard_mutex);
                return -EPERM;
        }
@@ -544,7 +544,7 @@ static int proc_fd_access_allowed(struct inode *inode)
         */
        task = get_proc_task(inode);
        if (task) {
-               allowed = ptrace_may_access(task, PTRACE_MODE_READ);
+               allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
                put_task_struct(task);
        }
        return allowed;
@@ -558,7 +558,7 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
        if (attr->ia_valid & ATTR_MODE)
                return -EPERM;
 
-       error = inode_change_ok(inode, attr);
+       error = setattr_prepare(dentry, attr);
        if (error)
                return error;
 
@@ -769,12 +769,19 @@ static int mem_open(struct inode* inode, struct file* file)
        if (!task)
                return -ESRCH;
 
-       mm = mm_access(task, PTRACE_MODE_ATTACH);
+       mm = mm_access(task, PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS);
        put_task_struct(task);
 
        if (IS_ERR(mm))
                return PTR_ERR(mm);
 
+       if (mm) {
+               /* ensure this mm_struct can't be freed */
+               atomic_inc(&mm->mm_count);
+               /* but do not pin its memory */
+               mmput(mm);
+       }
+
        /* OK to pass negative loff_t, we can catch out-of-range */
        file->f_mode |= FMODE_UNSIGNED_OFFSET;
        file->private_data = mm;
@@ -798,6 +805,9 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
                return -ENOMEM;
 
        copied = 0;
+       if (!atomic_inc_not_zero(&mm->mm_users))
+               goto free;
+
        while (count > 0) {
                int this_len = min_t(int, count, PAGE_SIZE);
 
@@ -825,6 +835,8 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
        }
        *ppos = addr;
 
+       mmput(mm);
+free:
        free_page((unsigned long) page);
        return copied;
 }
@@ -861,7 +873,7 @@ static int mem_release(struct inode *inode, struct file *file)
 {
        struct mm_struct *mm = file->private_data;
        if (mm)
-               mmput(mm);
+               mmdrop(mm);
        return 0;
 }
 
@@ -893,7 +905,8 @@ static ssize_t environ_read(struct file *file, char __user *buf,
 
        mm = mm_for_maps(task);
        ret = PTR_ERR(mm);
-       if (!mm || IS_ERR(mm))
+       /* Ensure the process spawned far enough to have an environment. */
+       if (!mm || IS_ERR(mm) || !mm->env_end)
                goto out_free;
 
        ret = 0;
@@ -1818,7 +1831,7 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
 
                        fdt = files_fdtable(files);
                        f_flags = file->f_flags & ~O_CLOEXEC;
-                       if (FD_ISSET(fd, fdt->close_on_exec))
+                       if (close_on_exec(fd, fdt))
                                f_flags |= O_CLOEXEC;
 
                        if (path) {
@@ -2614,7 +2627,7 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
        if (result)
                return result;
 
-       if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
+       if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
                result = -EACCES;
                goto out_unlock;
        }
@@ -2703,6 +2716,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        ONE("stat",       S_IRUGO, proc_tgid_stat),
        ONE("statm",      S_IRUGO, proc_pid_statm),
        REG("maps",       S_IRUGO, proc_maps_operations),
+       REG("arm_maps",   S_IRUGO, proc_armv7_maps_operations),
 #ifdef CONFIG_NUMA
        REG("numa_maps",  S_IRUGO, proc_numa_maps_operations),
 #endif
@@ -3049,6 +3063,7 @@ static const struct pid_entry tid_base_stuff[] = {
        ONE("stat",      S_IRUGO, proc_tid_stat),
        ONE("statm",     S_IRUGO, proc_pid_statm),
        REG("maps",      S_IRUGO, proc_maps_operations),
+       REG("arm_maps",  S_IRUGO, proc_armv7_maps_operations),
 #ifdef CONFIG_NUMA
        REG("numa_maps", S_IRUGO, proc_numa_maps_operations),
 #endif