diff options
Diffstat (limited to 'fs/smb/server/transport_ipc.c')
| -rw-r--r-- | fs/smb/server/transport_ipc.c | 20 | 
1 files changed, 19 insertions, 1 deletions
diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c index 2aa1b29bea08..2c08cccfa680 100644 --- a/fs/smb/server/transport_ipc.c +++ b/fs/smb/server/transport_ipc.c @@ -263,10 +263,16 @@ static void ipc_msg_handle_free(int handle)  static int handle_response(int type, void *payload, size_t sz)  { -	unsigned int handle = *(unsigned int *)payload; +	unsigned int handle;  	struct ipc_msg_table_entry *entry;  	int ret = 0; +	/* Prevent 4-byte read beyond declared payload size */ +	if (sz < sizeof(unsigned int)) +		return -EINVAL; + +	handle = *(unsigned int *)payload; +  	ipc_update_last_active();  	down_read(&ipc_msg_table_lock);  	hash_for_each_possible(ipc_msg_table, entry, ipc_table_hlist, handle) { @@ -825,6 +831,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle  	if (!msg)  		return NULL; +	lockdep_assert_not_held(&sess->rpc_lock); + +	down_read(&sess->rpc_lock);  	msg->type = KSMBD_EVENT_RPC_REQUEST;  	req = (struct ksmbd_rpc_command *)msg->payload;  	req->handle = handle; @@ -833,6 +842,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle  	req->flags |= KSMBD_RPC_WRITE_METHOD;  	req->payload_sz = payload_sz;  	memcpy(req->payload, payload, payload_sz); +	up_read(&sess->rpc_lock);  	resp = ipc_msg_send_request(msg, req->handle);  	ipc_msg_free(msg); @@ -849,6 +859,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)  	if (!msg)  		return NULL; +	lockdep_assert_not_held(&sess->rpc_lock); + +	down_read(&sess->rpc_lock);  	msg->type = KSMBD_EVENT_RPC_REQUEST;  	req = (struct ksmbd_rpc_command *)msg->payload;  	req->handle = handle; @@ -856,6 +869,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)  	req->flags |= rpc_context_flags(sess);  	req->flags |= KSMBD_RPC_READ_METHOD;  	req->payload_sz = 0; +	up_read(&sess->rpc_lock);  	resp = ipc_msg_send_request(msg, req->handle);  	ipc_msg_free(msg); @@ -876,6 +890,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle  	if (!msg)  		return NULL; +	lockdep_assert_not_held(&sess->rpc_lock); + +	down_read(&sess->rpc_lock);  	msg->type = KSMBD_EVENT_RPC_REQUEST;  	req = (struct ksmbd_rpc_command *)msg->payload;  	req->handle = handle; @@ -884,6 +901,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle  	req->flags |= KSMBD_RPC_IOCTL_METHOD;  	req->payload_sz = payload_sz;  	memcpy(req->payload, payload, payload_sz); +	up_read(&sess->rpc_lock);  	resp = ipc_msg_send_request(msg, req->handle);  	ipc_msg_free(msg);  | 
