Bug 10162

Summary: stratcliff test segfaults on ia64
Product: glibc Reporter: Aurelien Jarno <aurelien>
Component: libcAssignee: H.J. Lu <hjl.tools>
Status: RESOLVED FIXED    
Severity: normal CC: glibc-bugs
Priority: P2 Flags: fweimer: security-
Version: unspecified   
Target Milestone: ---   
Host: ia64-unknown-linux-gnu Target: ia64-unknown-linux-gnu
Build: ia64-unknown-linux-gnu Last reconfirmed:
Attachments: A patch

Description Aurelien Jarno 2009-05-17 17:56:36 UTC
glibc 2.10 has added a new test for memchr() in stratcliff. This new test fails 
on ia64, which has its own assembly version in sysdeps/ia64/memchr.S.

It looks like this assembly version does some prefetch, and crosses the page 
boundary, causing the segfault. It should be possible to do prefetching while 
not triggering page faults on ia64, but I don't know enough ia64 assembly to be 
able to modify this code myself.
Comment 1 H.J. Lu 2009-05-20 21:22:57 UTC
stratcliff.c has

  int size = sysconf (_SC_PAGESIZE);
  int nchars = size / sizeof (CHAR);
...
  adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
                       MAP_PRIVATE | MAP_ANON, -1, 0); 
...
      mprotect (adr, size, PROT_NONE);
      mprotect (adr + 2 * nchars, size, PROT_NONE);
      adr += nchars;
...
   CHAR *cp = MEMCHR (&adr[outer], L('V'), 3 * size);

memchr is called with size which contains unreadable pages. How
does it work on any arch?
Comment 2 H.J. Lu 2009-05-20 22:28:33 UTC
The problem is software pipeline doesn't take page boundary into
account.
Comment 3 Aurelien Jarno 2009-05-20 22:34:49 UTC
(In reply to comment #1)
> stratcliff.c has
> 
>   int size = sysconf (_SC_PAGESIZE);
>   int nchars = size / sizeof (CHAR);
> ...
>   adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
>                        MAP_PRIVATE | MAP_ANON, -1, 0); 
> ...
>       mprotect (adr, size, PROT_NONE);
>       mprotect (adr + 2 * nchars, size, PROT_NONE);
>       adr += nchars;
> ...
>    CHAR *cp = MEMCHR (&adr[outer], L('V'), 3 * size);
> 
> memchr is called with size which contains unreadable pages. How
> does it work on any arch?

The looked up char is now to be before the page boundary, that is before the 
unreadable pages. This test actually checks that in such condition theses pages 
are not accessed.
Comment 4 H.J. Lu 2009-05-21 19:45:37 UTC
A patch is posted at

http://sourceware.org/ml/libc-alpha/2009-05/msg00110.html
Comment 5 H.J. Lu 2009-05-21 19:46:44 UTC
(In reply to comment #4)
> A patch is posted at
> 
> http://sourceware.org/ml/libc-alpha/2009-05/msg00110.html

Oops. Wrong patch. I will upload the patch here.
Comment 6 H.J. Lu 2009-05-21 19:47:07 UTC
Created attachment 3955 [details]
A patch
Comment 7 Aurelien Jarno 2009-05-21 20:57:15 UTC
I confirm it works well, thanks a lot! Could someone apply this patch?
Comment 8 Ulrich Drepper 2009-05-22 01:50:40 UTC
Fixed in current git version.
Comment 9 Petr Baudis 2009-11-09 17:59:09 UTC
Unfortunately, this seems to break when calling memchr() on a shared mmap()ed
buffer - this crashes now:

#include<sys/mman.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
int main() {
  void *m = mmap(NULL, 53, PROT_READ, MAP_SHARED, open("/etc/passwd", O_RDONLY
), 0);
  volatile void *q = memchr(m, ':', 53);
}

since memchr() tries to access m-8. I have only very little idea IA64, I think
it is because the kernel cannot fill p[] in time, causing the speculative load
to fail, and the assumption that speculative load fails only if the mapping is
inaccessible is invalid?
Comment 10 H.J. Lu 2009-11-09 21:01:57 UTC
A patch is posted at

http://sourceware.org/ml/libc-alpha/2009-11/msg00032.html
Comment 11 Ulrich Drepper 2009-11-15 03:20:57 UTC
Fixed in git.
Comment 12 H.J. Lu 2009-11-15 16:18:02 UTC
(In reply to comment #10)
> A patch is posted at
> 
> http://sourceware.org/ml/libc-alpha/2009-11/msg00032.html

Please use the patch above. It handles reading beyond memory
properly, regardless memory size.
Comment 13 Ulrich Drepper 2009-11-20 16:31:36 UTC
Applied.