]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/proc/base.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[karo-tx-linux.git] / fs / proc / base.c
index e42bbd843ed13793e93a9af193e8b14136013d31..a7310841c83149e406c1089d30a8c27b2c1e67fb 100644 (file)
@@ -647,17 +647,11 @@ static int mounts_release(struct inode *inode, struct file *file)
 static unsigned mounts_poll(struct file *file, poll_table *wait)
 {
        struct proc_mounts *p = file->private_data;
-       struct mnt_namespace *ns = p->ns;
        unsigned res = POLLIN | POLLRDNORM;
 
-       poll_wait(file, &ns->poll, wait);
-
-       spin_lock(&vfsmount_lock);
-       if (p->event != ns->event) {
-               p->event = ns->event;
+       poll_wait(file, &p->ns->poll, wait);
+       if (mnt_had_events(p))
                res |= POLLERR | POLLPRI;
-       }
-       spin_unlock(&vfsmount_lock);
 
        return res;
 }
@@ -1095,8 +1089,12 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
        if (!capable(CAP_AUDIT_CONTROL))
                return -EPERM;
 
-       if (current != pid_task(proc_pid(inode), PIDTYPE_PID))
+       rcu_read_lock();
+       if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
+               rcu_read_unlock();
                return -EPERM;
+       }
+       rcu_read_unlock();
 
        if (count >= PAGE_SIZE)
                count = PAGE_SIZE - 1;
@@ -2369,16 +2367,30 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct pid_namespace *ns = dentry->d_sb->s_fs_info;
        pid_t tgid = task_tgid_nr_ns(current, ns);
-       char tmp[PROC_NUMBUF];
-       if (!tgid)
-               return ERR_PTR(-ENOENT);
-       sprintf(tmp, "%d", task_tgid_nr_ns(current, ns));
-       return ERR_PTR(vfs_follow_link(nd,tmp));
+       char *name = ERR_PTR(-ENOENT);
+       if (tgid) {
+               name = __getname();
+               if (!name)
+                       name = ERR_PTR(-ENOMEM);
+               else
+                       sprintf(name, "%d", tgid);
+       }
+       nd_set_link(nd, name);
+       return NULL;
+}
+
+static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
+                               void *cookie)
+{
+       char *s = nd_get_link(nd);
+       if (!IS_ERR(s))
+               __putname(s);
 }
 
 static const struct inode_operations proc_self_inode_operations = {
        .readlink       = proc_self_readlink,
        .follow_link    = proc_self_follow_link,
+       .put_link       = proc_self_put_link,
 };
 
 /*