]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/proc/base.c
proc: make /proc/pid/limits world readable
[net-next-2.6.git] / fs / proc / base.c
index 69254a365ce2e1a0797cd37bdf623381fbb0119b..8e4addaa542458badbe0e62da644ec1c64194f99 100644 (file)
@@ -149,18 +149,13 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
        return count;
 }
 
-static int get_fs_path(struct task_struct *task, struct path *path, bool root)
+static int get_task_root(struct task_struct *task, struct path *root)
 {
-       struct fs_struct *fs;
        int result = -ENOENT;
 
        task_lock(task);
-       fs = task->fs;
-       if (fs) {
-               read_lock(&fs->lock);
-               *path = root ? fs->root : fs->pwd;
-               path_get(path);
-               read_unlock(&fs->lock);
+       if (task->fs) {
+               get_fs_root(task->fs, root);
                result = 0;
        }
        task_unlock(task);
@@ -173,7 +168,12 @@ static int proc_cwd_link(struct inode *inode, struct path *path)
        int result = -ENOENT;
 
        if (task) {
-               result = get_fs_path(task, path, 0);
+               task_lock(task);
+               if (task->fs) {
+                       get_fs_pwd(task->fs, path);
+                       result = 0;
+               }
+               task_unlock(task);
                put_task_struct(task);
        }
        return result;
@@ -185,7 +185,7 @@ static int proc_root_link(struct inode *inode, struct path *path)
        int result = -ENOENT;
 
        if (task) {
-               result = get_fs_path(task, path, 1);
+               result = get_task_root(task, path);
                put_task_struct(task);
        }
        return result;
@@ -559,9 +559,19 @@ static int proc_setattr(struct dentry *dentry, struct iattr *attr)
                return -EPERM;
 
        error = inode_change_ok(inode, attr);
-       if (!error)
-               error = inode_setattr(inode, attr);
-       return error;
+       if (error)
+               return error;
+
+       if ((attr->ia_valid & ATTR_SIZE) &&
+           attr->ia_size != i_size_read(inode)) {
+               error = vmtruncate(inode, attr->ia_size);
+               if (error)
+                       return error;
+       }
+
+       setattr_copy(inode, attr);
+       mark_inode_dirty(inode);
+       return 0;
 }
 
 static const struct inode_operations proc_def_inode_operations = {
@@ -587,7 +597,7 @@ static int mounts_open_common(struct inode *inode, struct file *file,
                                get_mnt_ns(ns);
                }
                rcu_read_unlock();
-               if (ns && get_fs_path(task, &root, 1) == 0)
+               if (ns && get_task_root(task, &root) == 0)
                        ret = 0;
                put_task_struct(task);
        }
@@ -1516,7 +1526,7 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
        if (!tmp)
                return -ENOMEM;
 
-       pathname = d_path(path, tmp, PAGE_SIZE);
+       pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE);
        len = PTR_ERR(pathname);
        if (IS_ERR(pathname))
                goto out;
@@ -2665,7 +2675,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        INF("auxv",       S_IRUSR, proc_pid_auxv),
        ONE("status",     S_IRUGO, proc_pid_status),
        ONE("personality", S_IRUSR, proc_pid_personality),
-       INF("limits",     S_IRUSR, proc_pid_limits),
+       INF("limits",     S_IRUGO, proc_pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
@@ -3001,7 +3011,7 @@ static const struct pid_entry tid_base_stuff[] = {
        INF("auxv",      S_IRUSR, proc_pid_auxv),
        ONE("status",    S_IRUGO, proc_pid_status),
        ONE("personality", S_IRUSR, proc_pid_personality),
-       INF("limits",    S_IRUSR, proc_pid_limits),
+       INF("limits",    S_IRUGO, proc_pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",     S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif