[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#626451: linux-image: mremap returns useless pages moving anonymous shared mmap, access causes SIGBUS



Package: linux-image
Severity: normal

one-line summary:
mremap yields unusable pages when growing an ANONYMOUS SHARED mmap with MAYMOVE.

full description:
This program (courtesy of Alan Curry) demonstrates the raising of a
bus error by the (misguided?) sequence of 
- mmap'ing a one-page map with MAP_SHARED | MAP_ANONYMOUS
- mremap'ing to a larger size
- attempting to access the new portion of the map


#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

int main(void)
{
  int pgsz;
  void *p;

  pgsz = getpagesize();
  printf("pgsz = %d\n", pgsz);

  p = mmap(NULL, pgsz, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
  printf("p before growth = %p\n", p);

  p = mremap(p, pgsz, pgsz*2, MREMAP_MAYMOVE);
  printf("p after growth = %p\n", p);

  /* try to access the last byte of the original allocation */
  printf("p[%d] = %d\n", pgsz-1, ((volatile char *)p)[pgsz-1]);

  /* try to access the first byte of the new allocation */
  printf("p[%d] = %d\n", pgsz, ((volatile char *)p)[pgsz]);

  return 0;

} 


Alan Curry's comments: {

The problem seems to be that a growing mremap doesn't work on shared
anonymous mappings. This might be by design, but it seems fishy to me since
mremap doesn't return an error but instead gives you some pages that you
can't use.

I think you'd be justified in reporting this as a kernel bug. If it turns out
to be an intentional restriction it should at least be mentioned in the
mremap man page.

Here's a much smaller demo program. If MAP_SHARED is changed to MAP_PRIVATE,
there's no problem. If a file is provided for backing store instead of
MAP_ANONYMOUS, there's no problem. The combination of shared and anonymous
causes the SIGBUS. 
}


Upon further reflection, the sequence is meaningless; and if it's
possible for mremap to detect that the combination MAP_SHARED|MAP_ANONYMOUS
is defined for the mapping, it ought to refuse the request
(returning MAP_FAILED, with errno==EINVAL) if it included
MREMAP_MAYMOVE, or ignore the option and attempt to keep the
mapping fixed.

Also, the manpage for mremap ought to advise against doing this.
Because an anonymous mapping can only be shared by forking, but
once the two processes have separated, if one moves the mapping,
how is the other ever to find it? Sure, one can think of ways
of informing this second program of the change; but there's no
clear way of maintaining this association automatically.

This problem arose in a discussion in comp.unix.programmer
which began with the message:
<6e42b7e2-8f29-4c41-98eb-3caa4108f964@m10g2000yqd.googlegroups.com>
or
http://groups.google.com/group/comp.unix.programmer/browse_thread/thread/9a8c963aedc91ca2#

I can be contacted at mijoryx@yahoo.com or in the newsgroup thread.

Thank you for your time.

M. Joshua Ryan

keywords
mmap mremap mman.h MAP_SHARED MAP_ANONYMOUS MREMAP_MAYMOVE



-- System Information:
Debian Release: 5.0.8
  APT prefers oldstable
  APT policy: (500, 'oldstable')
Architecture: i386 (i586)

Kernel: Linux 2.6.25.15
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/bash


Reply to: