cifs: make sure we do not overflow the max EA buffer size

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>
This commit is contained in:
Ronnie Sahlberg 2020-02-13 12:14:47 +10:00 коммит произвёл Steve French
Родитель 2c6251ad91
Коммит 85db6b7ae6
1 изменённых файлов: 34 добавлений и 1 удалений

Просмотреть файл

@ -1116,7 +1116,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;
@ -1139,6 +1140,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;
}
}
}