aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/i2o/i2o_config.c
diff options
context:
space:
mode:
authorVasily Averin <vvs@sw.ru>2007-07-17 07:04:24 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:06 -0400
commit1725d71d992f5947bdd5b4f9a30fe8a05571fe66 (patch)
tree3f75479254b5ce59fd9e47a4603c2e01e1c946e3 /drivers/message/i2o/i2o_config.c
parent2bf68a3699601bd3e53b4efce7f2d780e243aa35 (diff)
i2o_cfg_passthru cleanup
This patch fixes a number of issues in i2o_cfg_passthru{,32}: - i2o_msg_get_wait() return vaile is not checked; - i2o_message memory leaks on error paths; - infinite loop to sg_list_cleanup in passthru32 It's important issue because of i2o_cfg_passthru is used by raidutils for monitorig controllers state, and in case of memory shortage it leads to the node crash or disk IO stall. [akpm@linux-foundation.org: fix null-ptr deref] Signed-off-by: Vasily Averin <vvs@sw.ru> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Markus Lidel <Markus.Lidel@shadowconnect.com> Acked-by: Kirill Korotaev <dev@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/message/i2o/i2o_config.c')
-rw-r--r--drivers/message/i2o/i2o_config.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 8ba275a12773..84e046e94f5f 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -554,8 +554,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
554 return -ENXIO; 554 return -ENXIO;
555 } 555 }
556 556
557 msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
558
559 sb = c->status_block.virt; 557 sb = c->status_block.virt;
560 558
561 if (get_user(size, &user_msg[0])) { 559 if (get_user(size, &user_msg[0])) {
@@ -573,24 +571,30 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
573 571
574 size <<= 2; // Convert to bytes 572 size <<= 2; // Convert to bytes
575 573
574 msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
575 if (IS_ERR(msg))
576 return PTR_ERR(msg);
577
578 rcode = -EFAULT;
576 /* Copy in the user's I2O command */ 579 /* Copy in the user's I2O command */
577 if (copy_from_user(msg, user_msg, size)) { 580 if (copy_from_user(msg, user_msg, size)) {
578 osm_warn("unable to copy user message\n"); 581 osm_warn("unable to copy user message\n");
579 return -EFAULT; 582 goto out;
580 } 583 }
581 i2o_dump_message(msg); 584 i2o_dump_message(msg);
582 585
583 if (get_user(reply_size, &user_reply[0]) < 0) 586 if (get_user(reply_size, &user_reply[0]) < 0)
584 return -EFAULT; 587 goto out;
585 588
586 reply_size >>= 16; 589 reply_size >>= 16;
587 reply_size <<= 2; 590 reply_size <<= 2;
588 591
592 rcode = -ENOMEM;
589 reply = kzalloc(reply_size, GFP_KERNEL); 593 reply = kzalloc(reply_size, GFP_KERNEL);
590 if (!reply) { 594 if (!reply) {
591 printk(KERN_WARNING "%s: Could not allocate reply buffer\n", 595 printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
592 c->name); 596 c->name);
593 return -ENOMEM; 597 goto out;
594 } 598 }
595 599
596 sg_offset = (msg->u.head[0] >> 4) & 0x0f; 600 sg_offset = (msg->u.head[0] >> 4) & 0x0f;
@@ -661,13 +665,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
661 } 665 }
662 666
663 rcode = i2o_msg_post_wait(c, msg, 60); 667 rcode = i2o_msg_post_wait(c, msg, 60);
668 msg = NULL;
664 if (rcode) { 669 if (rcode) {
665 reply[4] = ((u32) rcode) << 24; 670 reply[4] = ((u32) rcode) << 24;
666 goto sg_list_cleanup; 671 goto sg_list_cleanup;
667 } 672 }
668 673
669 if (sg_offset) { 674 if (sg_offset) {
670 u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE]; 675 u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE];
671 /* Copy back the Scatter Gather buffers back to user space */ 676 /* Copy back the Scatter Gather buffers back to user space */
672 u32 j; 677 u32 j;
673 // TODO 64bit fix 678 // TODO 64bit fix
@@ -675,7 +680,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
675 int sg_size; 680 int sg_size;
676 681
677 // re-acquire the original message to handle correctly the sg copy operation 682 // re-acquire the original message to handle correctly the sg copy operation
678 memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); 683 memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
679 // get user msg size in u32s 684 // get user msg size in u32s
680 if (get_user(size, &user_msg[0])) { 685 if (get_user(size, &user_msg[0])) {
681 rcode = -EFAULT; 686 rcode = -EFAULT;
@@ -684,7 +689,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
684 size = size >> 16; 689 size = size >> 16;
685 size *= 4; 690 size *= 4;
686 /* Copy in the user's I2O command */ 691 /* Copy in the user's I2O command */
687 if (copy_from_user(msg, user_msg, size)) { 692 if (copy_from_user(rmsg, user_msg, size)) {
688 rcode = -EFAULT; 693 rcode = -EFAULT;
689 goto sg_list_cleanup; 694 goto sg_list_cleanup;
690 } 695 }
@@ -692,7 +697,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
692 (size - sg_offset * 4) / sizeof(struct sg_simple_element); 697 (size - sg_offset * 4) / sizeof(struct sg_simple_element);
693 698
694 // TODO 64bit fix 699 // TODO 64bit fix
695 sg = (struct sg_simple_element *)(msg + sg_offset); 700 sg = (struct sg_simple_element *)(rmsg + sg_offset);
696 for (j = 0; j < sg_count; j++) { 701 for (j = 0; j < sg_count; j++) {
697 /* Copy out the SG list to user's buffer if necessary */ 702 /* Copy out the SG list to user's buffer if necessary */
698 if (! 703 if (!
@@ -714,7 +719,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
714 } 719 }
715 } 720 }
716 721
717 sg_list_cleanup: 722sg_list_cleanup:
718 /* Copy back the reply to user space */ 723 /* Copy back the reply to user space */
719 if (reply_size) { 724 if (reply_size) {
720 // we wrote our own values for context - now restore the user supplied ones 725 // we wrote our own values for context - now restore the user supplied ones
@@ -723,7 +728,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
723 "%s: Could not copy message context FROM user\n", 728 "%s: Could not copy message context FROM user\n",
724 c->name); 729 c->name);
725 rcode = -EFAULT; 730 rcode = -EFAULT;
726 goto sg_list_cleanup;
727 } 731 }
728 if (copy_to_user(user_reply, reply, reply_size)) { 732 if (copy_to_user(user_reply, reply, reply_size)) {
729 printk(KERN_WARNING 733 printk(KERN_WARNING
@@ -731,12 +735,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
731 rcode = -EFAULT; 735 rcode = -EFAULT;
732 } 736 }
733 } 737 }
734
735 for (i = 0; i < sg_index; i++) 738 for (i = 0; i < sg_index; i++)
736 i2o_dma_free(&c->pdev->dev, &sg_list[i]); 739 i2o_dma_free(&c->pdev->dev, &sg_list[i]);
737 740
738 cleanup: 741cleanup:
739 kfree(reply); 742 kfree(reply);
743out:
744 if (msg)
745 i2o_msg_nop(c, msg);
740 return rcode; 746 return rcode;
741} 747}
742 748
@@ -793,8 +799,6 @@ static int i2o_cfg_passthru(unsigned long arg)
793 return -ENXIO; 799 return -ENXIO;
794 } 800 }
795 801
796 msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
797
798 sb = c->status_block.virt; 802 sb = c->status_block.virt;
799 803
800 if (get_user(size, &user_msg[0])) 804 if (get_user(size, &user_msg[0]))
@@ -810,12 +814,17 @@ static int i2o_cfg_passthru(unsigned long arg)
810 814
811 size <<= 2; // Convert to bytes 815 size <<= 2; // Convert to bytes
812 816
817 msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
818 if (IS_ERR(msg))
819 return PTR_ERR(msg);
820
821 rcode = -EFAULT;
813 /* Copy in the user's I2O command */ 822 /* Copy in the user's I2O command */
814 if (copy_from_user(msg, user_msg, size)) 823 if (copy_from_user(msg, user_msg, size))
815 return -EFAULT; 824 goto out;
816 825
817 if (get_user(reply_size, &user_reply[0]) < 0) 826 if (get_user(reply_size, &user_reply[0]) < 0)
818 return -EFAULT; 827 goto out;
819 828
820 reply_size >>= 16; 829 reply_size >>= 16;
821 reply_size <<= 2; 830 reply_size <<= 2;
@@ -824,7 +833,8 @@ static int i2o_cfg_passthru(unsigned long arg)
824 if (!reply) { 833 if (!reply) {
825 printk(KERN_WARNING "%s: Could not allocate reply buffer\n", 834 printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
826 c->name); 835 c->name);
827 return -ENOMEM; 836 rcode = -ENOMEM;
837 goto out;
828 } 838 }
829 839
830 sg_offset = (msg->u.head[0] >> 4) & 0x0f; 840 sg_offset = (msg->u.head[0] >> 4) & 0x0f;
@@ -891,13 +901,14 @@ static int i2o_cfg_passthru(unsigned long arg)
891 } 901 }
892 902
893 rcode = i2o_msg_post_wait(c, msg, 60); 903 rcode = i2o_msg_post_wait(c, msg, 60);
904 msg = NULL;
894 if (rcode) { 905 if (rcode) {
895 reply[4] = ((u32) rcode) << 24; 906 reply[4] = ((u32) rcode) << 24;
896 goto sg_list_cleanup; 907 goto sg_list_cleanup;
897 } 908 }
898 909
899 if (sg_offset) { 910 if (sg_offset) {
900 u32 msg[128]; 911 u32 rmsg[128];
901 /* Copy back the Scatter Gather buffers back to user space */ 912 /* Copy back the Scatter Gather buffers back to user space */
902 u32 j; 913 u32 j;
903 // TODO 64bit fix 914 // TODO 64bit fix
@@ -905,7 +916,7 @@ static int i2o_cfg_passthru(unsigned long arg)
905 int sg_size; 916 int sg_size;
906 917
907 // re-acquire the original message to handle correctly the sg copy operation 918 // re-acquire the original message to handle correctly the sg copy operation
908 memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); 919 memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
909 // get user msg size in u32s 920 // get user msg size in u32s
910 if (get_user(size, &user_msg[0])) { 921 if (get_user(size, &user_msg[0])) {
911 rcode = -EFAULT; 922 rcode = -EFAULT;
@@ -914,7 +925,7 @@ static int i2o_cfg_passthru(unsigned long arg)
914 size = size >> 16; 925 size = size >> 16;
915 size *= 4; 926 size *= 4;
916 /* Copy in the user's I2O command */ 927 /* Copy in the user's I2O command */
917 if (copy_from_user(msg, user_msg, size)) { 928 if (copy_from_user(rmsg, user_msg, size)) {
918 rcode = -EFAULT; 929 rcode = -EFAULT;
919 goto sg_list_cleanup; 930 goto sg_list_cleanup;
920 } 931 }
@@ -922,7 +933,7 @@ static int i2o_cfg_passthru(unsigned long arg)
922 (size - sg_offset * 4) / sizeof(struct sg_simple_element); 933 (size - sg_offset * 4) / sizeof(struct sg_simple_element);
923 934
924 // TODO 64bit fix 935 // TODO 64bit fix
925 sg = (struct sg_simple_element *)(msg + sg_offset); 936 sg = (struct sg_simple_element *)(rmsg + sg_offset);
926 for (j = 0; j < sg_count; j++) { 937 for (j = 0; j < sg_count; j++) {
927 /* Copy out the SG list to user's buffer if necessary */ 938 /* Copy out the SG list to user's buffer if necessary */
928 if (! 939 if (!
@@ -944,7 +955,7 @@ static int i2o_cfg_passthru(unsigned long arg)
944 } 955 }
945 } 956 }
946 957
947 sg_list_cleanup: 958sg_list_cleanup:
948 /* Copy back the reply to user space */ 959 /* Copy back the reply to user space */
949 if (reply_size) { 960 if (reply_size) {
950 // we wrote our own values for context - now restore the user supplied ones 961 // we wrote our own values for context - now restore the user supplied ones
@@ -964,8 +975,11 @@ static int i2o_cfg_passthru(unsigned long arg)
964 for (i = 0; i < sg_index; i++) 975 for (i = 0; i < sg_index; i++)
965 kfree(sg_list[i]); 976 kfree(sg_list[i]);
966 977
967 cleanup: 978cleanup:
968 kfree(reply); 979 kfree(reply);
980out:
981 if (msg)
982 i2o_msg_nop(c, msg);
969 return rcode; 983 return rcode;
970} 984}
971#endif 985#endif