lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200616023856.GD2005@dread.disaster.area>
Date:   Tue, 16 Jun 2020 12:38:56 +1000
From:   Dave Chinner <david@...morbit.com>
To:     "yukuai (C)" <yukuai3@...wei.com>
Cc:     darrick.wong@...cle.com, linux-xfs@...r.kernel.org,
        linux-kernel@...r.kernel.org, yi.zhang@...wei.com
Subject: Re: [PATCH] xfs: fix use-after-free on CIL context on shutdown

On Tue, Jun 16, 2020 at 09:16:09AM +0800, yukuai (C) wrote:
> On 2020/6/11 10:45, Dave Chinner wrote:
> > 
> > From: Dave Chinner <dchinner@...hat.com>
> > 
> > xlog_wait() on the CIL context can reference a freed context if the
> > waiter doesn't get scheduled before the CIL context is freed. This
> > can happen when a task is on the hard throttle and the CIL push
> > aborts due to a shutdown. This was detected by generic/019:
> > 
> > thread 1			thread 2
> > 
> > __xfs_trans_commit
> >   xfs_log_commit_cil
> >    <CIL size over hard throttle limit>
> >    xlog_wait
> >     schedule
> > 				xlog_cil_push_work
> > 				wake_up_all
> > 				<shutdown aborts commit>
> > 				xlog_cil_committed
> > 				kmem_free
> > 
> >     remove_wait_queue
> >      spin_lock_irqsave --> UAF
> > 
> > Fix it by moving the wait queue to the CIL rather than keeping it in
> > in the CIL context that gets freed on push completion. Because the
> > wait queue is now independent of the CIL context and we might have
> > multiple contexts in flight at once, only wake the waiters on the
> > push throttle when the context we are pushing is over the hard
> > throttle size threshold.
> 
> Hi, Dave,
> 
> How do you think about the following fix:
> 
> 1. use autoremove_wake_func(), and remove remove_wait_queue() to
> avoid UAF.
> 2. add finish_wait().
> 
> @@ -576,12 +576,13 @@ xlog_wait(
>                 __releases(lock)
>  {
>         DECLARE_WAITQUEUE(wait, current);
> +       wait.func = autoremove_wake_function;
> 
>         add_wait_queue_exclusive(wq, &wait);
>         __set_current_state(TASK_UNINTERRUPTIBLE);
>         spin_unlock(lock);
>         schedule();
> -       remove_wait_queue(wq, &wait);
> +       finish_wait(wq, &wait);
>  }

Yes, that would address this specific symptom of the problem, but it
doesn't fix the problem root cause: that the wq can be freed while
this function sleeps. IMO, this sort of change leaves a trap for
future modifications - all the code calling xlog_wait() assumes the
embedded wq the task is sleeping on still exists after waiting so we
really should be fixing the problem the incorrect existence
guarantee in the CIL code that you tripped over.

Cheers,

Dave.
-- 
Dave Chinner
david@...morbit.com

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ