Subject: port-i386/3920: linux emulation doesn't support mremap()
To: None <gnats-bugs@gnats.netbsd.org>
From: Matthias Scheler <tron@lyssa.owl.de>
List: netbsd-bugs
Date: 07/27/1997 22:34:35
>Number:         3920
>Category:       port-i386
>Synopsis:       linux emulation doesn't support mremap()
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jul 27 13:35:00 1997
>Last-Modified:
>Originator:     Matthias Scheler
>Organization:
Matthias Scheler                                http://home.owl.de/~tron/
>Release:        970716
>Environment:
System: NetBSD lyssa 1.2G NetBSD 1.2G (LYSSA) #1: Sun Jul 27 22:12:15 MEST 1997 tron@lyssa:/usr/src/sys/arch/i386/compile/LYSSA i386


>Description:
When I tried to use a Linux GCC environment under NetBSD I discovered that
"cpp" died sometimes because it uses the unsupported mremap() syscall.
After looking through the source of linux libc 5.4.23 I found that it is
only called in "dl-malloc/malloc.c":

#if __STD_C
static mchunkptr mremap_chunk(mchunkptr p, size_t new_size)
#else
static mchunkptr mremap_chunk(p, new_size) mchunkptr p; size_t new_size;
#endif
{
...
  cp = (char *)mremap((char *)p - offset, size + offset, new_size, 1);

  if (cp == (char *)-1) return 0;
...
}

...

#if __STD_C
Void_t* rEALLOc(Void_t* oldmem, size_t bytes)
#else
Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
#endif
{
...
#if HAVE_MMAP
  if (chunk_is_mmapped(oldp))
  {
#if HAVE_MREMAP
    newp = mremap_chunk(oldp, nb);
    if(newp) return chunk2mem(newp);
#endif
...

As one can see a dummy function returning an error on mremap() will solve
the problem.

>How-To-Repeat:
Start a linux binary which uses realloc() from a recent "libc" (5.4.x).

>Fix:
*** src/sys/compat/linux/linux_file.c.orig	Fri Jun 27 13:23:39 1997
--- src/sys/compat/linux/linux_file.c	Sun Jul 27 22:00:47 1997
*************** linux_sys_fdatasync(p, v, retval)
*** 822,824 ****
--- 822,844 ----
  #endif
  	return sys_fsync(p, v, retval);
  }
+ 
+ /*
+  * mremap() dummy
+ */
+ int
+ linux_sys_mremap(p, v, retval)
+ 	struct proc *p;
+ 	void *v;
+ 	register_t *retval;
+ {
+ #ifdef notdef
+ 	struct linux_sys_mremap_args /* {
+ 		syscallarg(void *) old_address;
+ 		syscallarg(size_t) old_size;
+ 		syscallarg(size_t) new_size;
+ 		syscallarg(unsigned long) flags;
+ 	} */ *uap = v;
+ #endif
+ 	return ENOMEM;
+ }
*** src/sys/compat/linux/linux_syscallargs.h.orig	Sat Jun 14 13:27:51 1997
--- src/sys/compat/linux/linux_syscallargs.h	Sun Jul 27 22:11:28 1997
*************** struct linux_sys___sysctl_args {
*** 330,335 ****
--- 330,342 ----
  	syscallarg(struct linux___sysctl *) lsp;
  };
  
+ struct linux_sys_mremap_args {
+ 	syscallarg(void *) old_address;
+ 	syscallarg(size_t) old_size;
+ 	syscallarg(size_t) new_size;
+ 	syscallarg(unsigned long) flags;
+ };
+ 
  /*
   * System call prototypes.
   */
*************** int	linux_sys_fdatasync	__P((struct proc
*** 462,464 ****
--- 469,472 ----
  int	linux_sys___sysctl	__P((struct proc *, void *, register_t *));
  int	sys_mlock	__P((struct proc *, void *, register_t *));
  int	sys_munlock	__P((struct proc *, void *, register_t *));
+ int	linux_sys_mremap	__P((struct proc *, void *, register_t *));
*** src/sys/compat/linux/linux_syscalls.c.orig	Sat Jun 14 13:27:52 1997
--- src/sys/compat/linux/linux_syscalls.c	Sun Jul 27 22:02:16 1997
*************** char *linux_syscallnames[] = {
*** 181,185 ****
  	"#160 (unimplemented sched_get_priority_min)",		/* 160 = unimplemented sched_get_priority_min */
  	"#161 (unimplemented sched_rr_get_interval)",		/* 161 = unimplemented sched_rr_get_interval */
  	"#162 (unimplemented nanosleep)",		/* 162 = unimplemented nanosleep */
! 	"#163 (unimplemented mremap)",		/* 163 = unimplemented mremap */
  };
--- 181,185 ----
  	"#160 (unimplemented sched_get_priority_min)",		/* 160 = unimplemented sched_get_priority_min */
  	"#161 (unimplemented sched_rr_get_interval)",		/* 161 = unimplemented sched_rr_get_interval */
  	"#162 (unimplemented nanosleep)",		/* 162 = unimplemented nanosleep */
! 	"mremap",			/* 163 = mremap */
  };
*** src/sys/compat/linux/linux_sysent.c.orig	Sat Jun 14 13:27:52 1997
--- src/sys/compat/linux/linux_sysent.c	Sun Jul 27 22:07:28 1997
*************** struct sysent linux_sysent[] = {
*** 359,365 ****
  	    sys_nosys },			/* 161 = unimplemented sched_rr_get_interval */
  	{ 0, 0,
  	    sys_nosys },			/* 162 = unimplemented nanosleep */
! 	{ 0, 0,
! 	    sys_nosys },			/* 163 = unimplemented mremap */
  };
  
--- 359,365 ----
  	    sys_nosys },			/* 161 = unimplemented sched_rr_get_interval */
  	{ 0, 0,
  	    sys_nosys },			/* 162 = unimplemented nanosleep */
! 	{ 4, s(struct linux_sys_mremap_args),
! 	    linux_sys_mremap },			/* 163 = mremap */
  };
  
>Audit-Trail:
>Unformatted: