@@ -915,10 +915,30 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
if (!utf16_path)
return -ENOMEM;
+ len = sizeof(ea) + ea_name_len + ea_value_len + 1;
+
memset(rqst, 0, sizeof(rqst));
resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
memset(rsp_iov, 0, sizeof(rsp_iov));
+ /*
+ * Make sure we have enough space to store the new EA.
+ */
+ rc = smb2_query_info_compound(xid, tcon, utf16_path,
+ FILE_READ_EA,
+ FILE_FULL_EA_INFORMATION,
+ SMB2_O_INFO_FILE,
+ SMB2_MAX_EA_BUF,
+ &rsp_iov[0], &resp_buftype[0], cifs_sb);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ resp_buftype[0] = CIFS_NO_BUFFER;
+ rsp_iov[0].iov_base = NULL;
+ if (len + rsp_iov[0].iov_len > SMB2_MAX_EA_BUF) {
+ rc = -ERANGE;
+ goto sea_exit;
+ }
+
+
/* Open */
memset(&open_iov, 0, sizeof(open_iov));
rqst[0].rq_iov = open_iov;
When setting/adding an EA, check how much EA space we arelady have on this file and make sure that if we add this new EA that the result will still fit inside a SMB2_MAX_EA_BUF. In the client we limit the maximum buffer to currently 64k. When we store these on the server we have no way of knowing if/what the servers limit for EAs are. They could be, and often are, much larger than 64k. This change is to return an error and not set the EA if we suspect that the result could overflow the buffer. This prevents the very annoying behaviour that we can add EAs well beyond the maximum clientside buffer and thus, at that stage make it is no longer query or list the existing EAs any more. The check for overflow is overly conservative : if (len + rsp_iov[0].iov_len > SMB2_MAX_EA_BUF) { since the actual size of the EAs are a bit less than iov_len but this is simpler to read. The only effect of this is that we will stop allowing adding new EAs ~100 bytes earlier than stricly needed which does not matter much for 64k buffers. Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> --- fs/cifs/smb2ops.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)