| From 444c9a450d980a16d6817ef6e8ec33d9828de301 Mon Sep 17 00:00:00 2001 |
| From: Ronnie Sahlberg <lsahlber@redhat.com> |
| Date: Thu, 13 Feb 2020 12:14:47 +1000 |
| Subject: [PATCH] cifs: make sure we do not overflow the max EA buffer size |
| |
| commit 85db6b7ae65f33be4bb44f1c28261a3faa126437 upstream. |
| |
| RHBZ: 1752437 |
| |
| Before we add a new EA we should check that this will not overflow |
| the maximum buffer we have available to read the EAs back. |
| Otherwise we can get into a situation where the EAs are so big that |
| we can not read them back to the client and thus we can not list EAs |
| anymore or delete them. |
| |
| Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> |
| Signed-off-by: Steve French <stfrench@microsoft.com> |
| CC: Stable <stable@vger.kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c |
| index 20360dc77f24..597d50d23fbe 100644 |
| --- a/fs/cifs/smb2ops.c |
| +++ b/fs/cifs/smb2ops.c |
| @@ -1078,7 +1078,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, |
| void *data[1]; |
| struct smb2_file_full_ea_info *ea = NULL; |
| struct kvec close_iov[1]; |
| - int rc; |
| + struct smb2_query_info_rsp *rsp; |
| + int rc, used_len = 0; |
| |
| if (smb3_encryption_required(tcon)) |
| flags |= CIFS_TRANSFORM_REQ; |
| @@ -1101,6 +1102,38 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, |
| cifs_sb); |
| if (rc == -ENODATA) |
| goto sea_exit; |
| + } else { |
| + /* If we are adding a attribute we should first check |
| + * if there will be enough space available to store |
| + * the new EA. If not we should not add it since we |
| + * would not be able to even read the EAs back. |
| + */ |
| + rc = smb2_query_info_compound(xid, tcon, utf16_path, |
| + FILE_READ_EA, |
| + FILE_FULL_EA_INFORMATION, |
| + SMB2_O_INFO_FILE, |
| + CIFSMaxBufSize - |
| + MAX_SMB2_CREATE_RESPONSE_SIZE - |
| + MAX_SMB2_CLOSE_RESPONSE_SIZE, |
| + &rsp_iov[1], &resp_buftype[1], cifs_sb); |
| + if (rc == 0) { |
| + rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; |
| + used_len = le32_to_cpu(rsp->OutputBufferLength); |
| + } |
| + free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); |
| + resp_buftype[1] = CIFS_NO_BUFFER; |
| + memset(&rsp_iov[1], 0, sizeof(rsp_iov[1])); |
| + rc = 0; |
| + |
| + /* Use a fudge factor of 256 bytes in case we collide |
| + * with a different set_EAs command. |
| + */ |
| + if(CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE - |
| + MAX_SMB2_CLOSE_RESPONSE_SIZE - 256 < |
| + used_len + ea_name_len + ea_value_len + 1) { |
| + rc = -ENOSPC; |
| + goto sea_exit; |
| + } |
| } |
| } |
| |
| -- |
| 2.7.4 |
| |