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