aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/capi/capiutil.c
diff options
context:
space:
mode:
authorKarsten Keil <kkeil@suse.de>2007-02-28 23:13:50 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-01 17:53:39 -0500
commit17f0cd2f350b90b28301e27fe0e39f34bfe7e730 (patch)
tree6baba85d4f3b83398dc5a412b328bfcef1633548 /drivers/isdn/capi/capiutil.c
parent34bbd704051c9d053d69e90569a3a2365f4c7b50 (diff)
[PATCH] Fix buffer overflow and races in capi debug functions
The CAPI trace debug functions were using a fixed size buffer, which can be overflowed if wrong formatted CAPI messages were sent to the kernel capi layer. The code was also not protected against multiple callers. This fix bug 8028. Additionally the patch make the CAPI trace functions optional. Signed-off-by: Karsten Keil <kkeil@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/isdn/capi/capiutil.c')
-rw-r--r--drivers/isdn/capi/capiutil.c254
1 files changed, 208 insertions, 46 deletions
diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c
index c1b21552fc03..ad1e2702c2d1 100644
--- a/drivers/isdn/capi/capiutil.c
+++ b/drivers/isdn/capi/capiutil.c
@@ -648,6 +648,9 @@ char *capi_cmd2str(u8 cmd, u8 subcmd)
648 648
649 649
650/*-------------------------------------------------------*/ 650/*-------------------------------------------------------*/
651
652#ifdef CONFIG_CAPI_TRACE
653
651/*-------------------------------------------------------*/ 654/*-------------------------------------------------------*/
652 655
653static char *pnames[] = 656static char *pnames[] =
@@ -703,44 +706,77 @@ static char *pnames[] =
703}; 706};
704 707
705 708
706static char buf[8192];
707static char *p = NULL;
708 709
709#include <stdarg.h> 710#include <stdarg.h>
710 711
711/*-------------------------------------------------------*/ 712/*-------------------------------------------------------*/
712static void bufprint(char *fmt,...) 713static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...)
713{ 714{
714 va_list f; 715 va_list f;
716 size_t n,r;
717
718 if (!cdb)
719 return NULL;
715 va_start(f, fmt); 720 va_start(f, fmt);
716 vsprintf(p, fmt, f); 721 r = cdb->size - cdb->pos;
722 n = vsnprintf(cdb->p, r, fmt, f);
717 va_end(f); 723 va_end(f);
718 p += strlen(p); 724 if (n >= r) {
725 /* truncated, need bigger buffer */
726 size_t ns = 2 * cdb->size;
727 u_char *nb;
728
729 while ((ns - cdb->pos) <= n)
730 ns *= 2;
731 nb = kmalloc(ns, GFP_ATOMIC);
732 if (!nb) {
733 cdebbuf_free(cdb);
734 return NULL;
735 }
736 memcpy(nb, cdb->buf, cdb->pos);
737 kfree(cdb->buf);
738 nb[cdb->pos] = 0;
739 cdb->buf = nb;
740 cdb->p = cdb->buf + cdb->pos;
741 cdb->size = ns;
742 va_start(f, fmt);
743 r = cdb->size - cdb->pos;
744 n = vsnprintf(cdb->p, r, fmt, f);
745 va_end(f);
746 }
747 cdb->p += n;
748 cdb->pos += n;
749 return cdb;
719} 750}
720 751
721static void printstructlen(u8 * m, unsigned len) 752static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len)
722{ 753{
723 unsigned hex = 0; 754 unsigned hex = 0;
755
756 if (!cdb)
757 return NULL;
724 for (; len; len--, m++) 758 for (; len; len--, m++)
725 if (isalnum(*m) || *m == ' ') { 759 if (isalnum(*m) || *m == ' ') {
726 if (hex) 760 if (hex)
727 bufprint(">"); 761 cdb = bufprint(cdb, ">");
728 bufprint("%c", *m); 762 cdb = bufprint(cdb, "%c", *m);
729 hex = 0; 763 hex = 0;
730 } else { 764 } else {
731 if (!hex) 765 if (!hex)
732 bufprint("<%02x", *m); 766 cdb = bufprint(cdb, "<%02x", *m);
733 else 767 else
734 bufprint(" %02x", *m); 768 cdb = bufprint(cdb, " %02x", *m);
735 hex = 1; 769 hex = 1;
736 } 770 }
737 if (hex) 771 if (hex)
738 bufprint(">"); 772 cdb = bufprint(cdb, ">");
773 return cdb;
739} 774}
740 775
741static void printstruct(u8 * m) 776static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m)
742{ 777{
743 unsigned len; 778 unsigned len;
779
744 if (m[0] != 0xff) { 780 if (m[0] != 0xff) {
745 len = m[0]; 781 len = m[0];
746 m += 1; 782 m += 1;
@@ -748,42 +784,45 @@ static void printstruct(u8 * m)
748 len = ((u16 *) (m + 1))[0]; 784 len = ((u16 *) (m + 1))[0];
749 m += 3; 785 m += 3;
750 } 786 }
751 printstructlen(m, len); 787 cdb = printstructlen(cdb, m, len);
788 return cdb;
752} 789}
753 790
754/*-------------------------------------------------------*/ 791/*-------------------------------------------------------*/
755#define NAME (pnames[cmsg->par[cmsg->p]]) 792#define NAME (pnames[cmsg->par[cmsg->p]])
756 793
757static void protocol_message_2_pars(_cmsg * cmsg, int level) 794static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
758{ 795{
759 for (; TYP != _CEND; cmsg->p++) { 796 for (; TYP != _CEND; cmsg->p++) {
760 int slen = 29 + 3 - level; 797 int slen = 29 + 3 - level;
761 int i; 798 int i;
762 799
763 bufprint(" "); 800 if (!cdb)
801 return NULL;
802 cdb = bufprint(cdb, " ");
764 for (i = 0; i < level - 1; i++) 803 for (i = 0; i < level - 1; i++)
765 bufprint(" "); 804 cdb = bufprint(cdb, " ");
766 805
767 switch (TYP) { 806 switch (TYP) {
768 case _CBYTE: 807 case _CBYTE:
769 bufprint("%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); 808 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
770 cmsg->l++; 809 cmsg->l++;
771 break; 810 break;
772 case _CWORD: 811 case _CWORD:
773 bufprint("%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); 812 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
774 cmsg->l += 2; 813 cmsg->l += 2;
775 break; 814 break;
776 case _CDWORD: 815 case _CDWORD:
777 bufprint("%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); 816 cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
778 cmsg->l += 4; 817 cmsg->l += 4;
779 break; 818 break;
780 case _CSTRUCT: 819 case _CSTRUCT:
781 bufprint("%-*s = ", slen, NAME); 820 cdb = bufprint(cdb, "%-*s = ", slen, NAME);
782 if (cmsg->m[cmsg->l] == '\0') 821 if (cmsg->m[cmsg->l] == '\0')
783 bufprint("default"); 822 cdb = bufprint(cdb, "default");
784 else 823 else
785 printstruct(cmsg->m + cmsg->l); 824 cdb = printstruct(cdb, cmsg->m + cmsg->l);
786 bufprint("\n"); 825 cdb = bufprint(cdb, "\n");
787 if (cmsg->m[cmsg->l] != 0xff) 826 if (cmsg->m[cmsg->l] != 0xff)
788 cmsg->l += 1 + cmsg->m[cmsg->l]; 827 cmsg->l += 1 + cmsg->m[cmsg->l];
789 else 828 else
@@ -794,61 +833,184 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level)
794 case _CMSTRUCT: 833 case _CMSTRUCT:
795/*----- Metastruktur 0 -----*/ 834/*----- Metastruktur 0 -----*/
796 if (cmsg->m[cmsg->l] == '\0') { 835 if (cmsg->m[cmsg->l] == '\0') {
797 bufprint("%-*s = default\n", slen, NAME); 836 cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
798 cmsg->l++; 837 cmsg->l++;
799 jumpcstruct(cmsg); 838 jumpcstruct(cmsg);
800 } else { 839 } else {
801 char *name = NAME; 840 char *name = NAME;
802 unsigned _l = cmsg->l; 841 unsigned _l = cmsg->l;
803 bufprint("%-*s\n", slen, name); 842 cdb = bufprint(cdb, "%-*s\n", slen, name);
804 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; 843 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
805 cmsg->p++; 844 cmsg->p++;
806 protocol_message_2_pars(cmsg, level + 1); 845 cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
807 } 846 }
808 break; 847 break;
809 } 848 }
810 } 849 }
850 return cdb;
811} 851}
812/*-------------------------------------------------------*/ 852/*-------------------------------------------------------*/
813char *capi_message2str(u8 * msg) 853
854static _cdebbuf *g_debbuf;
855static u_long g_debbuf_lock;
856static _cmsg *g_cmsg;
857
858_cdebbuf *cdebbuf_alloc(void)
814{ 859{
860 _cdebbuf *cdb;
861
862 if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
863 cdb = g_debbuf;
864 goto init;
865 } else
866 cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
867 if (!cdb)
868 return NULL;
869 cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
870 if (!cdb->buf) {
871 kfree(cdb);
872 return NULL;
873 }
874 cdb->size = CDEBUG_SIZE;
875init:
876 cdb->buf[0] = 0;
877 cdb->p = cdb->buf;
878 cdb->pos = 0;
879 return cdb;
880}
815 881
816 _cmsg cmsg; 882void cdebbuf_free(_cdebbuf *cdb)
817 p = buf; 883{
818 p[0] = 0; 884 if (likely(cdb == g_debbuf)) {
885 test_and_clear_bit(1, &g_debbuf_lock);
886 return;
887 }
888 if (likely(cdb))
889 kfree(cdb->buf);
890 kfree(cdb);
891}
819 892
820 cmsg.m = msg;
821 cmsg.l = 8;
822 cmsg.p = 0;
823 byteTRcpy(cmsg.m + 4, &cmsg.Command);
824 byteTRcpy(cmsg.m + 5, &cmsg.Subcommand);
825 cmsg.par = cpars[command_2_index(cmsg.Command, cmsg.Subcommand)];
826 893
827 bufprint("%-26s ID=%03d #0x%04x LEN=%04d\n", 894_cdebbuf *capi_message2str(u8 * msg)
828 mnames[command_2_index(cmsg.Command, cmsg.Subcommand)], 895{
896 _cdebbuf *cdb;
897 _cmsg *cmsg;
898
899 cdb = cdebbuf_alloc();
900 if (unlikely(!cdb))
901 return NULL;
902 if (likely(cdb == g_debbuf))
903 cmsg = g_cmsg;
904 else
905 cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
906 if (unlikely(!cmsg)) {
907 cdebbuf_free(cdb);
908 return NULL;
909 }
910 cmsg->m = msg;
911 cmsg->l = 8;
912 cmsg->p = 0;
913 byteTRcpy(cmsg->m + 4, &cmsg->Command);
914 byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
915 cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
916
917 cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
918 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
829 ((unsigned short *) msg)[1], 919 ((unsigned short *) msg)[1],
830 ((unsigned short *) msg)[3], 920 ((unsigned short *) msg)[3],
831 ((unsigned short *) msg)[0]); 921 ((unsigned short *) msg)[0]);
832 922
833 protocol_message_2_pars(&cmsg, 1); 923 cdb = protocol_message_2_pars(cdb, cmsg, 1);
834 return buf; 924 if (unlikely(cmsg != g_cmsg))
925 kfree(cmsg);
926 return cdb;
835} 927}
836 928
837char *capi_cmsg2str(_cmsg * cmsg) 929_cdebbuf *capi_cmsg2str(_cmsg * cmsg)
838{ 930{
839 p = buf; 931 _cdebbuf *cdb;
840 p[0] = 0; 932
933 cdb = cdebbuf_alloc();
934 if (!cdb)
935 return NULL;
841 cmsg->l = 8; 936 cmsg->l = 8;
842 cmsg->p = 0; 937 cmsg->p = 0;
843 bufprint("%s ID=%03d #0x%04x LEN=%04d\n", 938 cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n",
844 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], 939 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
845 ((u16 *) cmsg->m)[1], 940 ((u16 *) cmsg->m)[1],
846 ((u16 *) cmsg->m)[3], 941 ((u16 *) cmsg->m)[3],
847 ((u16 *) cmsg->m)[0]); 942 ((u16 *) cmsg->m)[0]);
848 protocol_message_2_pars(cmsg, 1); 943 cdb = protocol_message_2_pars(cdb, cmsg, 1);
849 return buf; 944 return cdb;
850} 945}
851 946
947int __init cdebug_init(void)
948{
949 g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL);
950 if (!g_cmsg)
951 return ENOMEM;
952 g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
953 if (!g_debbuf) {
954 kfree(g_cmsg);
955 return ENOMEM;
956 }
957 g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
958 if (!g_debbuf->buf) {
959 kfree(g_cmsg);
960 kfree(g_debbuf);
961 return ENOMEM;;
962 }
963 g_debbuf->size = CDEBUG_GSIZE;
964 g_debbuf->buf[0] = 0;
965 g_debbuf->p = g_debbuf->buf;
966 g_debbuf->pos = 0;
967 return 0;
968}
969
970void __exit cdebug_exit(void)
971{
972 if (g_debbuf)
973 kfree(g_debbuf->buf);
974 kfree(g_debbuf);
975 kfree(g_cmsg);
976}
977
978#else /* !CONFIG_CAPI_TRACE */
979
980static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
981
982_cdebbuf *capi_message2str(u8 * msg)
983{
984 return &g_debbuf;
985}
986
987_cdebbuf *capi_cmsg2str(_cmsg * cmsg)
988{
989 return &g_debbuf;
990}
991
992_cdebbuf *cdebbuf_alloc(void)
993{
994 return &g_debbuf;
995}
996
997void cdebbuf_free(_cdebbuf *cdb)
998{
999}
1000
1001int __init cdebug_init(void)
1002{
1003 return 0;
1004}
1005
1006void __exit cdebug_exit(void)
1007{
1008}
1009
1010#endif
1011
1012EXPORT_SYMBOL(cdebbuf_alloc);
1013EXPORT_SYMBOL(cdebbuf_free);
852EXPORT_SYMBOL(capi_cmsg2message); 1014EXPORT_SYMBOL(capi_cmsg2message);
853EXPORT_SYMBOL(capi_message2cmsg); 1015EXPORT_SYMBOL(capi_message2cmsg);
854EXPORT_SYMBOL(capi_cmsg_header); 1016EXPORT_SYMBOL(capi_cmsg_header);