diff mbox series

[4/8] cifs: Fix creating NFS-style char/block devices

Message ID 20240928215948.4494-5-pali@kernel.org
State New
Headers show
Series cifs: Fix support for NFS-style reparse points | expand

Commit Message

Pali Rohár Sept. 28, 2024, 9:59 p.m. UTC
Linux SMB client currently creates NFS-style char and block devices with
swapped major and minor numbers.

Per MS-FSCC 2.1.2.6 NFS_SPECFILE_CHR and NFS_SPECFILE_BLK DataBuffer's
field contains two 32-bit integers that represent major and minor device
numbers.

So the first one 32-bit integer in DataBuffer is major number and second
one in DataBuffer is minor number. Microsoft Windows NFS server reads them
in this order too.

But Linux CIFS client creates new reparse point DataBuffer with minor
number first and major number second.

Fix this problem in Linux SMB client and puts major and minor number in
the correct order into DataBuffer.

This change fixes interoperability of char and block devices on Windows
share which is exported over both SMB and NFS protocols.

Fixes: 102466f303ff ("smb: client: allow creating special files via reparse points")
Signed-off-by: Pali Rohár <pali@kernel.org>
---
 fs/smb/client/reparse.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Steve French Sept. 29, 2024, 12:18 a.m. UTC | #1
Looks like a duplicate of Paulo's earlier already merged patch, so
will skip this one.  Reviewing the others in the series now.

commit a9de67336a4aa3ff2e706ba023fb5f7ff681a954
Author: Paulo Alcantara <pc@manguebit.com>
Date:   Wed Sep 18 21:53:35 2024 -0300

    smb: client: set correct device number on nfs reparse points

    Fix major and minor numbers set on special files created with NFS
    reparse points.

On Sat, Sep 28, 2024 at 5:02 PM Pali Rohár <pali@kernel.org> wrote:
>
> Linux SMB client currently creates NFS-style char and block devices with
> swapped major and minor numbers.
>
> Per MS-FSCC 2.1.2.6 NFS_SPECFILE_CHR and NFS_SPECFILE_BLK DataBuffer's
> field contains two 32-bit integers that represent major and minor device
> numbers.
>
> So the first one 32-bit integer in DataBuffer is major number and second
> one in DataBuffer is minor number. Microsoft Windows NFS server reads them
> in this order too.
>
> But Linux CIFS client creates new reparse point DataBuffer with minor
> number first and major number second.
>
> Fix this problem in Linux SMB client and puts major and minor number in
> the correct order into DataBuffer.
>
> This change fixes interoperability of char and block devices on Windows
> share which is exported over both SMB and NFS protocols.
>
> Fixes: 102466f303ff ("smb: client: allow creating special files via reparse points")
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  fs/smb/client/reparse.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> index 48c27581ec51..63984796721a 100644
> --- a/fs/smb/client/reparse.c
> +++ b/fs/smb/client/reparse.c
> @@ -108,8 +108,8 @@ static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
>         buf->InodeType = cpu_to_le64(type);
>         buf->ReparseDataLength = cpu_to_le16(len + dlen -
>                                              sizeof(struct reparse_data_buffer));
> -       *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MAJOR(dev) << 32) |
> -                                                MINOR(dev));
> +       *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MINOR(dev) << 32) |
> +                                                MAJOR(dev));
>         iov->iov_base = buf;
>         iov->iov_len = len + dlen;
>         return 0;
> --
> 2.20.1
>
>
Pali Rohár Sept. 29, 2024, 12:44 a.m. UTC | #2
Ops, sorry for that. I just let my work branch on v6.11-rc7 and here
this change was not yet. But it is funny that we have hit this problem
independently in nearly same time.

On Saturday 28 September 2024 19:18:26 Steve French wrote:
> Looks like a duplicate of Paulo's earlier already merged patch, so
> will skip this one.  Reviewing the others in the series now.
> 
> commit a9de67336a4aa3ff2e706ba023fb5f7ff681a954
> Author: Paulo Alcantara <pc@manguebit.com>
> Date:   Wed Sep 18 21:53:35 2024 -0300
> 
>     smb: client: set correct device number on nfs reparse points
> 
>     Fix major and minor numbers set on special files created with NFS
>     reparse points.
> 
> On Sat, Sep 28, 2024 at 5:02 PM Pali Rohár <pali@kernel.org> wrote:
> >
> > Linux SMB client currently creates NFS-style char and block devices with
> > swapped major and minor numbers.
> >
> > Per MS-FSCC 2.1.2.6 NFS_SPECFILE_CHR and NFS_SPECFILE_BLK DataBuffer's
> > field contains two 32-bit integers that represent major and minor device
> > numbers.
> >
> > So the first one 32-bit integer in DataBuffer is major number and second
> > one in DataBuffer is minor number. Microsoft Windows NFS server reads them
> > in this order too.
> >
> > But Linux CIFS client creates new reparse point DataBuffer with minor
> > number first and major number second.
> >
> > Fix this problem in Linux SMB client and puts major and minor number in
> > the correct order into DataBuffer.
> >
> > This change fixes interoperability of char and block devices on Windows
> > share which is exported over both SMB and NFS protocols.
> >
> > Fixes: 102466f303ff ("smb: client: allow creating special files via reparse points")
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  fs/smb/client/reparse.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> > index 48c27581ec51..63984796721a 100644
> > --- a/fs/smb/client/reparse.c
> > +++ b/fs/smb/client/reparse.c
> > @@ -108,8 +108,8 @@ static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
> >         buf->InodeType = cpu_to_le64(type);
> >         buf->ReparseDataLength = cpu_to_le16(len + dlen -
> >                                              sizeof(struct reparse_data_buffer));
> > -       *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MAJOR(dev) << 32) |
> > -                                                MINOR(dev));
> > +       *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MINOR(dev) << 32) |
> > +                                                MAJOR(dev));
> >         iov->iov_base = buf;
> >         iov->iov_len = len + dlen;
> >         return 0;
> > --
> > 2.20.1
> >
> >
> 
> 
> -- 
> Thanks,
> 
> Steve
Pali Rohár Sept. 29, 2024, 12:51 a.m. UTC | #3
I guess that patch 3 can be dropped too as Paulo fixed it recently in:
https://git.samba.org/sfrench/?p=sfrench/cifs-2.6.git;a=commit;h=663f295e35594f4c2584fc68c28546b747b637cd

On Saturday 28 September 2024 19:47:52 Steve French wrote:
> Patch 3 may need to be rebased, iirc patch 3 didn't merge but 1 and 2 did
> 
> On Sat, Sep 28, 2024, 7:44 PM Pali Rohár <pali@kernel.org> wrote:
> 
> > Ops, sorry for that. I just let my work branch on v6.11-rc7 and here
> > this change was not yet. But it is funny that we have hit this problem
> > independently in nearly same time.
> >
> > On Saturday 28 September 2024 19:18:26 Steve French wrote:
> > > Looks like a duplicate of Paulo's earlier already merged patch, so
> > > will skip this one.  Reviewing the others in the series now.
> > >
> > > commit a9de67336a4aa3ff2e706ba023fb5f7ff681a954
> > > Author: Paulo Alcantara <pc@manguebit.com>
> > > Date:   Wed Sep 18 21:53:35 2024 -0300
> > >
> > >     smb: client: set correct device number on nfs reparse points
> > >
> > >     Fix major and minor numbers set on special files created with NFS
> > >     reparse points.
> > >
> > > On Sat, Sep 28, 2024 at 5:02 PM Pali Rohár <pali@kernel.org> wrote:
> > > >
> > > > Linux SMB client currently creates NFS-style char and block devices
> > with
> > > > swapped major and minor numbers.
> > > >
> > > > Per MS-FSCC 2.1.2.6 NFS_SPECFILE_CHR and NFS_SPECFILE_BLK DataBuffer's
> > > > field contains two 32-bit integers that represent major and minor
> > device
> > > > numbers.
> > > >
> > > > So the first one 32-bit integer in DataBuffer is major number and
> > second
> > > > one in DataBuffer is minor number. Microsoft Windows NFS server reads
> > them
> > > > in this order too.
> > > >
> > > > But Linux CIFS client creates new reparse point DataBuffer with minor
> > > > number first and major number second.
> > > >
> > > > Fix this problem in Linux SMB client and puts major and minor number in
> > > > the correct order into DataBuffer.
> > > >
> > > > This change fixes interoperability of char and block devices on Windows
> > > > share which is exported over both SMB and NFS protocols.
> > > >
> > > > Fixes: 102466f303ff ("smb: client: allow creating special files via
> > reparse points")
> > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > ---
> > > >  fs/smb/client/reparse.c | 4 ++--
> > > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> > > > index 48c27581ec51..63984796721a 100644
> > > > --- a/fs/smb/client/reparse.c
> > > > +++ b/fs/smb/client/reparse.c
> > > > @@ -108,8 +108,8 @@ static int nfs_set_reparse_buf(struct
> > reparse_posix_data *buf,
> > > >         buf->InodeType = cpu_to_le64(type);
> > > >         buf->ReparseDataLength = cpu_to_le16(len + dlen -
> > > >                                              sizeof(struct
> > reparse_data_buffer));
> > > > -       *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MAJOR(dev) <<
> > 32) |
> > > > -                                                MINOR(dev));
> > > > +       *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MINOR(dev) <<
> > 32) |
> > > > +                                                MAJOR(dev));
> > > >         iov->iov_base = buf;
> > > >         iov->iov_len = len + dlen;
> > > >         return 0;
> > > > --
> > > > 2.20.1
> > > >
> > > >
> > >
> > >
> > > --
> > > Thanks,
> > >
> > > Steve
> >
diff mbox series

Patch

diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 48c27581ec51..63984796721a 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -108,8 +108,8 @@  static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
 	buf->InodeType = cpu_to_le64(type);
 	buf->ReparseDataLength = cpu_to_le16(len + dlen -
 					     sizeof(struct reparse_data_buffer));
-	*(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MAJOR(dev) << 32) |
-						 MINOR(dev));
+	*(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MINOR(dev) << 32) |
+						 MAJOR(dev));
 	iov->iov_base = buf;
 	iov->iov_len = len + dlen;
 	return 0;