1414#include <linux/mm.h>
1515#include <linux/moduleparam.h>
1616#include <linux/mutex.h>
17+ #include <linux/overflow.h>
1718#include <linux/pci.h>
1819#include <linux/scatterlist.h>
1920#include <linux/types.h>
@@ -366,7 +367,7 @@ static int encode_passthrough(struct qaic_device *qdev, void *trans, struct wrap
366367 if (in_trans -> hdr .len % 8 != 0 )
367368 return - EINVAL ;
368369
369- if (msg_hdr_len + in_trans -> hdr .len > QAIC_MANAGE_EXT_MSG_LENGTH )
370+ if (size_add ( msg_hdr_len , in_trans -> hdr .len ) > QAIC_MANAGE_EXT_MSG_LENGTH )
370371 return - ENOSPC ;
371372
372373 trans_wrapper = add_wrapper (wrappers ,
@@ -418,9 +419,12 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
418419 }
419420
420421 ret = get_user_pages_fast (xfer_start_addr , nr_pages , 0 , page_list );
421- if (ret < 0 || ret != nr_pages ) {
422- ret = - EFAULT ;
422+ if (ret < 0 )
423423 goto free_page_list ;
424+ if (ret != nr_pages ) {
425+ nr_pages = ret ;
426+ ret = - EFAULT ;
427+ goto put_pages ;
424428 }
425429
426430 sgt = kmalloc (sizeof (* sgt ), GFP_KERNEL );
@@ -557,11 +561,8 @@ static int encode_dma(struct qaic_device *qdev, void *trans, struct wrapper_list
557561 msg = & wrapper -> msg ;
558562 msg_hdr_len = le32_to_cpu (msg -> hdr .len );
559563
560- if (msg_hdr_len > (UINT_MAX - QAIC_MANAGE_EXT_MSG_LENGTH ))
561- return - EINVAL ;
562-
563564 /* There should be enough space to hold at least one ASP entry. */
564- if (msg_hdr_len + sizeof (* out_trans ) + sizeof (struct wire_addr_size_pair ) >
565+ if (size_add ( msg_hdr_len , sizeof (* out_trans ) + sizeof (struct wire_addr_size_pair ) ) >
565566 QAIC_MANAGE_EXT_MSG_LENGTH )
566567 return - ENOMEM ;
567568
@@ -634,7 +635,7 @@ static int encode_activate(struct qaic_device *qdev, void *trans, struct wrapper
634635 msg = & wrapper -> msg ;
635636 msg_hdr_len = le32_to_cpu (msg -> hdr .len );
636637
637- if (msg_hdr_len + sizeof (* out_trans ) > QAIC_MANAGE_MAX_MSG_LENGTH )
638+ if (size_add ( msg_hdr_len , sizeof (* out_trans ) ) > QAIC_MANAGE_MAX_MSG_LENGTH )
638639 return - ENOSPC ;
639640
640641 if (!in_trans -> queue_size )
@@ -718,7 +719,7 @@ static int encode_status(struct qaic_device *qdev, void *trans, struct wrapper_l
718719 msg = & wrapper -> msg ;
719720 msg_hdr_len = le32_to_cpu (msg -> hdr .len );
720721
721- if (msg_hdr_len + in_trans -> hdr .len > QAIC_MANAGE_MAX_MSG_LENGTH )
722+ if (size_add ( msg_hdr_len , in_trans -> hdr .len ) > QAIC_MANAGE_MAX_MSG_LENGTH )
722723 return - ENOSPC ;
723724
724725 trans_wrapper = add_wrapper (wrappers , sizeof (* trans_wrapper ));
@@ -748,7 +749,8 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
748749 int ret ;
749750 int i ;
750751
751- if (!user_msg -> count ) {
752+ if (!user_msg -> count ||
753+ user_msg -> len < sizeof (* trans_hdr )) {
752754 ret = - EINVAL ;
753755 goto out ;
754756 }
@@ -765,12 +767,13 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
765767 }
766768
767769 for (i = 0 ; i < user_msg -> count ; ++ i ) {
768- if (user_len >= user_msg -> len ) {
770+ if (user_len > user_msg -> len - sizeof ( * trans_hdr ) ) {
769771 ret = - EINVAL ;
770772 break ;
771773 }
772774 trans_hdr = (struct qaic_manage_trans_hdr * )(user_msg -> data + user_len );
773- if (user_len + trans_hdr -> len > user_msg -> len ) {
775+ if (trans_hdr -> len < sizeof (trans_hdr ) ||
776+ size_add (user_len , trans_hdr -> len ) > user_msg -> len ) {
774777 ret = - EINVAL ;
775778 break ;
776779 }
@@ -953,15 +956,23 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
953956 int ret ;
954957 int i ;
955958
956- if (msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH )
959+ if (msg_hdr_len < sizeof (* trans_hdr ) ||
960+ msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH )
957961 return - EINVAL ;
958962
959963 user_msg -> len = 0 ;
960964 user_msg -> count = le32_to_cpu (msg -> hdr .count );
961965
962966 for (i = 0 ; i < user_msg -> count ; ++ i ) {
967+ u32 hdr_len ;
968+
969+ if (msg_len > msg_hdr_len - sizeof (* trans_hdr ))
970+ return - EINVAL ;
971+
963972 trans_hdr = (struct wire_trans_hdr * )(msg -> data + msg_len );
964- if (msg_len + le32_to_cpu (trans_hdr -> len ) > msg_hdr_len )
973+ hdr_len = le32_to_cpu (trans_hdr -> len );
974+ if (hdr_len < sizeof (* trans_hdr ) ||
975+ size_add (msg_len , hdr_len ) > msg_hdr_len )
965976 return - EINVAL ;
966977
967978 switch (le32_to_cpu (trans_hdr -> type )) {
0 commit comments