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