]
Jean-Frederic Clere updated MODCLUSTER-582:
-------------------------------------------
        Status: Resolved  (was: Pull Request Sent)
    Resolution: Done
 mod_cluster segfaults in process_info() due to wrongly generated
assembler instruction movslq
---------------------------------------------------------------------------------------------
                 Key: MODCLUSTER-582
                 URL: 
https://issues.jboss.org/browse/MODCLUSTER-582
             Project: mod_cluster
          Issue Type: Bug
          Components: Native (httpd modules)
    Affects Versions: 1.2.13.Final, 1.3.6.Final, 2.0.0.Alpha1
         Environment: RHEL, gcc
            Reporter: Michal Karm Babacek
            Assignee: Michal Karm Babacek
            Priority: Blocker
             Fix For: 1.3.8.Final, 2.0.0.Alpha1
 Affected code:
[
1.3.x|https://github.com/modcluster/mod_cluster/blob/1.3.x/native/mod_man...]
[
1.2.x|https://github.com/modcluster/mod_cluster/blob/1.2.x/native/mod_man...]
[
master|https://github.com/modcluster/mod_proxy_cluster/blob/master/native...]
 Martin Osvald from Red Hat:
 {quote}
 h3. Description of problem:
 mod_cluster segfaults in process_info() due to wrongly generated assembler instruction
movslq
 How reproducible:
 intermittent
 Steps to Reproduce:
 TBD or N/A
 h3. Actual results:
 {code}
 Core was generated by `/usr/sbin/httpd.worker'.
 Program terminated with signal 11, Segmentation fault.
 #0  process_info (r=0x7fc2840386a8, errtype=<value optimized out>) at
mod_manager.c:1150
 1150            ap_rprintf(r, ",Elected: %d,Read: %d,Transfered: %d,Connected:
%d,Load: %d\n",
 (gdb) bt
 #0  process_info (r=0x7fc2840386a8, errtype=<value optimized out>) at
mod_manager.c:1150
 #1  0x00007fc2b9d8344a in manager_handler (r=0x7fc2840386a8) at mod_manager.c:2705
 #2  0x00007fc2bf54f640 in ap_run_handler (r=0x7fc2840386a8) at
/usr/src/debug/httpd-2.2.15/server/config.c:158
 #3  0x00007fc2bf552efe in ap_invoke_handler (r=0x7fc2840386a8) at
/usr/src/debug/httpd-2.2.15/server/config.c:376
 #4  0x00007fc2bf55e300 in ap_process_request (r=0x7fc2840386a8) at
/usr/src/debug/httpd-2.2.15/modules/http/http_request.c:282
 #5  0x00007fc2bf55b178 in ap_process_http_connection (c=0x7fc2ac051d00) at
/usr/src/debug/httpd-2.2.15/modules/http/http_core.c:190
 #6  0x00007fc2bf557148 in ap_run_process_connection (c=0x7fc2ac051d00) at
/usr/src/debug/httpd-2.2.15/server/connection.c:43
 #7  0x00007fc2bf564052 in process_socket (thd=0x7fc2bffe8d30, dummy=<value optimized
out>) at /usr/src/debug/httpd-2.2.15/server/mpm/worker/worker.c:544
 #8  worker_thread (thd=0x7fc2bffe8d30, dummy=<value optimized out>) at
/usr/src/debug/httpd-2.2.15/server/mpm/worker/worker.c:894
 #9  0x00007fc2bddf99d1 in start_thread (arg=0x7fc2a51f4700) at pthread_create.c:301
 #10 0x00007fc2bdb46a8d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115
 (gdb)
 {code}
 h3. Expected results:
 no segfault
 h3.Additional info:
 It looks like the produced assembler in function process_info() is wrong, there is a
movslq instruction leading to results not expected on C source code level...
 {code}
 # gdb /usr/sbin/httpd.worker
./dump_new/dump/core.httpd.worker.pid8422.usr48.sig11.tim1493787964
 ...
 (gdb) f 0
 #0  process_info (r=0x7fc2840386a8, errtype=<value optimized out>) at
mod_manager.c:1150
 1150            ap_rprintf(r, ",Elected: %d,Read: %d,Transfered: %d,Connected:
%d,Load: %d\n",
 (gdb) list
 1145    #if AP_MODULE_MAGIC_AT_LEAST(20101223,1)
 1146            proxystat  = (proxy_worker_shared *) pptr;
 1147    #else
 1148            proxystat  = (proxy_worker_stat *) pptr;
 1149    #endif
 1150            ap_rprintf(r, ",Elected: %d,Read: %d,Transfered: %d,Connected:
%d,Load: %d\n",
 1151                       (int) proxystat->elected, (int) proxystat->read, (int)
proxystat->transferred,
 1152                       (int) proxystat->busy, proxystat->lbfactor);
 1153            
 1154        }
 (gdb) i registers 
 rax            0x7fc26b59df58   140473001434968           <<<--- there should be
0x7fc2bf507f98 instead
 rbx            0x7fc24c056b5c   140472475806556
 rcx            0x7fc2840229a8   140473415117224
 rdx            0xffffffffac096100       -1408671488
 rsi            0x7fc2b9d85c00   140474318347264
 rdi            0x7fc2840386a8   140473415206568
 rbp            0x17     0x17
 rsp            0x7fc2a51f3b40   0x7fc2a51f3b40
 r8             0x3036203a6c74542c       3473999597862671404
 r9             0x6873756c462c6666       7526488510160463462
 r10            0x3031203a74696177       3472592223112618359
 r11            0x0      0
 r12            0x7fc2a51f3b98   140473970670488
 r13            0x7fc2840386a8   140473415206568
 r14            0x17     23
 r15            0x431bde82d7b634db       4835703278458516699
 rip            0x7fc2b9d7d90d   0x7fc2b9d7d90d <process_info+477>
 eflags         0x203    [ CF IF ]
 cs             0x33     51
 ss             0x2b     43
 ds             0x0      0
 es             0x0      0
 fs             0x0      0
 gs             0x0      0
 (gdb) disassemble /m $rip
 ...
 1143            pptr = (char *) ou;
    0x00007fc2b9d7d8f4 <+452>:   mov    0x58(%rsp),%rax
 1144            pptr = pptr + ou->offset;
 1145    #if AP_MODULE_MAGIC_AT_LEAST(20101223,1)
 1146            proxystat  = (proxy_worker_shared *) pptr;
 1147    #else
 1148            proxystat  = (proxy_worker_stat *) pptr;
    0x00007fc2b9d7d903 <+467>:   movslq 0x138(%rax),%rdx       <<<--- this
brings wrong result into rdx
    0x00007fc2b9d7d90a <+474>:   add    %rdx,%rax              <<<--- which
is then added to rax, rax should normally hold address of ou + ou->offset 
 1149    #endif
 1150            ap_rprintf(r, ",Elected: %d,Read: %d,Transfered: %d,Connected:
%d,Load: %d\n",
    0x00007fc2b9d7d8f9 <+457>:   lea    0x8300(%rip),%rsi        # 0x7fc2b9d85c00 
<<<--- the string ",Elected: %d,Read: %d,Transfered: %d,Connected: %d,Load:
%d\n"
    0x00007fc2b9d7d900 <+464>:   mov    %r13,%rdi                                 
<<<--- r parameter
 => 0x00007fc2b9d7d90d <+477>:   mov    0xc0(%rax),%r9         <<<---
ap_rprintf params starting here proxystat->elected, ...
    0x00007fc2b9d7d914 <+484>:   mov    0x20(%rax),%r8
    0x00007fc2b9d7d918 <+488>:   mov    0x28(%rax),%rcx
    0x00007fc2b9d7d91c <+492>:   mov    0x30(%rax),%rdx
    0x00007fc2b9d7d920 <+496>:   mov    0x18(%rax),%eax
    0x00007fc2b9d7d923 <+499>:   mov    %eax,(%rsp)
    0x00007fc2b9d7d926 <+502>:   xor    %eax,%eax
    0x00007fc2b9d7d928 <+504>:   callq  0x7fc2b9d7c0f0 <ap_rprintf@plt>
 ...
 (gdb)
 {code}
 from gdb it looks like proxystat contains correct address, but it only seems so as very
likely due to debugging info knowing where to look:
 {code}
 (gdb) p proxystat 
 $2 = (proxy_worker_stat *) 0x7fc2bf507f98
 (gdb) p *proxystat
 $11 = {
   status = 0, 
   error_time = 0, 
   retries = 0, 
   lbstatus = 0, 
   lbfactor = 0, 
   transferred = 0, 
   read = 0, 
   elected = 0, 
   route = '\000' <repeats 63 times>, 
   redirect = '\000' <repeats 63 times>, 
   context = 0x0, 
   busy = 206158430208, 
   lbset = 1818454389
 }
 (gdb)
 {code}
 but actually computed value for proxystat by assembler is wrongly 0x7fc26b59df58 instead
of 0x7fc2bf507f98:
 {code}
 (gdb) x/x $rax
 0x7fc26b59df58: Cannot access memory at address 0x7fc26b59df58
 (gdb)
 {code}
 address of ou and offset value:
 {code}
 (gdb) p ou
 $5 = (nodeinfo_t *) 0x7fc2bf507e58
 (gdb) p /x ou->offset
 $7 = 0x140
 (gdb)
 {code}
 their correct sum:
 {code}
 (gdb) p /x 0x7fc2bf507e58 + 0x140
 $9 = 0x7fc2bf507f98
 (gdb)
 {code}
 which is the same as already mentioned proxystat using debuginfo:
 {code}
 (gdb) p proxystat 
 $2 = (proxy_worker_stat *) 0x7fc2bf507f98
 (gdb)
 {code}
 so the below 2 lines in process_info() lead to computing it wrongly and they will have to
be rewritten:
 {code}
 1097 static char * process_info(request_rec *r, int *errtype)
 1098 {
 ...
 1141         pptr = (char *) ou;
 1142         pptr = pptr + ou->offset;
 {code}
 {quote}