Skip to content

Commit 158a66b

Browse files
Marios Makassikissmfrench
authored andcommitted
ksmbd: validate length in smb2_write()
The SMB2 Write packet contains data that is to be written to a file or to a pipe. Depending on the client, there may be padding between the header and the data field. Currently, the length is validated only in the case padding is present. Since the DataOffset field always points to the beginning of the data, there is no need to have a special case for padding. By removing this, the length is validated in both cases. Signed-off-by: Marios Makassikis <[email protected]> Acked-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent d21a580 commit 158a66b

File tree

1 file changed

+19
-30
lines changed

1 file changed

+19
-30
lines changed

fs/ksmbd/smb2pdu.c

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6328,23 +6328,18 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
63286328
length = le32_to_cpu(req->Length);
63296329
id = req->VolatileFileId;
63306330

6331-
if (le16_to_cpu(req->DataOffset) ==
6332-
offsetof(struct smb2_write_req, Buffer)) {
6333-
data_buf = (char *)&req->Buffer[0];
6334-
} else {
6335-
if ((u64)le16_to_cpu(req->DataOffset) + length >
6336-
get_rfc1002_len(work->request_buf)) {
6337-
pr_err("invalid write data offset %u, smb_len %u\n",
6338-
le16_to_cpu(req->DataOffset),
6339-
get_rfc1002_len(work->request_buf));
6340-
err = -EINVAL;
6341-
goto out;
6342-
}
6343-
6344-
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
6345-
le16_to_cpu(req->DataOffset));
6331+
if ((u64)le16_to_cpu(req->DataOffset) + length >
6332+
get_rfc1002_len(work->request_buf)) {
6333+
pr_err("invalid write data offset %u, smb_len %u\n",
6334+
le16_to_cpu(req->DataOffset),
6335+
get_rfc1002_len(work->request_buf));
6336+
err = -EINVAL;
6337+
goto out;
63466338
}
63476339

6340+
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
6341+
le16_to_cpu(req->DataOffset));
6342+
63486343
rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length);
63496344
if (rpc_resp) {
63506345
if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
@@ -6489,22 +6484,16 @@ int smb2_write(struct ksmbd_work *work)
64896484

64906485
if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
64916486
req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
6492-
if (le16_to_cpu(req->DataOffset) ==
6493-
offsetof(struct smb2_write_req, Buffer)) {
6494-
data_buf = (char *)&req->Buffer[0];
6495-
} else {
6496-
if ((u64)le16_to_cpu(req->DataOffset) + length >
6497-
get_rfc1002_len(work->request_buf)) {
6498-
pr_err("invalid write data offset %u, smb_len %u\n",
6499-
le16_to_cpu(req->DataOffset),
6500-
get_rfc1002_len(work->request_buf));
6501-
err = -EINVAL;
6502-
goto out;
6503-
}
6504-
6505-
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
6506-
le16_to_cpu(req->DataOffset));
6487+
if ((u64)le16_to_cpu(req->DataOffset) + length >
6488+
get_rfc1002_len(work->request_buf)) {
6489+
pr_err("invalid write data offset %u, smb_len %u\n",
6490+
le16_to_cpu(req->DataOffset),
6491+
get_rfc1002_len(work->request_buf));
6492+
err = -EINVAL;
6493+
goto out;
65076494
}
6495+
data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
6496+
le16_to_cpu(req->DataOffset));
65086497

65096498
ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
65106499
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)

0 commit comments

Comments
 (0)