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
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
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
© 2016 - 2024 Red Hat, Inc.