@@ -3001,7 +3001,7 @@ static int smb2_query_reparse_point(const unsigned int xid,
3001
3001
struct kvec * rsp_iov ;
3002
3002
struct smb2_ioctl_rsp * ioctl_rsp ;
3003
3003
struct reparse_data_buffer * reparse_buf ;
3004
- u32 plen ;
3004
+ u32 off , count , len ;
3005
3005
3006
3006
cifs_dbg (FYI , "%s: path: %s\n" , __func__ , full_path );
3007
3007
@@ -3082,16 +3082,22 @@ static int smb2_query_reparse_point(const unsigned int xid,
3082
3082
*/
3083
3083
if (rc == 0 ) {
3084
3084
/* See MS-FSCC 2.3.23 */
3085
+ off = le32_to_cpu (ioctl_rsp -> OutputOffset );
3086
+ count = le32_to_cpu (ioctl_rsp -> OutputCount );
3087
+ if (check_add_overflow (off , count , & len ) ||
3088
+ len > rsp_iov [1 ].iov_len ) {
3089
+ cifs_tcon_dbg (VFS , "%s: invalid ioctl: off=%d count=%d\n" ,
3090
+ __func__ , off , count );
3091
+ rc = - EIO ;
3092
+ goto query_rp_exit ;
3093
+ }
3085
3094
3086
- reparse_buf = (struct reparse_data_buffer * )
3087
- ((char * )ioctl_rsp +
3088
- le32_to_cpu (ioctl_rsp -> OutputOffset ));
3089
- plen = le32_to_cpu (ioctl_rsp -> OutputCount );
3090
-
3091
- if (plen + le32_to_cpu (ioctl_rsp -> OutputOffset ) >
3092
- rsp_iov [1 ].iov_len ) {
3093
- cifs_tcon_dbg (FYI , "srv returned invalid ioctl len: %d\n" ,
3094
- plen );
3095
+ reparse_buf = (void * )((u8 * )ioctl_rsp + off );
3096
+ len = sizeof (* reparse_buf );
3097
+ if (count < len ||
3098
+ count < le16_to_cpu (reparse_buf -> ReparseDataLength ) + len ) {
3099
+ cifs_tcon_dbg (VFS , "%s: invalid ioctl: off=%d count=%d\n" ,
3100
+ __func__ , off , count );
3095
3101
rc = - EIO ;
3096
3102
goto query_rp_exit ;
3097
3103
}
0 commit comments