On Mon, Dec 02, 2024 at 06:30:41PM +0100, Alexander Bluhm wrote:
> On Mon, Dec 02, 2024 at 05:22:23PM +0100, Alexander Bluhm wrote:
> > panic: Data modified on freelist: word 11 of object 0xd7632800 size 0x270 
> > previous type mount (0xdead410f != 0xdead4110)
> 
> It looks like the struct mount mnt_lock rwl_readers was derecemented
> after free.  rwl_readers = 3735896335 = 0xdead410f
> 
> This happens in vfs_busy() with RW_READ.  New rw_do_enter_read()
> function added call to rw_dec(&rwl->rwl_readers) there.
> 
> I have the impression that the reimplementation of rw-lock makes
> the problem visible.  Accessing struct mount after sleep is
> questionalble.  Does anything prevent a file system unount while
> sleeping in vfs_busy()?

New implementation of rw-locks is wrong.

vfs_lookup() checks the existance of dp->v_mountedhere
each time before vfs_busy() is called.

        while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
            (cnp->cn_flags & NOCROSSMOUNT) == 0) {
                if (vfs_busy(mp, VB_READ|VB_WAIT))
                        continue;

vfs_busy() calls rw_enter() with RW_READ and RW_SLEEPFAIL.

Old rw_enter() did 

                error = sleep_finish(0, do_sleep);
                ...
                if (flags & RW_SLEEPFAIL)
                        return (EAGAIN);

New rw_do_enter_read() does

                error = sleep_finish(RW_SLEEP_TMO,
                    atomic_load_int(&rwl->rwl_waiters) > 0 ||
                    ISSET(atomic_load_long(&rwl->rwl_owner), RWLOCK_WRLOCK));
                ...
                if (ISSET(flags, RW_SLEEPFAIL)) {
                        error = EAGAIN;
                        goto fail;
                }
        ...
fail:
        rw_dec(&rwl->rwl_readers);
        return (error);

After sleep_finish() and RW_SLEEPFAIL there is no guarantee that
rwl is still valid memory.  This is a use-after-free in rw_do_enter_read().

bluhm

Reply via email to