Uploaded image for project: 'Guacamole'
  1. Guacamole
  2. GUACAMOLE-614

Infinite loop caused by guac_iconv

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Open
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: 0.9.14
    • Fix Version/s: None
    • Component/s: guacamole-server
    • Labels:
      None
    • Environment:
      Guacd 0.9.14 with docker

      Description

      The encoding reader/writer may return zero, but the caller did not check zero value. That may cause the infinite loop when handle incorrect bytes. 

       See the line starts with /*** .

      int guac_iconv(guac_iconv_read* reader, const char** input, int in_remaining,
      guac_iconv_write* writer, char** output, int out_remaining) {
      
      while (in_remaining > 0 && out_remaining > 0) {
      
      int value;
      const char* read_start;
      char* write_start;
      
      /* Read character */
      read_start = *input;
      
      
      /*** reader may return value and not change input ***/
      value = reader(input, in_remaining);
      
      
      in_remaining -= *input - read_start;
      
      /* Write character */
      write_start = *output;
      
      /*** writer may return value and not change output ***/
      writer(output, out_remaining, value);
      
      
      out_remaining -= *output - write_start;
      
      /* Stop if null terminator reached */
      if (value == 0)
      return 1;
      
      }
      
      /* Null terminator not reached */
      return 0;
      }
      

       

      Analysis procedure

      1.  Find problem thread

      [root@jettydocker2 /]# ps -ef
      UID PID PPID C STIME TTY TIME CMD
      root 1 0 0 01:35 ? 00:00:40 /usr/local/sbin/guacd -b 0.0.0.0 -f
      root 464 1 0 02:51 ? 00:00:17 /usr/local/sbin/guacd -b 0.0.0.0 -f
      root 615 1 96 03:12 ? 01:23:39 /usr/local/sbin/guacd -b 0.0.0.0 -f
      root 703 1 0 03:38 ? 00:00:00 /usr/local/sbin/guacd -b 0.0.0.0 -f
      root 712 1 0 03:45 ? 00:00:15 /usr/local/sbin/guacd -b 0.0.0.0 -f
      root 728 1 0 04:01 ? 00:00:02 /usr/local/sbin/guacd -b 0.0.0.0 -f
      root 735 0 0 04:39 ? 00:00:00 bash
      root 747 735 0 04:39 ? 00:00:00 ps -ef
      
      [root@jettydocker2 /]# top -b -H -p 615
      top - 04:40:08 up 48 days, 2:56, 0 users, load average: 1.01, 1.11, 1.19
      Threads: 3 total, 1 running, 2 sleeping, 0 stopped, 0 zombie
      %Cpu(s): 25.4 us, 0.0 sy, 0.0 ni, 74.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
      KiB Mem : 8175596 total, 2269700 free, 1883596 used, 4022300 buff/cache
      KiB Swap: 0 total, 0 free, 0 used. 5914664 avail Mem
      
      PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
      619 root 20 0 1861008 23848 3444 R 99.9 0.3 83:56.87 guacd
      615 root 20 0 1861008 23848 3444 S 0.0 0.3 0:00.00 guacd
      621 root 20 0 1861008 23848 3444 S 0.0 0.3 0:00.02 guacd
      
      

       

      2. GDB anaylsis

      [root@jettydocker2 /]# gdb /usr/local/sbin/guacd 615
      
      GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-110.el7
      Copyright (C) 2013 Free Software Foundation, Inc.
      License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
      This is free software: you are free to change and redistribute it.
      There is NO WARRANTY, to the extent permitted by law. Type "show copying"
      and "show
      ....
      
      (gdb) info threads
      Id Target Id Frame
      3 Thread 0x7efffeffd700 (LWP 619) "guacd" guac_iconv (reader=0x7f00683e22fa <GUAC_READ_UTF8>, input=0x7efffefbc638, in_remaining=2,
      writer=0x7f00683e240f <GUAC_WRITE_UTF8>, output=0x7efffefbc630, out_remaining=1) at iconv.c:74
      2 Thread 0x7f0059ffb700 (LWP 621) "guacd" 0x00007f00721f9f3d in nanosleep () from /lib64/libpthread.so.0
      * 1 Thread 0x7f0043fff700 (LWP 615) "guacd" 0x00007f00721f3f97 in pthread_join () from /lib64/libpthread.so.0
      (gdb) t 3
      [Switching to thread 3 (Thread 0x7efffeffd700 (LWP 619))]
      #0 guac_iconv (reader=0x7f00683e22fa <GUAC_READ_UTF8>, input=0x7efffefbc638, in_remaining=2, writer=0x7f00683e240f <GUAC_WRITE_UTF8>,
      output=0x7efffefbc630, out_remaining=1) at iconv.c:74
      74 read_start = *input;
      
      (gdb) bt
      #0 guac_iconv (reader=0x7f00683e22fa <GUAC_READ_UTF8>, input=0x7efffefbc638, in_remaining=2, writer=0x7f00683e240f <GUAC_WRITE_UTF8>,
      output=0x7efffefbc630, out_remaining=1) at iconv.c:74
      #1 0x00007f00683df11d in guac_vnc_cut_text (client=0x7f007302e010, text=0x7f00600019d0 " #", <incomplete sequence \345\255>, textlen=5) at clipboard.c:135
      #2 0x00007f00681c97c7 in HandleRFBServerMessage () from /lib64/libvncclient.so.0
      #3 0x00007f00683e0c97 in guac_vnc_client_thread (data=0x7f005c00aee0) at vnc.c:350
      #4 0x00007f00721f2e25 in start_thread () from /lib64/libpthread.so.0
      #5 0x00007f0070aeabad in clone () from /lib64/libc.so.6
      
      (gdb) f 0
      #0 guac_iconv (reader=0x7f00683e22fa <GUAC_READ_UTF8>, input=0x7efffefbc638, in_remaining=2, writer=0x7f00683e240f <GUAC_WRITE_UTF8>,
      output=0x7efffefbc630, out_remaining=1) at iconv.c:79
      79 write_start = *output;
      (gdb) n [18/1979]
      80 writer(output, out_remaining, value);
      (gdb) n
      81 out_remaining -= *output - write_start;
      (gdb) n
      84 if (value == 0)
      (gdb) n
      67 while (in_remaining > 0 && out_remaining > 0) {
      (gdb) n
      74 read_start = *input;
      (gdb) n
      75 value = reader(input, in_remaining);
      (gdb) step
      GUAC_READ_UTF8 (input=0x7efffefbc638, remaining=2) at iconv.c:98
      98 *input += guac_utf8_read(*input, remaining, &value);
      (gdb) step
      guac_utf8_read (utf8=0x7f00600019d3 <incomplete sequence \345\255>, length=2, codepoint=0x7efffefbc58c) at unicode.c:133
      133 if (length <= 0)
      (gdb) n
      137 initial = (unsigned char) *(utf8++);
      (gdb) n
      140 if ((initial | 0x7F) == 0x7F) {
      (gdb) n
      146 else if ((initial | 0x1F) == 0xDF) {
      (gdb) n
      152 else if ((initial | 0x0F) == 0xEF) {
      (gdb) n
      153 result = initial & 0x0F;
      (gdb) n
      154 bytes = 3;
      (gdb) n
      170 if (bytes > length)
      (gdb) n
      171 return 0;
      (gdb) n
      182 }
      GUAC_READ_UTF8 (input=0x7efffefbc638, remaining=2) at iconv.c:99
      99 return value;
      (gdb) n
      101 }
      (gdb)
      guac_iconv (reader=0x7f00683e22fa <GUAC_READ_UTF8>, input=0x7efffefbc638, in_remaining=2, writer=0x7f00683e240f <GUAC_WRITE_UTF8>, output=0x7efffefbc630,
      out_remaining=1) at iconv.c:76
      76 in_remaining -= *input - read_start;
      (gdb) p *input - read_start
      $15 = 0
      

       

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                aiden0z Aiden Luo
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated: