@@ -3122,7 +3122,7 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
3122
3122
struct kvec close_iov [1 ];
3123
3123
struct smb2_ioctl_rsp * ioctl_rsp ;
3124
3124
struct reparse_data_buffer * reparse_buf ;
3125
- u32 plen ;
3125
+ u32 off , count , len ;
3126
3126
3127
3127
cifs_dbg (FYI , "%s: path: %s\n" , __func__ , full_path );
3128
3128
@@ -3202,16 +3202,22 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
3202
3202
*/
3203
3203
if (rc == 0 ) {
3204
3204
/* See MS-FSCC 2.3.23 */
3205
+ off = le32_to_cpu (ioctl_rsp -> OutputOffset );
3206
+ count = le32_to_cpu (ioctl_rsp -> OutputCount );
3207
+ if (check_add_overflow (off , count , & len ) ||
3208
+ len > rsp_iov [1 ].iov_len ) {
3209
+ cifs_tcon_dbg (VFS , "%s: invalid ioctl: off=%d count=%d\n" ,
3210
+ __func__ , off , count );
3211
+ rc = - EIO ;
3212
+ goto query_rp_exit ;
3213
+ }
3205
3214
3206
- reparse_buf = (struct reparse_data_buffer * )
3207
- ((char * )ioctl_rsp +
3208
- le32_to_cpu (ioctl_rsp -> OutputOffset ));
3209
- plen = le32_to_cpu (ioctl_rsp -> OutputCount );
3210
-
3211
- if (plen + le32_to_cpu (ioctl_rsp -> OutputOffset ) >
3212
- rsp_iov [1 ].iov_len ) {
3213
- cifs_tcon_dbg (FYI , "srv returned invalid ioctl len: %d\n" ,
3214
- plen );
3215
+ reparse_buf = (void * )((u8 * )ioctl_rsp + off );
3216
+ len = sizeof (* reparse_buf );
3217
+ if (count < len ||
3218
+ count < le16_to_cpu (reparse_buf -> ReparseDataLength ) + len ) {
3219
+ cifs_tcon_dbg (VFS , "%s: invalid ioctl: off=%d count=%d\n" ,
3220
+ __func__ , off , count );
3215
3221
rc = - EIO ;
3216
3222
goto query_rp_exit ;
3217
3223
}
0 commit comments