Re: Re: WARNING in kill_block_super

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Al Viro wrote:
> On Wed, Apr 04, 2018 at 07:53:07PM +0900, Tetsuo Handa wrote:
> > Al and Michal, are you OK with this patch?
> 
> First of all, it does *NOT* fix the problems with careless ->kill_sb().
> The fuse-blk case is the only real rationale so far.  Said that,
> 

Please notice below one as well. Fixing all careless ->kill_sb() will be too
difficult to backport. For now, avoid calling deactivate_locked_super() is
safer.


[upstream] WARNING: refcount bug in put_pid_ns
https://syzkaller.appspot.com/bug?id=17e202b4794da213570ba33ac2f70277ef1ce015

static __latent_entropy struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size, int __user *child_tidptr, struct pid *pid, int trace, unsigned long tls, int node)
{
(...snipped...)
  if (pid != &init_struct_pid) {
    pid = alloc_pid(p->nsproxy->pid_ns_for_children) {
      pid_ns_prepare_proc(ns) {
        mnt = kern_mount_data(&proc_fs_type, ns) {
          mnt = vfs_kern_mount(type, SB_KERNMOUNT, type->name, data) {
            root = mount_fs(type, flags, name, data) {
              root = type->mount(type, flags, name, data) {
                return mount_ns(fs_type, flags, data, ns, ns->user_ns, proc_fill_super) {
                  sb = sget_userns(fs_type, ns_test_super, ns_set_super, flags, user_ns, ns) {
                    err = register_shrinker(&s->s_shrink); // <= failed by fault injection.
                    if (err) {
                      deactivate_locked_super(s) {
                        fs->kill_sb(s) {
                          put_pid_ns(ns) {
                            kref_put(&ns->kref, free_pid_ns) // <= ns->kref is decremented here.
                          }
                        }
                      }
                      s = ERR_PTR(err);
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    if (IS_ERR(pid)) {
      retval = PTR_ERR(pid);
      goto bad_fork_cleanup_thread;
    }
  }
(...snipped...)
bad_fork_cleanup_thread:
  exit_thread(p);
bad_fork_cleanup_io:
  if (p->io_context) exit_io_context(p);
bad_fork_cleanup_namespaces:
  exit_task_namespaces(p) {
     switch_task_namespaces(p, NULL) {
       if (ns && atomic_dec_and_test(&ns->count)) { // <= ns->count becomes 0
         free_nsproxy(ns) {
           if (ns->pid_ns_for_children) {
             put_pid_ns(ns->pid_ns_for_children) {
               kref_put(&ns->kref, free_pid_ns) // <= ns->kref is decremented again and underflows.
             }
           }
         }
       }
     }
  }
(...snipped...)
}




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux