title: memcpy() segmentation fault debugging exercise on PROT_READ in mmap()
body: <p>I have generated SIGSEGV in my code intentionally to learn to debug it under various utilities like <em>catchsegv</em>, <em>gdb</em>, <em>valgrind</em> &amp; <em>pmap</em>. I intentionally used memcpy() on mmap'ed file which is having flag of PROT_READ set by mprotect(). Now when I am debugging it under gdb I am not able to make any conclusion from assembly output. I am quite a newbie to assembly.</p>
  
  <p>Details - </p>
  
  <p>Memory Stuff :</p>
  
  <pre><code>    (gdb) x/35i 0x00002aaaaad55500
      0x2aaaaad55500 &lt;memccpy+32&gt;: jne    0x2aaaaad554e8 &lt;memccpy+8&gt;
      0x2aaaaad55502 &lt;memccpy+34&gt;: mov    %rdi,%rax
      0x2aaaaad55505 &lt;memccpy+37&gt;: retq
      0x2aaaaad55506 &lt;memccpy+38&gt;: nopw   %cs:0x0(%rax,%rax,1)
      0x2aaaaad55510 &lt;memccpy+48&gt;: xor    %eax,%eax
      0x2aaaaad55512 &lt;memccpy+50&gt;: retq
      0x2aaaaad55513:      nop
      0x2aaaaad55514:      nop
      0x2aaaaad55515:      nop
      0x2aaaaad55516:      nop
      0x2aaaaad55517:      nop
      0x2aaaaad55518:      nop
      0x2aaaaad55519:      nop
      0x2aaaaad5551a:      nop
      0x2aaaaad5551b:      nop
      0x2aaaaad5551c:      nop
      0x2aaaaad5551d:      nop
      0x2aaaaad5551e:      nop
      0x2aaaaad5551f:      nop
      0x2aaaaad55520 &lt;__memcpy_chk&gt;:       cmp    %rdx,%rcx
      0x2aaaaad55523 &lt;__memcpy_chk+3&gt;:     jb     0x2aaaaadcb590 &lt;__chk_fail&gt;
      0x2aaaaad55529:      nopl   0x0(%rax)
      0x2aaaaad55530 &lt;memcpy&gt;:     cmp    $0x20,%rdx
      0x2aaaaad55534 &lt;memcpy+4&gt;:   mov    %rdi,%rax
      0x2aaaaad55537 &lt;memcpy+7&gt;:   jae    0x2aaaaad555b0 &lt;memcpy+128&gt;
      0x2aaaaad55539 &lt;memcpy+9&gt;:   test   $0x1,%dl
      0x2aaaaad5553c &lt;memcpy+12&gt;:  je     0x2aaaaad55549 &lt;memcpy+25&gt;
      0x2aaaaad5553e &lt;memcpy+14&gt;:  movzbl (%rsi),%ecx
      =&gt; 0x2aaaaad55541 &lt;memcpy+17&gt;:  mov    %cl,(%rdi)
      0x2aaaaad55543 &lt;memcpy+19&gt;:  inc    %rsi
      0x2aaaaad55546 &lt;memcpy+22&gt;:  inc    %rdi
      0x2aaaaad55549 &lt;memcpy+25&gt;:  test   $0x2,%dl
      0x2aaaaad5554c &lt;memcpy+28&gt;:  je     0x2aaaaad55560 &lt;memcpy+48&gt;
      0x2aaaaad5554e &lt;memcpy+30&gt;:  movzwl (%rsi),%ecx
      0x2aaaaad55551 &lt;memcpy+33&gt;:  mov    %cx,(%rdi)
  </code></pre>
  
  <p>As you can see that SEGFAULT happened at instruction 0x2aaaaad55541, which is also indicated in 64bit Instruction Pointer register RIP. </p>
  
  <p>Registers :</p>
  
  <pre><code>    (gdb) info registers
      rax            0x2aaaaaacf002   46912496267266
      rbx            0x40146a 4199530
      rcx            0x69     105
      rdx            0x1      1
      rsi            0x40146a 4199530
      rdi            0x2aaaaaacf002   46912496267266
      rbp            0x7      0x7
      rsp            0x7fffffffe468   0x7fffffffe468
      r8             0x40146a 4199530
      r9             0x53202c444145525f       5989836176067220063
      r10            0x7fffffffe1f0   140737488347632
      r11            0x2aaaaad55530   46912498914608
      r12            0x2aaaab05eac8   46912502098632
      r13            0x7fffffffe5a0   140737488348576
      r14            0x7fffffffe590   140737488348560
      r15            0x2aaaaaacf000   46912496267264
      rip            0x2aaaaad55541   0x2aaaaad55541 &lt;memcpy+17&gt;
      eflags         0x10202  [ IF RF ]
      cs             0x33     51
      ss             0x2b     43
      ds             0x0      0
      es             0x0      0
      fs             0x0      0
      gs             0x0      0
  </code></pre>
  
  <p>Process mappings :</p>
  
  <p>Below is the output of "info proc mappings" command inside gdb.</p>
  
  <pre><code>    [excerpt]
      0x2aaaaaacf000     0x2aaaaaad0000     0x1000          0             /tmp/dst_file
      [/excerpt]
  </code></pre>
  
  <p>/tmp/dst_file is mapped into memory using mmap() and made READ ONLY using PROT_READ before memcpy() call &amp; memcpy() tries to write content on it and thus SEGFAULT appears.</p>
  
  <p>Memcpy() call used :</p>
  
  <pre><code>    memcpy (mmap_start + myfilestat1.st_size, str1, strlen(str1))
  </code></pre>
  
  <p>mmap_start is the starting address and myfilestat1.st_size is new truncated file size. str1 is the string to append to the file.</p>
  
  <p>Here is a little flow of my source code - </p>
  
  <pre><code>    1. Fstat original size of file 
      2. Set Offset of file to grow depending upon strlen() of string to append 
      3. Ftruncate() to grow file size 
      4. Fstat new file size. 
      5. Mmap the newly truncated file 
      6. If segmentation fault need to be generated, call mprotect() to convert to PROT_READ. 
      7. Memcpy() with Orignal fstat size to append contents to text file. 
  </code></pre>
  
  <p>Question - </p>
  
  <p>Now what I am not able to understand is </p>
  
  <pre><code>    0x2aaaaad55541 &lt;memcpy+17&gt;:  mov    %cl,(%rdi)
  </code></pre>
  
  <p>What does this instruction exactly do? RDI register contains end address of file mapped to start writing, why does the value at RDI address is being written at CX register?</p>
  
  <p>Any help is appreciated. Let me know if more info is needed.</p>