mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
Merge tag 'v7.1-rc-part1-ksmbd-srv-fixes' of git://git.samba.org/ksmbd
Pull smb server updates from Steve French:
- smbdirect double free fixes
- Add some smbdirect logging
- Minor cleanup in crypto, and smbdirect and in IPC handling
- Minor cleanup to move header info to common FSCC code
- Fix crypt message use after free
- Fix memory leak in session setup
- Fix for DACL parsing
- Fix EA name length validation
- Reconnect fix
- Fix use after free in close
* tag 'v7.1-rc-part1-ksmbd-srv-fixes' of git://git.samba.org/ksmbd:
smb: smbdirect: add some logging to SMBDIRECT_CHECK_STATUS_{WARN,DISCONNECT}()
smb: smbdirect: introduce smbdirect_socket.logging infrastructure
smb: smbdirect: let smbdirect.h include #include <linux/types.h>
smb: server: avoid double-free in smb_direct_free_sendmsg after smb_direct_flush_send_list()
smb: client: avoid double-free in smbd_free_send_io() after smbd_send_batch_flush()
ksmbd: fix use-after-free from async crypto on Qualcomm crypto engine
ksmbd: fix mechToken leak when SPNEGO decode fails after token alloc
ksmbd: require 3 sub-authorities before reading sub_auth[2]
ksmbd: validate EaNameLength in smb2_get_ea()
ksmbd: Remove unnecessary selection of CRYPTO_ECB
ksmbd: validate owner of durable handle on reconnect
ksmbd: fix use-after-free in __ksmbd_close_fd() via durable scavenger
ksmbd: ipc: use kzalloc_flex and __counted_by
smb: move filesystem_vol_info into common/fscc.h
smb: move file_basic_info into common/fscc.h
smb: move some definitions from common/smb2pdu.h into common/fscc.h
This commit is contained in:
@@ -2061,15 +2061,6 @@ typedef struct {
|
||||
__le32 EASize;
|
||||
} __packed FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
|
||||
|
||||
typedef struct {
|
||||
__le64 CreationTime;
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le32 Attributes;
|
||||
__u32 Pad;
|
||||
} __packed FILE_BASIC_INFO; /* size info, level 0x101 */
|
||||
|
||||
struct file_allocation_info {
|
||||
__le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
|
||||
} __packed; /* size used on disk, for level 0x103 for set, 0x105 for query */
|
||||
|
||||
@@ -6147,8 +6147,8 @@ replay_again:
|
||||
max_len = sizeof(struct smb3_fs_ss_info);
|
||||
min_len = sizeof(struct smb3_fs_ss_info);
|
||||
} else if (level == FS_VOLUME_INFORMATION) {
|
||||
max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN;
|
||||
min_len = sizeof(struct smb3_fs_vol_info);
|
||||
max_len = sizeof(struct filesystem_vol_info) + MAX_VOL_LABEL_LEN;
|
||||
min_len = sizeof(struct filesystem_vol_info);
|
||||
} else {
|
||||
cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level);
|
||||
return -EINVAL;
|
||||
@@ -6203,9 +6203,9 @@ replay_again:
|
||||
tcon->perf_sector_size =
|
||||
le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
|
||||
} else if (level == FS_VOLUME_INFORMATION) {
|
||||
struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *)
|
||||
struct filesystem_vol_info *vol_info = (struct filesystem_vol_info *)
|
||||
(offset + (char *)rsp);
|
||||
tcon->vol_serial_number = vol_info->VolumeSerialNumber;
|
||||
tcon->vol_serial_number = le32_to_cpu(vol_info->VolumeSerialNumber);
|
||||
tcon->vol_create_time = vol_info->VolumeCreationTime;
|
||||
}
|
||||
|
||||
|
||||
@@ -1551,17 +1551,25 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
|
||||
|
||||
rc = smbd_post_send(sc, batch, request);
|
||||
if (!rc) {
|
||||
/*
|
||||
* From here request is moved to batch
|
||||
* and we should not free it explicitly.
|
||||
*/
|
||||
|
||||
if (batch != &_batch)
|
||||
return 0;
|
||||
|
||||
rc = smbd_send_batch_flush(sc, batch, true);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
goto err_flush;
|
||||
}
|
||||
|
||||
err_dma:
|
||||
smbd_free_send_io(request);
|
||||
|
||||
err_flush:
|
||||
err_alloc:
|
||||
atomic_inc(&sc->send_io.credits.count);
|
||||
wake_up(&sc->send_io.credits.wait_queue);
|
||||
|
||||
@@ -12,6 +12,220 @@
|
||||
#ifndef _COMMON_SMB_FSCC_H
|
||||
#define _COMMON_SMB_FSCC_H
|
||||
|
||||
/* Reparse structures - see MS-FSCC 2.1.2 */
|
||||
|
||||
/* struct fsctl_reparse_info_req is empty, only response structs (see below) */
|
||||
struct reparse_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__u8 DataBuffer[]; /* Variable Length */
|
||||
} __packed;
|
||||
|
||||
struct reparse_guid_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__u8 ReparseGuid[16];
|
||||
__u8 DataBuffer[]; /* Variable Length */
|
||||
} __packed;
|
||||
|
||||
struct reparse_mount_point_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__le16 SubstituteNameOffset;
|
||||
__le16 SubstituteNameLength;
|
||||
__le16 PrintNameOffset;
|
||||
__le16 PrintNameLength;
|
||||
__u8 PathBuffer[]; /* Variable Length */
|
||||
} __packed;
|
||||
|
||||
#define SYMLINK_FLAG_RELATIVE 0x00000001
|
||||
|
||||
struct reparse_symlink_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__le16 SubstituteNameOffset;
|
||||
__le16 SubstituteNameLength;
|
||||
__le16 PrintNameOffset;
|
||||
__le16 PrintNameLength;
|
||||
__le32 Flags;
|
||||
__u8 PathBuffer[]; /* Variable Length */
|
||||
} __packed;
|
||||
|
||||
/* For IO_REPARSE_TAG_NFS - see MS-FSCC 2.1.2.6 */
|
||||
#define NFS_SPECFILE_LNK 0x00000000014B4E4C
|
||||
#define NFS_SPECFILE_CHR 0x0000000000524843
|
||||
#define NFS_SPECFILE_BLK 0x00000000004B4C42
|
||||
#define NFS_SPECFILE_FIFO 0x000000004F464946
|
||||
#define NFS_SPECFILE_SOCK 0x000000004B434F53
|
||||
struct reparse_nfs_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__le64 InodeType; /* NFS_SPECFILE_* */
|
||||
__u8 DataBuffer[];
|
||||
} __packed;
|
||||
|
||||
/* For IO_REPARSE_TAG_LX_SYMLINK - see MS-FSCC 2.1.2.7 */
|
||||
struct reparse_wsl_symlink_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__le32 Version; /* Always 2 */
|
||||
__u8 Target[]; /* Variable Length UTF-8 string without nul-term */
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.7 */
|
||||
struct duplicate_extents_to_file {
|
||||
__u64 PersistentFileHandle; /* source file handle, opaque endianness */
|
||||
__u64 VolatileFileHandle;
|
||||
__le64 SourceFileOffset;
|
||||
__le64 TargetFileOffset;
|
||||
__le64 ByteCount; /* Bytes to be copied */
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.9 */
|
||||
#define DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC 0x00000001
|
||||
struct duplicate_extents_to_file_ex {
|
||||
__le64 StructureSize; /* MUST be set to 0x30 */
|
||||
__u64 PersistentFileHandle; /* source file handle, opaque endianness */
|
||||
__u64 VolatileFileHandle;
|
||||
__le64 SourceFileOffset;
|
||||
__le64 TargetFileOffset;
|
||||
__le64 ByteCount; /* Bytes to be copied */
|
||||
__le32 Flags;
|
||||
__le32 Reserved;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.20 */
|
||||
struct fsctl_get_integrity_information_rsp {
|
||||
__le16 ChecksumAlgorithm;
|
||||
__le16 Reserved;
|
||||
__le32 Flags;
|
||||
__le32 ChecksumChunkSizeInBytes;
|
||||
__le32 ClusterSizeInBytes;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.52 */
|
||||
struct file_allocated_range_buffer {
|
||||
__le64 file_offset;
|
||||
__le64 length;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.55 */
|
||||
struct fsctl_query_file_regions_req {
|
||||
__le64 FileOffset;
|
||||
__le64 Length;
|
||||
__le32 DesiredUsage;
|
||||
__le32 Reserved;
|
||||
} __packed;
|
||||
|
||||
/* DesiredUsage flags see MS-FSCC 2.3.56.1 */
|
||||
#define FILE_USAGE_INVALID_RANGE 0x00000000
|
||||
#define FILE_USAGE_VALID_CACHED_DATA 0x00000001
|
||||
#define FILE_USAGE_NONCACHED_DATA 0x00000002
|
||||
struct file_region_info {
|
||||
__le64 FileOffset;
|
||||
__le64 Length;
|
||||
__le32 DesiredUsage;
|
||||
__le32 Reserved;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.56 */
|
||||
struct fsctl_query_file_region_rsp {
|
||||
__le32 Flags;
|
||||
__le32 TotalRegionEntryCount;
|
||||
__le32 RegionEntryCount;
|
||||
__u32 Reserved;
|
||||
struct file_region_info Regions[];
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.58 */
|
||||
struct fsctl_query_on_disk_vol_info_rsp {
|
||||
__le64 DirectoryCount;
|
||||
__le64 FileCount;
|
||||
__le16 FsFormatMajVersion;
|
||||
__le16 FsFormatMinVersion;
|
||||
__u8 FsFormatName[24];
|
||||
__le64 FormatTime;
|
||||
__le64 LastUpdateTime;
|
||||
__u8 CopyrightInfo[68];
|
||||
__u8 AbstractInfo[68];
|
||||
__u8 FormatImplInfo[68];
|
||||
__u8 LastModifyImplInfo[68];
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.73 */
|
||||
struct fsctl_set_integrity_information_req {
|
||||
__le16 ChecksumAlgorithm;
|
||||
__le16 Reserved;
|
||||
__le32 Flags;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.75 */
|
||||
struct fsctl_set_integrity_info_ex_req {
|
||||
__u8 EnableIntegrity;
|
||||
__u8 KeepState;
|
||||
__u16 Reserved;
|
||||
__le32 Flags;
|
||||
__u8 Version;
|
||||
__u8 Reserved2[7];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA
|
||||
* See MS-FSCC 2.3.85
|
||||
*/
|
||||
struct file_zero_data_information {
|
||||
__le64 FileOffset;
|
||||
__le64 BeyondFinalZero;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This level 18, although with struct with same name is different from cifs
|
||||
* level 0x107. Level 0x107 has an extra u64 between AccessFlags and
|
||||
* CurrentByteOffset.
|
||||
* See MS-FSCC 2.4.2
|
||||
*/
|
||||
struct smb2_file_all_info { /* data block encoding of response to level 18 */
|
||||
__le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le32 Attributes;
|
||||
__u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
|
||||
__le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
|
||||
__le64 EndOfFile; /* size ie offset to first free byte in file */
|
||||
__le32 NumberOfLinks; /* hard links */
|
||||
__u8 DeletePending;
|
||||
__u8 Directory;
|
||||
__u16 Pad2; /* End of FILE_STANDARD_INFO equivalent */
|
||||
__le64 IndexNumber;
|
||||
__le32 EASize;
|
||||
__le32 AccessFlags;
|
||||
__le64 CurrentByteOffset;
|
||||
__le32 Mode;
|
||||
__le32 AlignmentRequirement;
|
||||
__le32 FileNameLength;
|
||||
union {
|
||||
char __pad; /* Legacy structure padding */
|
||||
DECLARE_FLEX_ARRAY(char, FileName);
|
||||
};
|
||||
} __packed; /* level 18 Query */
|
||||
|
||||
/* See MS-FSCC 2.4.7 */
|
||||
typedef struct file_basic_info { /* data block encoding of response to level 18 */
|
||||
__le64 CreationTime;
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le32 Attributes;
|
||||
__u32 Pad;
|
||||
} __packed FILE_BASIC_INFO; /* size info, level 0x101 */
|
||||
|
||||
/* See MS-FSCC 2.4.8 */
|
||||
typedef struct {
|
||||
__le32 NextEntryOffset;
|
||||
@@ -46,6 +260,11 @@ typedef struct {
|
||||
char FileName[];
|
||||
} __packed FILE_DIRECTORY_INFO; /* level 0x101 FF resp data */
|
||||
|
||||
/* See MS-FSCC 2.4.13 */
|
||||
struct smb2_file_eof_info { /* encoding of request for level 10 */
|
||||
__le64 EndOfFile; /* new end of file value */
|
||||
} __packed; /* level 20 Set */
|
||||
|
||||
/* See MS-FSCC 2.4.14 */
|
||||
typedef struct {
|
||||
__le32 NextEntryOffset;
|
||||
@@ -80,6 +299,26 @@ typedef struct {
|
||||
char FileName[];
|
||||
} __packed FILE_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
|
||||
|
||||
/* See MS-FSCC 2.4.27 */
|
||||
struct smb2_file_internal_info {
|
||||
__le64 IndexNumber;
|
||||
} __packed; /* level 6 Query */
|
||||
|
||||
/* See MS-FSCC 2.4.28.2 */
|
||||
struct smb2_file_link_info { /* encoding of request for level 11 */
|
||||
/* New members MUST be added within the struct_group() macro below. */
|
||||
__struct_group(smb2_file_link_info_hdr, __hdr, __packed,
|
||||
__u8 ReplaceIfExists; /* 1 = replace existing link with new */
|
||||
/* 0 = fail if link already exists */
|
||||
__u8 Reserved[7];
|
||||
__u64 RootDirectory; /* MBZ for network operations (why says spec?) */
|
||||
__le32 FileNameLength;
|
||||
);
|
||||
char FileName[]; /* Name to be assigned to new link */
|
||||
} __packed; /* level 11 Set */
|
||||
static_assert(offsetof(struct smb2_file_link_info, FileName) == sizeof(struct smb2_file_link_info_hdr),
|
||||
"struct member likely outside of __struct_group()");
|
||||
|
||||
/* See MS-FSCC 2.4.34 */
|
||||
struct smb2_file_network_open_info {
|
||||
struct_group_attr(network_open_info, __packed,
|
||||
@@ -94,6 +333,37 @@ struct smb2_file_network_open_info {
|
||||
__le32 Reserved;
|
||||
} __packed; /* level 34 Query also similar returned in close rsp and open rsp */
|
||||
|
||||
/* See MS-FSCC 2.4.42.2 */
|
||||
struct smb2_file_rename_info { /* encoding of request for level 10 */
|
||||
/* New members MUST be added within the struct_group() macro below. */
|
||||
__struct_group(smb2_file_rename_info_hdr, __hdr, __packed,
|
||||
__u8 ReplaceIfExists; /* 1 = replace existing target with new */
|
||||
/* 0 = fail if target already exists */
|
||||
__u8 Reserved[7];
|
||||
__u64 RootDirectory; /* MBZ for network operations (why says spec?) */
|
||||
__le32 FileNameLength;
|
||||
);
|
||||
char FileName[]; /* New name to be assigned */
|
||||
/* padding - overall struct size must be >= 24 so filename + pad >= 6 */
|
||||
} __packed; /* level 10 Set */
|
||||
static_assert(offsetof(struct smb2_file_rename_info, FileName) == sizeof(struct smb2_file_rename_info_hdr),
|
||||
"struct member likely outside of __struct_group()");
|
||||
|
||||
/* File System Information Classes */
|
||||
/* See MS-FSCC 2.5 */
|
||||
#define FS_VOLUME_INFORMATION 1 /* Query */
|
||||
#define FS_LABEL_INFORMATION 2 /* Set */
|
||||
#define FS_SIZE_INFORMATION 3 /* Query */
|
||||
#define FS_DEVICE_INFORMATION 4 /* Query */
|
||||
#define FS_ATTRIBUTE_INFORMATION 5 /* Query */
|
||||
#define FS_CONTROL_INFORMATION 6 /* Query, Set */
|
||||
#define FS_FULL_SIZE_INFORMATION 7 /* Query */
|
||||
#define FS_OBJECT_ID_INFORMATION 8 /* Query, Set */
|
||||
#define FS_DRIVER_PATH_INFORMATION 9 /* Query */
|
||||
#define FS_SECTOR_SIZE_INFORMATION 11 /* SMB3 or later. Query */
|
||||
/* See POSIX Extensions to MS-FSCC 2.3.1.1 */
|
||||
#define FS_POSIX_INFORMATION 100 /* SMB3.1.1 POSIX. Query */
|
||||
|
||||
/* See MS-FSCC 2.5.1 */
|
||||
#define MAX_FS_NAME_LEN 52
|
||||
typedef struct {
|
||||
@@ -130,6 +400,45 @@ typedef struct {
|
||||
#define FILE_CASE_PRESERVED_NAMES 0x00000002
|
||||
#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
|
||||
|
||||
/*
|
||||
* File System Control Information
|
||||
* See MS-FSCC 2.5.2
|
||||
*/
|
||||
struct smb2_fs_control_info {
|
||||
__le64 FreeSpaceStartFiltering;
|
||||
__le64 FreeSpaceThreshold;
|
||||
__le64 FreeSpaceStopFiltering;
|
||||
__le64 DefaultQuotaThreshold;
|
||||
__le64 DefaultQuotaLimit;
|
||||
__le32 FileSystemControlFlags;
|
||||
__le32 Padding;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.5.4 */
|
||||
struct smb2_fs_full_size_info {
|
||||
__le64 TotalAllocationUnits;
|
||||
__le64 CallerAvailableAllocationUnits;
|
||||
__le64 ActualAvailableAllocationUnits;
|
||||
__le32 SectorsPerAllocationUnit;
|
||||
__le32 BytesPerSector;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.5.7 */
|
||||
#define SSINFO_FLAGS_ALIGNED_DEVICE 0x00000001
|
||||
#define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 0x00000002
|
||||
#define SSINFO_FLAGS_NO_SEEK_PENALTY 0x00000004
|
||||
#define SSINFO_FLAGS_TRIM_ENABLED 0x00000008
|
||||
/* sector size info struct */
|
||||
struct smb3_fs_ss_info {
|
||||
__le32 LogicalBytesPerSector;
|
||||
__le32 PhysicalBytesPerSectorForAtomicity;
|
||||
__le32 PhysicalBytesPerSectorForPerf;
|
||||
__le32 FSEffPhysicalBytesPerSectorForAtomicity;
|
||||
__le32 Flags;
|
||||
__le32 ByteOffsetForSectorAlignment;
|
||||
__le32 ByteOffsetForPartitionAlignment;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.5.8 */
|
||||
typedef struct {
|
||||
__le64 TotalAllocationUnits;
|
||||
@@ -138,6 +447,17 @@ typedef struct {
|
||||
__le32 BytesPerSector;
|
||||
} __packed FILE_SYSTEM_SIZE_INFO; /* size info, level 0x103 */
|
||||
|
||||
/* volume info struct - see MS-FSCC 2.5.9 */
|
||||
#define MAX_VOL_LABEL_LEN 32
|
||||
struct filesystem_vol_info {
|
||||
__le64 VolumeCreationTime;
|
||||
__le32 VolumeSerialNumber;
|
||||
__le32 VolumeLabelLength; /* includes trailing null */
|
||||
__u8 SupportsObjects; /* True if eg like NTFS, supports objects */
|
||||
__u8 Reserved;
|
||||
__u8 VolumeLabel[]; /* variable len */
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.5.10 */
|
||||
typedef struct {
|
||||
__le32 DeviceType;
|
||||
@@ -189,6 +509,22 @@ typedef struct {
|
||||
#define FILE_ATTRIBUTE_NO_SCRUB_DATA_LE cpu_to_le32(FILE_ATTRIBUTE_NO_SCRUB_DATA)
|
||||
#define FILE_ATTRIBUTE_MASK_LE cpu_to_le32(FILE_ATTRIBUTE_MASK)
|
||||
|
||||
/*
|
||||
* SMB2 Notify Action Flags
|
||||
* See MS-FSCC 2.7.1
|
||||
*/
|
||||
#define FILE_ACTION_ADDED 0x00000001
|
||||
#define FILE_ACTION_REMOVED 0x00000002
|
||||
#define FILE_ACTION_MODIFIED 0x00000003
|
||||
#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
|
||||
#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
|
||||
#define FILE_ACTION_ADDED_STREAM 0x00000006
|
||||
#define FILE_ACTION_REMOVED_STREAM 0x00000007
|
||||
#define FILE_ACTION_MODIFIED_STREAM 0x00000008
|
||||
#define FILE_ACTION_REMOVED_BY_DELETE 0x00000009
|
||||
#define FILE_ACTION_ID_NOT_TUNNELLED 0x0000000A
|
||||
#define FILE_ACTION_TUNNELLED_ID_COLLISION 0x0000000B
|
||||
|
||||
/*
|
||||
* Response contains array of the following structures
|
||||
* See MS-FSCC 2.7.1
|
||||
|
||||
@@ -1006,22 +1006,6 @@ struct smb2_set_info_rsp {
|
||||
#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
|
||||
#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
|
||||
|
||||
/*
|
||||
* SMB2 Notify Action Flags
|
||||
* See MS-FSCC 2.7.1
|
||||
*/
|
||||
#define FILE_ACTION_ADDED 0x00000001
|
||||
#define FILE_ACTION_REMOVED 0x00000002
|
||||
#define FILE_ACTION_MODIFIED 0x00000003
|
||||
#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
|
||||
#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
|
||||
#define FILE_ACTION_ADDED_STREAM 0x00000006
|
||||
#define FILE_ACTION_REMOVED_STREAM 0x00000007
|
||||
#define FILE_ACTION_MODIFIED_STREAM 0x00000008
|
||||
#define FILE_ACTION_REMOVED_BY_DELETE 0x00000009
|
||||
#define FILE_ACTION_ID_NOT_TUNNELLED 0x0000000A
|
||||
#define FILE_ACTION_TUNNELLED_ID_COLLISION 0x0000000B
|
||||
|
||||
/* See MS-SMB2 2.2.35 */
|
||||
struct smb2_change_notify_req {
|
||||
struct smb2_hdr hdr;
|
||||
@@ -1499,105 +1483,6 @@ struct network_interface_info_ioctl_rsp {
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA */
|
||||
struct file_zero_data_information {
|
||||
__le64 FileOffset;
|
||||
__le64 BeyondFinalZero;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.7 */
|
||||
struct duplicate_extents_to_file {
|
||||
__u64 PersistentFileHandle; /* source file handle, opaque endianness */
|
||||
__u64 VolatileFileHandle;
|
||||
__le64 SourceFileOffset;
|
||||
__le64 TargetFileOffset;
|
||||
__le64 ByteCount; /* Bytes to be copied */
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.9 */
|
||||
#define DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC 0x00000001
|
||||
struct duplicate_extents_to_file_ex {
|
||||
__le64 StructureSize; /* MUST be set to 0x30 */
|
||||
__u64 PersistentFileHandle; /* source file handle, opaque endianness */
|
||||
__u64 VolatileFileHandle;
|
||||
__le64 SourceFileOffset;
|
||||
__le64 TargetFileOffset;
|
||||
__le64 ByteCount; /* Bytes to be copied */
|
||||
__le32 Flags;
|
||||
__le32 Reserved;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* See MS-FSCC 2.3.20 */
|
||||
struct fsctl_get_integrity_information_rsp {
|
||||
__le16 ChecksumAlgorithm;
|
||||
__le16 Reserved;
|
||||
__le32 Flags;
|
||||
__le32 ChecksumChunkSizeInBytes;
|
||||
__le32 ClusterSizeInBytes;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.55 */
|
||||
struct fsctl_query_file_regions_req {
|
||||
__le64 FileOffset;
|
||||
__le64 Length;
|
||||
__le32 DesiredUsage;
|
||||
__le32 Reserved;
|
||||
} __packed;
|
||||
|
||||
/* DesiredUsage flags see MS-FSCC 2.3.56.1 */
|
||||
#define FILE_USAGE_INVALID_RANGE 0x00000000
|
||||
#define FILE_USAGE_VALID_CACHED_DATA 0x00000001
|
||||
#define FILE_USAGE_NONCACHED_DATA 0x00000002
|
||||
|
||||
struct file_region_info {
|
||||
__le64 FileOffset;
|
||||
__le64 Length;
|
||||
__le32 DesiredUsage;
|
||||
__le32 Reserved;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.56 */
|
||||
struct fsctl_query_file_region_rsp {
|
||||
__le32 Flags;
|
||||
__le32 TotalRegionEntryCount;
|
||||
__le32 RegionEntryCount;
|
||||
__u32 Reserved;
|
||||
struct file_region_info Regions[];
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.58 */
|
||||
struct fsctl_query_on_disk_vol_info_rsp {
|
||||
__le64 DirectoryCount;
|
||||
__le64 FileCount;
|
||||
__le16 FsFormatMajVersion;
|
||||
__le16 FsFormatMinVersion;
|
||||
__u8 FsFormatName[24];
|
||||
__le64 FormatTime;
|
||||
__le64 LastUpdateTime;
|
||||
__u8 CopyrightInfo[68];
|
||||
__u8 AbstractInfo[68];
|
||||
__u8 FormatImplInfo[68];
|
||||
__u8 LastModifyImplInfo[68];
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.73 */
|
||||
struct fsctl_set_integrity_information_req {
|
||||
__le16 ChecksumAlgorithm;
|
||||
__le16 Reserved;
|
||||
__le32 Flags;
|
||||
} __packed;
|
||||
|
||||
/* See MS-FSCC 2.3.75 */
|
||||
struct fsctl_set_integrity_info_ex_req {
|
||||
__u8 EnableIntegrity;
|
||||
__u8 KeepState;
|
||||
__u16 Reserved;
|
||||
__le32 Flags;
|
||||
__u8 Version;
|
||||
__u8 Reserved2[7];
|
||||
} __packed;
|
||||
|
||||
/* Integrity ChecksumAlgorithm choices for above */
|
||||
#define CHECKSUM_TYPE_NONE 0x0000
|
||||
#define CHECKSUM_TYPE_CRC64 0x0002
|
||||
@@ -1606,72 +1491,6 @@ struct fsctl_set_integrity_info_ex_req {
|
||||
/* Integrity flags for above */
|
||||
#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
|
||||
|
||||
/* Reparse structures - see MS-FSCC 2.1.2 */
|
||||
|
||||
/* struct fsctl_reparse_info_req is empty, only response structs (see below) */
|
||||
struct reparse_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__u8 DataBuffer[]; /* Variable Length */
|
||||
} __packed;
|
||||
|
||||
struct reparse_guid_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__u8 ReparseGuid[16];
|
||||
__u8 DataBuffer[]; /* Variable Length */
|
||||
} __packed;
|
||||
|
||||
struct reparse_mount_point_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__le16 SubstituteNameOffset;
|
||||
__le16 SubstituteNameLength;
|
||||
__le16 PrintNameOffset;
|
||||
__le16 PrintNameLength;
|
||||
__u8 PathBuffer[]; /* Variable Length */
|
||||
} __packed;
|
||||
|
||||
#define SYMLINK_FLAG_RELATIVE 0x00000001
|
||||
|
||||
struct reparse_symlink_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__le16 SubstituteNameOffset;
|
||||
__le16 SubstituteNameLength;
|
||||
__le16 PrintNameOffset;
|
||||
__le16 PrintNameLength;
|
||||
__le32 Flags;
|
||||
__u8 PathBuffer[]; /* Variable Length */
|
||||
} __packed;
|
||||
|
||||
/* For IO_REPARSE_TAG_NFS - see MS-FSCC 2.1.2.6 */
|
||||
#define NFS_SPECFILE_LNK 0x00000000014B4E4C
|
||||
#define NFS_SPECFILE_CHR 0x0000000000524843
|
||||
#define NFS_SPECFILE_BLK 0x00000000004B4C42
|
||||
#define NFS_SPECFILE_FIFO 0x000000004F464946
|
||||
#define NFS_SPECFILE_SOCK 0x000000004B434F53
|
||||
struct reparse_nfs_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__le64 InodeType; /* NFS_SPECFILE_* */
|
||||
__u8 DataBuffer[];
|
||||
} __packed;
|
||||
|
||||
/* For IO_REPARSE_TAG_LX_SYMLINK - see MS-FSCC 2.1.2.7 */
|
||||
struct reparse_wsl_symlink_data_buffer {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__le32 Version; /* Always 2 */
|
||||
__u8 Target[]; /* Variable Length UTF-8 string without nul-term */
|
||||
} __packed;
|
||||
|
||||
struct validate_negotiate_info_req {
|
||||
__le32 Capabilities;
|
||||
__u8 Guid[SMB2_CLIENT_GUID_SIZE];
|
||||
@@ -1791,84 +1610,6 @@ struct smb2_query_info_rsp {
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* PDU query infolevel structure definitions
|
||||
*/
|
||||
|
||||
/* See MS-FSCC 2.3.52 */
|
||||
struct file_allocated_range_buffer {
|
||||
__le64 file_offset;
|
||||
__le64 length;
|
||||
} __packed;
|
||||
|
||||
struct smb2_file_internal_info {
|
||||
__le64 IndexNumber;
|
||||
} __packed; /* level 6 Query */
|
||||
|
||||
struct smb2_file_rename_info { /* encoding of request for level 10 */
|
||||
/* New members MUST be added within the struct_group() macro below. */
|
||||
__struct_group(smb2_file_rename_info_hdr, __hdr, __packed,
|
||||
__u8 ReplaceIfExists; /* 1 = replace existing target with new */
|
||||
/* 0 = fail if target already exists */
|
||||
__u8 Reserved[7];
|
||||
__u64 RootDirectory; /* MBZ for network operations (why says spec?) */
|
||||
__le32 FileNameLength;
|
||||
);
|
||||
char FileName[]; /* New name to be assigned */
|
||||
/* padding - overall struct size must be >= 24 so filename + pad >= 6 */
|
||||
} __packed; /* level 10 Set */
|
||||
static_assert(offsetof(struct smb2_file_rename_info, FileName) == sizeof(struct smb2_file_rename_info_hdr),
|
||||
"struct member likely outside of __struct_group()");
|
||||
|
||||
struct smb2_file_link_info { /* encoding of request for level 11 */
|
||||
/* New members MUST be added within the struct_group() macro below. */
|
||||
__struct_group(smb2_file_link_info_hdr, __hdr, __packed,
|
||||
__u8 ReplaceIfExists; /* 1 = replace existing link with new */
|
||||
/* 0 = fail if link already exists */
|
||||
__u8 Reserved[7];
|
||||
__u64 RootDirectory; /* MBZ for network operations (why says spec?) */
|
||||
__le32 FileNameLength;
|
||||
);
|
||||
char FileName[]; /* Name to be assigned to new link */
|
||||
} __packed; /* level 11 Set */
|
||||
static_assert(offsetof(struct smb2_file_link_info, FileName) == sizeof(struct smb2_file_link_info_hdr),
|
||||
"struct member likely outside of __struct_group()");
|
||||
|
||||
/*
|
||||
* This level 18, although with struct with same name is different from cifs
|
||||
* level 0x107. Level 0x107 has an extra u64 between AccessFlags and
|
||||
* CurrentByteOffset.
|
||||
*/
|
||||
struct smb2_file_all_info { /* data block encoding of response to level 18 */
|
||||
__le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le32 Attributes;
|
||||
__u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
|
||||
__le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
|
||||
__le64 EndOfFile; /* size ie offset to first free byte in file */
|
||||
__le32 NumberOfLinks; /* hard links */
|
||||
__u8 DeletePending;
|
||||
__u8 Directory;
|
||||
__u16 Pad2; /* End of FILE_STANDARD_INFO equivalent */
|
||||
__le64 IndexNumber;
|
||||
__le32 EASize;
|
||||
__le32 AccessFlags;
|
||||
__le64 CurrentByteOffset;
|
||||
__le32 Mode;
|
||||
__le32 AlignmentRequirement;
|
||||
__le32 FileNameLength;
|
||||
union {
|
||||
char __pad; /* Legacy structure padding */
|
||||
DECLARE_FLEX_ARRAY(char, FileName);
|
||||
};
|
||||
} __packed; /* level 18 Query */
|
||||
|
||||
struct smb2_file_eof_info { /* encoding of request for level 10 */
|
||||
__le64 EndOfFile; /* new end of file value */
|
||||
} __packed; /* level 20 Set */
|
||||
|
||||
/* Level 100 query info */
|
||||
struct smb311_posix_qinfo {
|
||||
__le64 CreationTime;
|
||||
@@ -1894,65 +1635,6 @@ struct smb311_posix_qinfo {
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
/* File System Information Classes */
|
||||
#define FS_VOLUME_INFORMATION 1 /* Query */
|
||||
#define FS_LABEL_INFORMATION 2 /* Set */
|
||||
#define FS_SIZE_INFORMATION 3 /* Query */
|
||||
#define FS_DEVICE_INFORMATION 4 /* Query */
|
||||
#define FS_ATTRIBUTE_INFORMATION 5 /* Query */
|
||||
#define FS_CONTROL_INFORMATION 6 /* Query, Set */
|
||||
#define FS_FULL_SIZE_INFORMATION 7 /* Query */
|
||||
#define FS_OBJECT_ID_INFORMATION 8 /* Query, Set */
|
||||
#define FS_DRIVER_PATH_INFORMATION 9 /* Query */
|
||||
#define FS_SECTOR_SIZE_INFORMATION 11 /* SMB3 or later. Query */
|
||||
#define FS_POSIX_INFORMATION 100 /* SMB3.1.1 POSIX. Query */
|
||||
|
||||
struct smb2_fs_full_size_info {
|
||||
__le64 TotalAllocationUnits;
|
||||
__le64 CallerAvailableAllocationUnits;
|
||||
__le64 ActualAvailableAllocationUnits;
|
||||
__le32 SectorsPerAllocationUnit;
|
||||
__le32 BytesPerSector;
|
||||
} __packed;
|
||||
|
||||
#define SSINFO_FLAGS_ALIGNED_DEVICE 0x00000001
|
||||
#define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 0x00000002
|
||||
#define SSINFO_FLAGS_NO_SEEK_PENALTY 0x00000004
|
||||
#define SSINFO_FLAGS_TRIM_ENABLED 0x00000008
|
||||
|
||||
/* sector size info struct */
|
||||
struct smb3_fs_ss_info {
|
||||
__le32 LogicalBytesPerSector;
|
||||
__le32 PhysicalBytesPerSectorForAtomicity;
|
||||
__le32 PhysicalBytesPerSectorForPerf;
|
||||
__le32 FSEffPhysicalBytesPerSectorForAtomicity;
|
||||
__le32 Flags;
|
||||
__le32 ByteOffsetForSectorAlignment;
|
||||
__le32 ByteOffsetForPartitionAlignment;
|
||||
} __packed;
|
||||
|
||||
/* File System Control Information */
|
||||
struct smb2_fs_control_info {
|
||||
__le64 FreeSpaceStartFiltering;
|
||||
__le64 FreeSpaceThreshold;
|
||||
__le64 FreeSpaceStopFiltering;
|
||||
__le64 DefaultQuotaThreshold;
|
||||
__le64 DefaultQuotaLimit;
|
||||
__le32 FileSystemControlFlags;
|
||||
__le32 Padding;
|
||||
} __packed;
|
||||
|
||||
/* volume info struct - see MS-FSCC 2.5.9 */
|
||||
#define MAX_VOL_LABEL_LEN 32
|
||||
struct smb3_fs_vol_info {
|
||||
__le64 VolumeCreationTime;
|
||||
__u32 VolumeSerialNumber;
|
||||
__le32 VolumeLabelLength; /* includes trailing null */
|
||||
__u8 SupportsObjects; /* True if eg like NTFS, supports objects */
|
||||
__u8 Reserved;
|
||||
__u8 VolumeLabel[]; /* variable len */
|
||||
} __packed;
|
||||
|
||||
/* See MS-SMB2 2.2.23 through 2.2.25 */
|
||||
struct smb2_oplock_break {
|
||||
struct smb2_hdr hdr;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_H__
|
||||
#define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* SMB-DIRECT buffer descriptor V1 structure [MS-SMBD] 2.2.3.1 */
|
||||
struct smbdirect_buffer_descriptor_v1 {
|
||||
__le64 offset;
|
||||
|
||||
@@ -350,6 +350,35 @@ struct smbdirect_socket {
|
||||
u64 dequeue_reassembly_queue;
|
||||
u64 send_empty;
|
||||
} statistics;
|
||||
|
||||
struct {
|
||||
#define SMBDIRECT_LOG_ERR 0x0
|
||||
#define SMBDIRECT_LOG_INFO 0x1
|
||||
|
||||
#define SMBDIRECT_LOG_OUTGOING 0x1
|
||||
#define SMBDIRECT_LOG_INCOMING 0x2
|
||||
#define SMBDIRECT_LOG_READ 0x4
|
||||
#define SMBDIRECT_LOG_WRITE 0x8
|
||||
#define SMBDIRECT_LOG_RDMA_SEND 0x10
|
||||
#define SMBDIRECT_LOG_RDMA_RECV 0x20
|
||||
#define SMBDIRECT_LOG_KEEP_ALIVE 0x40
|
||||
#define SMBDIRECT_LOG_RDMA_EVENT 0x80
|
||||
#define SMBDIRECT_LOG_RDMA_MR 0x100
|
||||
#define SMBDIRECT_LOG_RDMA_RW 0x200
|
||||
#define SMBDIRECT_LOG_NEGOTIATE 0x400
|
||||
void *private_ptr;
|
||||
bool (*needed)(struct smbdirect_socket *sc,
|
||||
void *private_ptr,
|
||||
unsigned int lvl,
|
||||
unsigned int cls);
|
||||
void (*vaprintf)(struct smbdirect_socket *sc,
|
||||
const char *func,
|
||||
unsigned int line,
|
||||
void *private_ptr,
|
||||
unsigned int lvl,
|
||||
unsigned int cls,
|
||||
struct va_format *vaf);
|
||||
} logging;
|
||||
};
|
||||
|
||||
static void __smbdirect_socket_disabled_work(struct work_struct *work)
|
||||
@@ -360,6 +389,100 @@ static void __smbdirect_socket_disabled_work(struct work_struct *work)
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
static bool __smbdirect_log_needed(struct smbdirect_socket *sc,
|
||||
void *private_ptr,
|
||||
unsigned int lvl,
|
||||
unsigned int cls)
|
||||
{
|
||||
/*
|
||||
* Should never be called, the caller should
|
||||
* set it's own functions.
|
||||
*/
|
||||
WARN_ON_ONCE(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __smbdirect_log_vaprintf(struct smbdirect_socket *sc,
|
||||
const char *func,
|
||||
unsigned int line,
|
||||
void *private_ptr,
|
||||
unsigned int lvl,
|
||||
unsigned int cls,
|
||||
struct va_format *vaf)
|
||||
{
|
||||
/*
|
||||
* Should never be called, the caller should
|
||||
* set it's own functions.
|
||||
*/
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
__printf(6, 7)
|
||||
static void __smbdirect_log_printf(struct smbdirect_socket *sc,
|
||||
const char *func,
|
||||
unsigned int line,
|
||||
unsigned int lvl,
|
||||
unsigned int cls,
|
||||
const char *fmt,
|
||||
...);
|
||||
__maybe_unused
|
||||
static void __smbdirect_log_printf(struct smbdirect_socket *sc,
|
||||
const char *func,
|
||||
unsigned int line,
|
||||
unsigned int lvl,
|
||||
unsigned int cls,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
|
||||
sc->logging.vaprintf(sc,
|
||||
func,
|
||||
line,
|
||||
sc->logging.private_ptr,
|
||||
lvl,
|
||||
cls,
|
||||
&vaf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#define ___smbdirect_log_generic(sc, func, line, lvl, cls, fmt, args...) do { \
|
||||
if (sc->logging.needed(sc, sc->logging.private_ptr, lvl, cls)) { \
|
||||
__smbdirect_log_printf(sc, func, line, lvl, cls, fmt, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
#define __smbdirect_log_generic(sc, lvl, cls, fmt, args...) \
|
||||
___smbdirect_log_generic(sc, __func__, __LINE__, lvl, cls, fmt, ##args)
|
||||
|
||||
#define smbdirect_log_outgoing(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_OUTGOING, fmt, ##args)
|
||||
#define smbdirect_log_incoming(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_INCOMING, fmt, ##args)
|
||||
#define smbdirect_log_read(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_READ, fmt, ##args)
|
||||
#define smbdirect_log_write(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_WRITE, fmt, ##args)
|
||||
#define smbdirect_log_rdma_send(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_SEND, fmt, ##args)
|
||||
#define smbdirect_log_rdma_recv(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_RECV, fmt, ##args)
|
||||
#define smbdirect_log_keep_alive(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_KEEP_ALIVE, fmt, ##args)
|
||||
#define smbdirect_log_rdma_event(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_EVENT, fmt, ##args)
|
||||
#define smbdirect_log_rdma_mr(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_MR, fmt, ##args)
|
||||
#define smbdirect_log_rdma_rw(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_RW, fmt, ##args)
|
||||
#define smbdirect_log_negotiate(sc, lvl, fmt, args...) \
|
||||
__smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_NEGOTIATE, fmt, ##args)
|
||||
|
||||
static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
|
||||
{
|
||||
/*
|
||||
@@ -420,6 +543,10 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
|
||||
INIT_WORK(&sc->mr_io.recovery_work, __smbdirect_socket_disabled_work);
|
||||
disable_work_sync(&sc->mr_io.recovery_work);
|
||||
init_waitqueue_head(&sc->mr_io.cleanup.wait_queue);
|
||||
|
||||
sc->logging.private_ptr = NULL;
|
||||
sc->logging.needed = __smbdirect_log_needed;
|
||||
sc->logging.vaprintf = __smbdirect_log_vaprintf;
|
||||
}
|
||||
|
||||
#define __SMBDIRECT_CHECK_STATUS_FAILED(__sc, __expected_status, __error_cmd, __unexpected_cmd) ({ \
|
||||
@@ -436,7 +563,6 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
|
||||
|
||||
#define __SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status, __unexpected_cmd) \
|
||||
__SMBDIRECT_CHECK_STATUS_FAILED(__sc, __expected_status, \
|
||||
, \
|
||||
{ \
|
||||
const struct sockaddr_storage *__src = NULL; \
|
||||
const struct sockaddr_storage *__dst = NULL; \
|
||||
@@ -444,6 +570,26 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
|
||||
__src = &(__sc)->rdma.cm_id->route.addr.src_addr; \
|
||||
__dst = &(__sc)->rdma.cm_id->route.addr.dst_addr; \
|
||||
} \
|
||||
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO, \
|
||||
"expected[%s] != %s first_error=%1pe local=%pISpsfc remote=%pISpsfc\n", \
|
||||
smbdirect_socket_status_string(__expected_status), \
|
||||
smbdirect_socket_status_string((__sc)->status), \
|
||||
SMBDIRECT_DEBUG_ERR_PTR((__sc)->first_error), \
|
||||
__src, __dst); \
|
||||
}, \
|
||||
{ \
|
||||
const struct sockaddr_storage *__src = NULL; \
|
||||
const struct sockaddr_storage *__dst = NULL; \
|
||||
if ((__sc)->rdma.cm_id) { \
|
||||
__src = &(__sc)->rdma.cm_id->route.addr.src_addr; \
|
||||
__dst = &(__sc)->rdma.cm_id->route.addr.dst_addr; \
|
||||
} \
|
||||
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR, \
|
||||
"expected[%s] != %s first_error=%1pe local=%pISpsfc remote=%pISpsfc\n", \
|
||||
smbdirect_socket_status_string(__expected_status), \
|
||||
smbdirect_socket_status_string((__sc)->status), \
|
||||
SMBDIRECT_DEBUG_ERR_PTR((__sc)->first_error), \
|
||||
__src, __dst); \
|
||||
WARN_ONCE(1, \
|
||||
"expected[%s] != %s first_error=%1pe local=%pISpsfc remote=%pISpsfc\n", \
|
||||
smbdirect_socket_status_string(__expected_status), \
|
||||
|
||||
@@ -7,7 +7,6 @@ config SMB_SERVER
|
||||
select NLS_UTF8
|
||||
select NLS_UCS2_UTILS
|
||||
select CRYPTO
|
||||
select CRYPTO_ECB
|
||||
select CRYPTO_LIB_ARC4
|
||||
select CRYPTO_LIB_DES
|
||||
select CRYPTO_LIB_MD5
|
||||
|
||||
@@ -827,6 +827,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
|
||||
struct smb2_transform_hdr *tr_hdr = smb_get_msg(iov[0].iov_base);
|
||||
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
|
||||
int rc;
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
struct scatterlist *sg;
|
||||
u8 sign[SMB2_SIGNATURE_SIZE] = {};
|
||||
u8 key[SMB3_ENC_DEC_KEY_SIZE];
|
||||
@@ -913,12 +914,12 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
|
||||
|
||||
aead_request_set_crypt(req, sg, sg, crypt_len, iv);
|
||||
aead_request_set_ad(req, assoc_data_len);
|
||||
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
|
||||
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
|
||||
CRYPTO_TFM_REQ_MAY_SLEEP,
|
||||
crypto_req_done, &wait);
|
||||
|
||||
if (enc)
|
||||
rc = crypto_aead_encrypt(req);
|
||||
else
|
||||
rc = crypto_aead_decrypt(req);
|
||||
rc = crypto_wait_req(enc ? crypto_aead_encrypt(req) :
|
||||
crypto_aead_decrypt(req), &wait);
|
||||
if (rc)
|
||||
goto free_iv;
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ void ksmbd_conn_free(struct ksmbd_conn *conn)
|
||||
xa_destroy(&conn->sessions);
|
||||
kvfree(conn->request_buf);
|
||||
kfree(conn->preauth_info);
|
||||
kfree(conn->mechToken);
|
||||
if (atomic_dec_and_test(&conn->refcnt)) {
|
||||
conn->transport->ops->free_transport(conn->transport);
|
||||
kfree(conn);
|
||||
|
||||
@@ -20,11 +20,6 @@ enum {
|
||||
CRYPTO_AEAD_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
CRYPTO_BLK_ECBDES = 32,
|
||||
CRYPTO_BLK_MAX,
|
||||
};
|
||||
|
||||
struct ksmbd_crypto_ctx {
|
||||
struct list_head list;
|
||||
|
||||
|
||||
@@ -382,12 +382,10 @@ void ksmbd_session_destroy(struct ksmbd_session *sess)
|
||||
return;
|
||||
|
||||
delete_proc_session(sess);
|
||||
|
||||
ksmbd_tree_conn_session_logoff(sess);
|
||||
ksmbd_destroy_file_table(sess);
|
||||
if (sess->user)
|
||||
ksmbd_free_user(sess->user);
|
||||
|
||||
ksmbd_tree_conn_session_logoff(sess);
|
||||
ksmbd_destroy_file_table(&sess->file_table);
|
||||
ksmbd_launch_ksmbd_durable_scavenger();
|
||||
ksmbd_session_rpc_clear_list(sess);
|
||||
free_channel_list(sess);
|
||||
@@ -618,7 +616,7 @@ void destroy_previous_session(struct ksmbd_conn *conn,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ksmbd_destroy_file_table(&prev_sess->file_table);
|
||||
ksmbd_destroy_file_table(prev_sess);
|
||||
prev_sess->state = SMB2_SESSION_EXPIRED;
|
||||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
|
||||
ksmbd_launch_ksmbd_durable_scavenger();
|
||||
|
||||
@@ -1841,6 +1841,7 @@ int smb2_check_durable_oplock(struct ksmbd_conn *conn,
|
||||
struct ksmbd_share_config *share,
|
||||
struct ksmbd_file *fp,
|
||||
struct lease_ctx_info *lctx,
|
||||
struct ksmbd_user *user,
|
||||
char *name)
|
||||
{
|
||||
struct oplock_info *opinfo = opinfo_get(fp);
|
||||
@@ -1849,6 +1850,12 @@ int smb2_check_durable_oplock(struct ksmbd_conn *conn,
|
||||
if (!opinfo)
|
||||
return 0;
|
||||
|
||||
if (ksmbd_vfs_compare_durable_owner(fp, user) == false) {
|
||||
ksmbd_debug(SMB, "Durable handle reconnect failed: owner mismatch\n");
|
||||
ret = -EBADF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opinfo->is_lease == false) {
|
||||
if (lctx) {
|
||||
pr_err("create context include lease\n");
|
||||
|
||||
@@ -126,5 +126,6 @@ int smb2_check_durable_oplock(struct ksmbd_conn *conn,
|
||||
struct ksmbd_share_config *share,
|
||||
struct ksmbd_file *fp,
|
||||
struct lease_ctx_info *lctx,
|
||||
struct ksmbd_user *user,
|
||||
char *name);
|
||||
#endif /* __KSMBD_OPLOCK_H */
|
||||
|
||||
@@ -629,7 +629,6 @@ static void __exit ksmbd_server_exit(void)
|
||||
MODULE_AUTHOR("Namjae Jeon <linkinjeon@kernel.org>");
|
||||
MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_SOFTDEP("pre: ecb");
|
||||
MODULE_SOFTDEP("pre: nls");
|
||||
MODULE_SOFTDEP("pre: aes");
|
||||
MODULE_SOFTDEP("pre: cmac");
|
||||
|
||||
@@ -1915,7 +1915,7 @@ out_err:
|
||||
else if (rc)
|
||||
rsp->hdr.Status = STATUS_LOGON_FAILURE;
|
||||
|
||||
if (conn->use_spnego && conn->mechToken) {
|
||||
if (conn->mechToken) {
|
||||
kfree(conn->mechToken);
|
||||
conn->mechToken = NULL;
|
||||
}
|
||||
@@ -3013,7 +3013,8 @@ int smb2_open(struct ksmbd_work *work)
|
||||
}
|
||||
|
||||
if (dh_info.reconnected == true) {
|
||||
rc = smb2_check_durable_oplock(conn, share, dh_info.fp, lc, name);
|
||||
rc = smb2_check_durable_oplock(conn, share, dh_info.fp,
|
||||
lc, sess->user, name);
|
||||
if (rc) {
|
||||
ksmbd_put_durable_fd(dh_info.fp);
|
||||
goto err_out2;
|
||||
@@ -4716,6 +4717,11 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
|
||||
ea_req = (struct smb2_ea_info_req *)((char *)req +
|
||||
le16_to_cpu(req->InputBufferOffset));
|
||||
|
||||
if (le32_to_cpu(req->InputBufferLength) <
|
||||
offsetof(struct smb2_ea_info_req, name) +
|
||||
ea_req->EaNameLength)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
/* need to send all EAs, if no specific EA is requested*/
|
||||
if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY)
|
||||
@@ -4858,7 +4864,7 @@ static void get_file_access_info(struct smb2_query_info_rsp *rsp,
|
||||
static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
|
||||
struct ksmbd_file *fp, void *rsp_org)
|
||||
{
|
||||
struct smb2_file_basic_info *basic_info;
|
||||
struct file_basic_info *basic_info;
|
||||
struct kstat stat;
|
||||
u64 time;
|
||||
int ret;
|
||||
@@ -4874,7 +4880,7 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
basic_info = (struct smb2_file_basic_info *)rsp->Buffer;
|
||||
basic_info = (struct file_basic_info *)rsp->Buffer;
|
||||
basic_info->CreationTime = cpu_to_le64(fp->create_time);
|
||||
time = ksmbd_UnixTimeToNT(stat.atime);
|
||||
basic_info->LastAccessTime = cpu_to_le64(time);
|
||||
@@ -4883,9 +4889,9 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
|
||||
time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
basic_info->ChangeTime = cpu_to_le64(time);
|
||||
basic_info->Attributes = fp->f_ci->m_fattr;
|
||||
basic_info->Pad1 = 0;
|
||||
basic_info->Pad = 0;
|
||||
rsp->OutputBufferLength =
|
||||
cpu_to_le32(sizeof(struct smb2_file_basic_info));
|
||||
cpu_to_le32(sizeof(struct file_basic_info));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5583,13 +5589,14 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
|
||||
serial_crc = crc32_le(serial_crc, ksmbd_netbios_name(),
|
||||
strlen(ksmbd_netbios_name()));
|
||||
/* Taking dummy value of serial number*/
|
||||
info->SerialNumber = cpu_to_le32(serial_crc);
|
||||
info->VolumeSerialNumber = cpu_to_le32(serial_crc);
|
||||
len = smbConvertToUTF16((__le16 *)info->VolumeLabel,
|
||||
share->name, PATH_MAX,
|
||||
conn->local_nls, 0);
|
||||
len = len * 2;
|
||||
info->VolumeLabelSize = cpu_to_le32(len);
|
||||
info->VolumeLabelLength = cpu_to_le32(len);
|
||||
info->Reserved = 0;
|
||||
info->SupportsObjects = 0;
|
||||
sz = sizeof(struct filesystem_vol_info) + len;
|
||||
rsp->OutputBufferLength = cpu_to_le32(sz);
|
||||
break;
|
||||
@@ -6222,7 +6229,7 @@ out:
|
||||
}
|
||||
|
||||
static int set_file_basic_info(struct ksmbd_file *fp,
|
||||
struct smb2_file_basic_info *file_info,
|
||||
struct file_basic_info *file_info,
|
||||
struct ksmbd_share_config *share)
|
||||
{
|
||||
struct iattr attrs;
|
||||
@@ -6504,10 +6511,10 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
switch (req->FileInfoClass) {
|
||||
case FILE_BASIC_INFORMATION:
|
||||
{
|
||||
if (buf_len < sizeof(struct smb2_file_basic_info))
|
||||
if (buf_len < sizeof(struct file_basic_info))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return set_file_basic_info(fp, (struct smb2_file_basic_info *)buffer, share);
|
||||
return set_file_basic_info(fp, (struct file_basic_info *)buffer, share);
|
||||
}
|
||||
case FILE_ALLOCATION_INFORMATION:
|
||||
{
|
||||
|
||||
@@ -186,15 +186,6 @@ struct smb2_file_alignment_info {
|
||||
__le32 AlignmentRequirement;
|
||||
} __packed;
|
||||
|
||||
struct smb2_file_basic_info { /* data block encoding of response to level 18 */
|
||||
__le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le32 Attributes;
|
||||
__u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
|
||||
} __packed;
|
||||
|
||||
struct smb2_file_alt_name_info {
|
||||
__le32 FileNameLength;
|
||||
char FileName[];
|
||||
|
||||
@@ -90,14 +90,6 @@ struct smb_negotiate_rsp {
|
||||
__le16 ByteCount;
|
||||
} __packed;
|
||||
|
||||
struct filesystem_vol_info {
|
||||
__le64 VolumeCreationTime;
|
||||
__le32 SerialNumber;
|
||||
__le32 VolumeLabelSize;
|
||||
__le16 Reserved;
|
||||
__le16 VolumeLabel[];
|
||||
} __packed;
|
||||
|
||||
#define EXTENDED_INFO_MAGIC 0x43667364 /* Cfsd */
|
||||
#define STRING_LENGTH 28
|
||||
|
||||
|
||||
@@ -451,7 +451,8 @@ static void parse_dacl(struct mnt_idmap *idmap,
|
||||
ppace[i]->access_req =
|
||||
smb_map_generic_desired_access(ppace[i]->access_req);
|
||||
|
||||
if (!(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) {
|
||||
if (ppace[i]->sid.num_subauth >= 3 &&
|
||||
!(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) {
|
||||
fattr->cf_mode =
|
||||
le32_to_cpu(ppace[i]->sid.sub_auth[2]);
|
||||
break;
|
||||
|
||||
@@ -55,7 +55,7 @@ static bool ksmbd_ipc_validate_version(struct genl_info *m)
|
||||
struct ksmbd_ipc_msg {
|
||||
unsigned int type;
|
||||
unsigned int sz;
|
||||
unsigned char payload[];
|
||||
unsigned char payload[] __counted_by(sz);
|
||||
};
|
||||
|
||||
struct ipc_msg_table_entry {
|
||||
@@ -242,9 +242,8 @@ static void ipc_update_last_active(void)
|
||||
static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz)
|
||||
{
|
||||
struct ksmbd_ipc_msg *msg;
|
||||
size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg);
|
||||
|
||||
msg = kvzalloc(msg_sz, KSMBD_DEFAULT_GFP);
|
||||
msg = kvzalloc_flex(*msg, payload, sz, KSMBD_DEFAULT_GFP);
|
||||
if (msg)
|
||||
msg->sz = sz;
|
||||
return msg;
|
||||
|
||||
@@ -1588,15 +1588,21 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* From here msg is moved to send_ctx
|
||||
* and we should not free it explicitly.
|
||||
*/
|
||||
|
||||
if (send_ctx == &_send_ctx) {
|
||||
ret = smb_direct_flush_send_list(sc, send_ctx, true);
|
||||
if (ret)
|
||||
goto err;
|
||||
goto flush_failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
smb_direct_free_sendmsg(sc, msg);
|
||||
flush_failed:
|
||||
header_failed:
|
||||
atomic_inc(&sc->send_io.credits.count);
|
||||
credit_failed:
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "misc.h"
|
||||
#include "mgmt/tree_connect.h"
|
||||
#include "mgmt/user_session.h"
|
||||
#include "mgmt/user_config.h"
|
||||
#include "smb_common.h"
|
||||
#include "server.h"
|
||||
#include "smb2pdu.h"
|
||||
@@ -463,9 +464,11 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
|
||||
* there are not accesses to fp->lock_list.
|
||||
*/
|
||||
list_for_each_entry_safe(smb_lock, tmp_lock, &fp->lock_list, flist) {
|
||||
spin_lock(&fp->conn->llist_lock);
|
||||
list_del(&smb_lock->clist);
|
||||
spin_unlock(&fp->conn->llist_lock);
|
||||
if (!list_empty(&smb_lock->clist) && fp->conn) {
|
||||
spin_lock(&fp->conn->llist_lock);
|
||||
list_del(&smb_lock->clist);
|
||||
spin_unlock(&fp->conn->llist_lock);
|
||||
}
|
||||
|
||||
list_del(&smb_lock->flist);
|
||||
locks_free_lock(smb_lock->fl);
|
||||
@@ -474,6 +477,8 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
|
||||
|
||||
if (ksmbd_stream_fd(fp))
|
||||
kfree(fp->stream.name);
|
||||
kfree(fp->owner.name);
|
||||
|
||||
kmem_cache_free(filp_cache, fp);
|
||||
}
|
||||
|
||||
@@ -785,11 +790,13 @@ void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
|
||||
}
|
||||
|
||||
static int
|
||||
__close_file_table_ids(struct ksmbd_file_table *ft,
|
||||
__close_file_table_ids(struct ksmbd_session *sess,
|
||||
struct ksmbd_tree_connect *tcon,
|
||||
bool (*skip)(struct ksmbd_tree_connect *tcon,
|
||||
struct ksmbd_file *fp))
|
||||
struct ksmbd_file *fp,
|
||||
struct ksmbd_user *user))
|
||||
{
|
||||
struct ksmbd_file_table *ft = &sess->file_table;
|
||||
struct ksmbd_file *fp;
|
||||
unsigned int id = 0;
|
||||
int num = 0;
|
||||
@@ -802,7 +809,7 @@ __close_file_table_ids(struct ksmbd_file_table *ft,
|
||||
break;
|
||||
}
|
||||
|
||||
if (skip(tcon, fp) ||
|
||||
if (skip(tcon, fp, sess->user) ||
|
||||
!atomic_dec_and_test(&fp->refcount)) {
|
||||
id++;
|
||||
write_unlock(&ft->lock);
|
||||
@@ -854,7 +861,8 @@ static inline bool is_reconnectable(struct ksmbd_file *fp)
|
||||
}
|
||||
|
||||
static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon,
|
||||
struct ksmbd_file *fp)
|
||||
struct ksmbd_file *fp,
|
||||
struct ksmbd_user *user)
|
||||
{
|
||||
return fp->tcon != tcon;
|
||||
}
|
||||
@@ -989,16 +997,74 @@ void ksmbd_stop_durable_scavenger(void)
|
||||
kthread_stop(server_conf.dh_task);
|
||||
}
|
||||
|
||||
/*
|
||||
* ksmbd_vfs_copy_durable_owner - Copy owner info for durable reconnect
|
||||
* @fp: ksmbd file pointer to store owner info
|
||||
* @user: user pointer to copy from
|
||||
*
|
||||
* This function binds the current user's identity to the file handle
|
||||
* to satisfy MS-SMB2 Step 8 (SecurityContext matching) during reconnect.
|
||||
*
|
||||
* Return: 0 on success, or negative error code on failure
|
||||
*/
|
||||
static int ksmbd_vfs_copy_durable_owner(struct ksmbd_file *fp,
|
||||
struct ksmbd_user *user)
|
||||
{
|
||||
if (!user)
|
||||
return -EINVAL;
|
||||
|
||||
/* Duplicate the user name to ensure identity persistence */
|
||||
fp->owner.name = kstrdup(user->name, GFP_KERNEL);
|
||||
if (!fp->owner.name)
|
||||
return -ENOMEM;
|
||||
|
||||
fp->owner.uid = user->uid;
|
||||
fp->owner.gid = user->gid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ksmbd_vfs_compare_durable_owner - Verify if the requester is original owner
|
||||
* @fp: existing ksmbd file pointer
|
||||
* @user: user pointer of the reconnect requester
|
||||
*
|
||||
* Compares the UID, GID, and name of the current requester against the
|
||||
* original owner stored in the file handle.
|
||||
*
|
||||
* Return: true if the user matches, false otherwise
|
||||
*/
|
||||
bool ksmbd_vfs_compare_durable_owner(struct ksmbd_file *fp,
|
||||
struct ksmbd_user *user)
|
||||
{
|
||||
if (!user || !fp->owner.name)
|
||||
return false;
|
||||
|
||||
/* Check if the UID and GID match first (fast path) */
|
||||
if (fp->owner.uid != user->uid || fp->owner.gid != user->gid)
|
||||
return false;
|
||||
|
||||
/* Validate the account name to ensure the same SecurityContext */
|
||||
if (strcmp(fp->owner.name, user->name))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool session_fd_check(struct ksmbd_tree_connect *tcon,
|
||||
struct ksmbd_file *fp)
|
||||
struct ksmbd_file *fp, struct ksmbd_user *user)
|
||||
{
|
||||
struct ksmbd_inode *ci;
|
||||
struct oplock_info *op;
|
||||
struct ksmbd_conn *conn;
|
||||
struct ksmbd_lock *smb_lock, *tmp_lock;
|
||||
|
||||
if (!is_reconnectable(fp))
|
||||
return false;
|
||||
|
||||
if (ksmbd_vfs_copy_durable_owner(fp, user))
|
||||
return false;
|
||||
|
||||
conn = fp->conn;
|
||||
ci = fp->f_ci;
|
||||
down_write(&ci->m_lock);
|
||||
@@ -1011,6 +1077,12 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon,
|
||||
}
|
||||
up_write(&ci->m_lock);
|
||||
|
||||
list_for_each_entry_safe(smb_lock, tmp_lock, &fp->lock_list, flist) {
|
||||
spin_lock(&fp->conn->llist_lock);
|
||||
list_del_init(&smb_lock->clist);
|
||||
spin_unlock(&fp->conn->llist_lock);
|
||||
}
|
||||
|
||||
fp->conn = NULL;
|
||||
fp->tcon = NULL;
|
||||
fp->volatile_id = KSMBD_NO_FID;
|
||||
@@ -1024,7 +1096,7 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon,
|
||||
|
||||
void ksmbd_close_tree_conn_fds(struct ksmbd_work *work)
|
||||
{
|
||||
int num = __close_file_table_ids(&work->sess->file_table,
|
||||
int num = __close_file_table_ids(work->sess,
|
||||
work->tcon,
|
||||
tree_conn_fd_check);
|
||||
|
||||
@@ -1033,7 +1105,7 @@ void ksmbd_close_tree_conn_fds(struct ksmbd_work *work)
|
||||
|
||||
void ksmbd_close_session_fds(struct ksmbd_work *work)
|
||||
{
|
||||
int num = __close_file_table_ids(&work->sess->file_table,
|
||||
int num = __close_file_table_ids(work->sess,
|
||||
work->tcon,
|
||||
session_fd_check);
|
||||
|
||||
@@ -1090,6 +1162,9 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
|
||||
{
|
||||
struct ksmbd_inode *ci;
|
||||
struct oplock_info *op;
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
struct ksmbd_lock *smb_lock;
|
||||
unsigned int old_f_state;
|
||||
|
||||
if (!fp->is_durable || fp->conn || fp->tcon) {
|
||||
pr_err("Invalid durable fd [%p:%p]\n", fp->conn, fp->tcon);
|
||||
@@ -1101,9 +1176,23 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
fp->conn = work->conn;
|
||||
old_f_state = fp->f_state;
|
||||
fp->f_state = FP_NEW;
|
||||
__open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
|
||||
if (!has_file_id(fp->volatile_id)) {
|
||||
fp->f_state = old_f_state;
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
fp->conn = conn;
|
||||
fp->tcon = work->tcon;
|
||||
|
||||
list_for_each_entry(smb_lock, &fp->lock_list, flist) {
|
||||
spin_lock(&conn->llist_lock);
|
||||
list_add_tail(&smb_lock->clist, &conn->lock_list);
|
||||
spin_unlock(&conn->llist_lock);
|
||||
}
|
||||
|
||||
ci = fp->f_ci;
|
||||
down_write(&ci->m_lock);
|
||||
list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
|
||||
@@ -1114,13 +1203,10 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
|
||||
}
|
||||
up_write(&ci->m_lock);
|
||||
|
||||
fp->f_state = FP_NEW;
|
||||
__open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
|
||||
if (!has_file_id(fp->volatile_id)) {
|
||||
fp->conn = NULL;
|
||||
fp->tcon = NULL;
|
||||
return -EBADF;
|
||||
}
|
||||
fp->owner.uid = fp->owner.gid = 0;
|
||||
kfree(fp->owner.name);
|
||||
fp->owner.name = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1135,12 +1221,14 @@ int ksmbd_init_file_table(struct ksmbd_file_table *ft)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ksmbd_destroy_file_table(struct ksmbd_file_table *ft)
|
||||
void ksmbd_destroy_file_table(struct ksmbd_session *sess)
|
||||
{
|
||||
struct ksmbd_file_table *ft = &sess->file_table;
|
||||
|
||||
if (!ft->idr)
|
||||
return;
|
||||
|
||||
__close_file_table_ids(ft, NULL, session_fd_check);
|
||||
__close_file_table_ids(sess, NULL, session_fd_check);
|
||||
idr_destroy(ft->idr);
|
||||
kfree(ft->idr);
|
||||
ft->idr = NULL;
|
||||
|
||||
@@ -68,6 +68,13 @@ enum {
|
||||
FP_CLOSED
|
||||
};
|
||||
|
||||
/* Owner information for durable handle reconnect */
|
||||
struct durable_owner {
|
||||
unsigned int uid;
|
||||
unsigned int gid;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct ksmbd_file {
|
||||
struct file *filp;
|
||||
u64 persistent_id;
|
||||
@@ -114,6 +121,7 @@ struct ksmbd_file {
|
||||
bool is_resilient;
|
||||
|
||||
bool is_posix_ctxt;
|
||||
struct durable_owner owner;
|
||||
};
|
||||
|
||||
static inline void set_ctx_actor(struct dir_context *ctx,
|
||||
@@ -140,7 +148,7 @@ static inline bool ksmbd_stream_fd(struct ksmbd_file *fp)
|
||||
}
|
||||
|
||||
int ksmbd_init_file_table(struct ksmbd_file_table *ft);
|
||||
void ksmbd_destroy_file_table(struct ksmbd_file_table *ft);
|
||||
void ksmbd_destroy_file_table(struct ksmbd_session *sess);
|
||||
int ksmbd_close_fd(struct ksmbd_work *work, u64 id);
|
||||
struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id);
|
||||
struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id);
|
||||
@@ -166,6 +174,8 @@ void ksmbd_free_global_file_table(void);
|
||||
void ksmbd_set_fd_limit(unsigned long limit);
|
||||
void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
|
||||
unsigned int state);
|
||||
bool ksmbd_vfs_compare_durable_owner(struct ksmbd_file *fp,
|
||||
struct ksmbd_user *user);
|
||||
|
||||
/*
|
||||
* INODE hash
|
||||
|
||||
Reference in New Issue
Block a user