cifs: Fix querying of WSL CHR and BLK reparse points over SMB1

When reparse point in SMB1 query_path_info() callback was detected then
query also for EA $LXDEV. In this EA are stored device major and minor
numbers used by WSL CHR and BLK reparse points. Without major and minor
numbers, stat() syscall does not work for char and block devices.

Similar code is already in SMB2+ query_path_info() callback function.

Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by Pali Rohár and committed by Steve French ef86ab13 56c0bea5

+36
+36
fs/smb/client/smb1ops.c
··· 568 data->reparse_point = le32_to_cpu(fi.Attributes) & ATTR_REPARSE; 569 } 570 571 return rc; 572 } 573
··· 568 data->reparse_point = le32_to_cpu(fi.Attributes) & ATTR_REPARSE; 569 } 570 571 + #ifdef CONFIG_CIFS_XATTR 572 + /* 573 + * For WSL CHR and BLK reparse points it is required to fetch 574 + * EA $LXDEV which contains major and minor device numbers. 575 + */ 576 + if (!rc && data->reparse_point) { 577 + struct smb2_file_full_ea_info *ea; 578 + 579 + ea = (struct smb2_file_full_ea_info *)data->wsl.eas; 580 + rc = CIFSSMBQAllEAs(xid, tcon, full_path, SMB2_WSL_XATTR_DEV, 581 + &ea->ea_data[SMB2_WSL_XATTR_NAME_LEN + 1], 582 + SMB2_WSL_XATTR_DEV_SIZE, cifs_sb); 583 + if (rc == SMB2_WSL_XATTR_DEV_SIZE) { 584 + ea->next_entry_offset = cpu_to_le32(0); 585 + ea->flags = 0; 586 + ea->ea_name_length = SMB2_WSL_XATTR_NAME_LEN; 587 + ea->ea_value_length = cpu_to_le16(SMB2_WSL_XATTR_DEV_SIZE); 588 + memcpy(&ea->ea_data[0], SMB2_WSL_XATTR_DEV, SMB2_WSL_XATTR_NAME_LEN + 1); 589 + data->wsl.eas_len = sizeof(*ea) + SMB2_WSL_XATTR_NAME_LEN + 1 + 590 + SMB2_WSL_XATTR_DEV_SIZE; 591 + rc = 0; 592 + } else if (rc >= 0) { 593 + /* It is an error if EA $LXDEV has wrong size. */ 594 + rc = -EINVAL; 595 + } else { 596 + /* 597 + * In all other cases ignore error if fetching 598 + * of EA $LXDEV failed. It is needed only for 599 + * WSL CHR and BLK reparse points and wsl_to_fattr() 600 + * handle the case when EA is missing. 601 + */ 602 + rc = 0; 603 + } 604 + } 605 + #endif 606 + 607 return rc; 608 } 609