Subject: kern/5406: break() fails after shmat() at a low address
To: None <gnats-bugs@gnats.netbsd.org>
From: Valtteri Vuorikoski <vuori@notcom.org>
List: netbsd-bugs
Date: 05/06/1998 12:59:30
>Number:         5406
>Category:       kern
>Synopsis:       break() fails after shmat() at a low address
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed May  6 03:05:01 1998
>Last-Modified:
>Originator:     Valtteri Vuorikoski
>Organization:
	Meditation
>Release:        NetBSD-current on May 4th, 1998
>Environment:
System: NetBSD ph 1.3E NetBSD 1.3E (PH-CROSS) #2: Mon May 4 20:41:10 EEST 1998 vuori@ph:/mnt/netbsd/src/sys/arch/i386/compile/PH-CROSS i386
Genuine i386 with UVM but not PMAP_NEW. Mostly 1.3.1 userland.

>Description:
 After attaching a shared memory segment at a low address (in the case of my
test program, at or under 0x14000), break() fails with ENOMEM.

>How-To-Repeat:

 Compile and run the following program.

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

/* SSIZE size of shared memory segment
 * SADDR where it gets attached
 * MSIZE size of memory to allocate
 *
 * the problem occurs with small values of SADDR, in this case when
 * SADDR <= 0x14000 */

#define SSIZE 4096
#define SADDR 0x14000
#define MSIZE 4096

int main(int argc, char **argv)
{
  int id;
  void *seg;
  char *mem;

  printf("starting\n");

  id = shmget(IPC_PRIVATE, SSIZE, 0755);

  if(id == -1)
  {
    printf("shmget failed, errno %d: %s\n", errno, strerror(errno));
    exit(1);
  } else
    printf("shmget succeeded for %d bytes, id %d\n", id, SSIZE);

  seg = shmat(id, (void*) SADDR, 0);

  if(seg == NULL)
  {
    printf("shmat failed, errno %d: %s\n", errno, strerror(errno));
    goto lose;
  } else
    printf("shmat succeeded, attached at address 0x%x (0 = system decides), id %d\n", SADDR, id);

  mem = sbrk(MSIZE);

  if(mem == (char*) -1)
    printf("sbrk failed, errno %d: %s\n", errno, strerror(errno));
  else
    printf("shbrk succeeded for %d bytes\n", MSIZE);

  if(shmdt(seg) == -1)
    printf("detaching shm segment failed, errno %d: %s\n", errno, strerror(errno));

  lose:
  if(shmctl(id, IPC_RMID, (struct shmid_ds *) NULL) == -1)
    printf("removing shm segment failed, errno %d: %s\n", errno, strerror(errno));

  printf("done\n");
  exit(0);
}

>Fix:
 Unknown.

>Audit-Trail:
>Unformatted: