Re: [PATCH 3.9 and earlier] hpfs: deadlock and race in directory lseek()

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

 



On Tue, Feb 11, 2014 at 12:06:58AM +0100, Mikulas Patocka wrote:
> Hi
> 
> This is backport of patch 31abdab9c11bb1694ecd1476a7edbe8e964d94ac for 
> stable kernels 3.9 and earlier.
> 
> Mikulas
> 
> 
> commit 31abdab9c11bb1694ecd1476a7edbe8e964d94ac
> Author: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
> Date:   Sat May 18 02:38:52 2013 -0400
> 
>     hpfs: deadlock and race in directory lseek()
> 
>     For one thing, there's an ABBA deadlock on hpfs fs-wide lock and i_mutex
>     in hpfs_dir_lseek() - there's a lot of methods that grab the former with
>     the caller already holding the latter, so it must take i_mutex first.
> 
>     For another, locking the damn thing, carefully validating the offset,
>     then dropping locks and assigning the offset is obviously racy.
> 
>     Moreover, we _must_ do hpfs_add_pos(), or the machinery in dnode.c
>     won't modify the sucker on B-tree surgeries.
> 
>     Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
> 
> 
> ---
>  fs/hpfs/dir.c  |   10 ++++++----
>  fs/hpfs/file.c |   36 ++++++++++++++++++++----------------
>  2 files changed, 26 insertions(+), 20 deletions(-)

That diffstat does not match up with the patch below.

What went wrong?

I've just picked the original patch to backport to 3.4, if that is
incorrect, please let me know.

thanks,

greg k-h

> 
> Index: linux-stable/fs/hpfs/dir.c
> ===================================================================
> --- linux-stable.orig/fs/hpfs/dir.c	2014-02-10 23:11:51.000000000 +0100
> +++ linux-stable/fs/hpfs/dir.c	2014-02-10 23:14:53.000000000 +0100
> @@ -33,25 +33,27 @@ static loff_t hpfs_dir_lseek(struct file
>  	if (whence == SEEK_DATA || whence == SEEK_HOLE)
>  		return -EINVAL;
>  
> +	mutex_lock(&i->i_mutex);
>  	hpfs_lock(s);
>  
>  	/*printk("dir lseek\n");*/
>  	if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
> -	mutex_lock(&i->i_mutex);
>  	pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;
>  	while (pos != new_off) {
>  		if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh);
>  		else goto fail;
>  		if (pos == 12) goto fail;
>  	}
> -	mutex_unlock(&i->i_mutex);
> +	hpfs_add_pos(i, &filp->f_pos);
>  ok:
> +	filp->f_pos = new_off;
>  	hpfs_unlock(s);
> -	return filp->f_pos = new_off;
> -fail:
>  	mutex_unlock(&i->i_mutex);
> +	return new_off;
> +fail:
>  	/*printk("illegal lseek: %016llx\n", new_off);*/
>  	hpfs_unlock(s);
> +	mutex_unlock(&i->i_mutex);
>  	return -ESPIPE;
>  }
>  
> --
> To unsubscribe from this list: send the line "unsubscribe stable" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]