On Sun, 11 Feb 2007 23:23:30 +0300 Alexey Dobriyan <[EMAIL PROTECTED]> wrote:

> [PATCH v4] Fix rmmod/read/write races in /proc entries

This:

static ssize_t
proc_file_write(struct file *file, const char __user *buffer,
                size_t count, loff_t *ppos)
{
        struct inode *inode = file->f_path.dentry->d_inode;
        struct proc_dir_entry * dp;
        ssize_t rv = -EIO;
        
        dp = PDE(inode);

        if (!dp->write_proc)
                goto out;

        spin_lock(&dp->pde_unload_lock);
        if (!dp->proc_fops)
                /*
                 * remove_proc_entry() marked PDE as "going away".
                 * No new writers allowed.
                 */
                goto out_unlock;

versus

                spin_lock(&de->pde_unload_lock);
                /*
                 * Stop accepting new readers/writers. If you're dynamically
                 * allocating ->proc_fops, save a pointer somewhere.
                 */
                de->proc_fops = NULL;
                /* Wait until all existing readers/writers are done. */
                if (de->pde_users > 0) {
                        struct completion c;

                        init_completion(&c);
                        if (!de->pde_unload_completion)
                                de->pde_unload_completion = &c;

                        spin_unlock(&de->pde_unload_lock);
                        spin_unlock(&proc_subdir_lock);

                        wait_for_completion(de->pde_unload_completion);

                        spin_lock(&proc_subdir_lock);
                        goto continue_removing;
                }
                spin_unlock(&de->pde_unload_lock);
  <here>
        ...
        <free de>

What prevents proc_file_write() from looking up and playing with this de in
<here>?


Also... lockdep wants this:

--- a/fs/proc/generic.c~fix-rmmod-read-write-races-in-proc-entries-fix
+++ a/fs/proc/generic.c
@@ -790,9 +790,8 @@ void remove_proc_entry(const char *name,
                de->proc_fops = NULL;
                /* Wait until all existing readers/writers are done. */
                if (de->pde_users > 0) {
-                       struct completion c;
+                       DECLARE_COMPLETION_ONSTACK(c);
 
-                       init_completion(&c);
                        if (!de->pde_unload_completion)
                                de->pde_unload_completion = &c;
 
_

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to