fs/smb/server/smb2misc.c

Source file repositories/reference/linux-study-clean/fs/smb/server/smb2misc.c

File Facts

System
Linux kernel
Corpus path
fs/smb/server/smb2misc.c
Extension
.c
Size
13875 bytes
Lines
473
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (((struct smb2_create_req *)hdr)->CreateContextsLength) {
			*off = le32_to_cpu(((struct smb2_create_req *)
				hdr)->CreateContextsOffset);
			*len = le32_to_cpu(((struct smb2_create_req *)
				hdr)->CreateContextsLength);
			if (!name_len)
				break;

			if (name_off + name_len < (u64)*off + *len)
				break;
		}

		*off = name_off;
		*len = name_len;
		break;
	}
	case SMB2_QUERY_INFO:
		*off = max_t(unsigned int,
			     le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset),
			     offsetof(struct smb2_query_info_req, Buffer));
		*len = le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLength);
		break;
	case SMB2_SET_INFO:
		*off = max_t(unsigned int,
			     le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset),
			     offsetof(struct smb2_set_info_req, Buffer));
		*len = le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength);
		break;
	case SMB2_READ:
		*off = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoOffset);
		*len = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoLength);
		break;
	case SMB2_WRITE:
		if (((struct smb2_write_req *)hdr)->DataOffset ||
		    ((struct smb2_write_req *)hdr)->Length) {
			*off = max_t(unsigned short int,
				     le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset),
				     offsetof(struct smb2_write_req, Buffer));
			*len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length);
			break;
		}

		*off = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoOffset);
		*len = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLength);
		break;
	case SMB2_QUERY_DIRECTORY:
		*off = max_t(unsigned short int,
			     le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset),
			     offsetof(struct smb2_query_directory_req, Buffer));
		*len = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameLength);
		break;
	case SMB2_LOCK:
	{
		unsigned short lock_count;

		lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount);
		if (lock_count > 0) {
			*off = offsetof(struct smb2_lock_req, locks);
			*len = sizeof(struct smb2_lock_element) * lock_count;
		}
		break;
	}
	case SMB2_IOCTL:
		*off = max_t(unsigned int,
			     le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset),
			     offsetof(struct smb2_ioctl_req, Buffer));
		*len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount);
		break;
	default:
		ksmbd_debug(SMB, "no length check for command\n");
		break;
	}

	if (*off > 4096) {
		ksmbd_debug(SMB, "offset %d too large\n", *off);
		ret = -EINVAL;
	} else if ((u64)*off + *len > MAX_STREAM_PROT_LEN) {
		ksmbd_debug(SMB, "Request is larger than maximum stream protocol length(%u): %llu\n",
			    MAX_STREAM_PROT_LEN, (u64)*off + *len);
		ret = -EINVAL;
	}

	return ret;
}

/*
 * Calculate the size of the SMB message based on the fixed header
 * portion, the number of word parameters and the data portion of the message.
 */
static int smb2_calc_size(void *buf, unsigned int *len)

Annotation

Implementation Notes