[comp.os.mach] Mach 2.5 bug

mcm@rti.UUCP (Mike Mitchell) (11/16/89)

I have run into a problem with Mach 2.5.  It is a problem that been in
BSD 4.X until BSD 4.3-Tahoe.  The fix is well understood for BSD type systems,
but I'm not sure how it fits into the Mach kernel.

The problem is that memory pages are not returned properly when using the
'brk()' library routine to free them.  More specifically, the PTE entries
are not invalidated properly when shrinking a region.  I can supply some
diffs to fix the problem for BSD systems, but I've never seen Mach source.

Anyway, try running the enclosed program.  Please tell me if it works on
your machine, and if so, what version of Mach and the type of CPU.

-------------------------------------------------------------------------

/*
 * This program shows off a problem with the kernel's "expand()" routine.
 */
#include <signal.h>

main()
{
    char *old_break, *cp;
    int i;
    extern char *sbrk(), *brk();
    void segv();

    signal(SIGSEGV, segv);

    i = getpagesize();
    old_break = sbrk(0);		/* get the current "break" */
    (void) brk(old_break + 2*i);	/* bump it up 2 pages */

    cp = old_break + i + 256;
    *cp = 1;				/* write into a new page */

    (void) brk(old_break);		/* release the memory */

    *cp = 2;				/* write into the page again.  This */
					/* time, you should get a sigsegv */

    printf("Your brk routine is broken!\n");
    exit(1);
}

void segv()
{
    printf("Your brk routine works correctly.\n");
    exit(0);
}

--------------------------------------------------------------------
-- 
Mike Mitchell	{decvax,seismo,ihnp4,philabs}!mcnc!rti!mcm  mcm@rti.rti.org

"If you hear me talking on the wind, You've got
 to understand, We must remain perfect strangers"	    (919) 541-6098

Rick.Rashid@CS.CMU.EDU (11/16/89)

The bug you describe has always been in Mach kernels and certainly is in
our current versions.  We have tried as much as possible to imitate the
behaviour of 4.3bsd and the code for brk() was written explicitly to do
so.  I didn't work on that particular routine myself, but in similar situations
in other parts of the bsd compatibility code we have similarly opted to
preserve the actual workings of 4.3bsd rather than make up a new definition
of behaviour that might be more logical.  In cases where we have occasionally
tried to modify the actions of bsd functions to better approximate the
man page definitions, we have often discovered that user or vendor programs
depend on the "incorrect" bsd implementation.  This is the reason for our
caution in making "corrections".

In any case, the impact of this particular bug is only to prevent the
actual release of the memory, not the semantics of brk() as defined in
the man pages.  In Mach terms, brk() does a vm_allocate if it expands
the memory but does not do a corresponding vm_deallocate if it contracts.
Programs will still work as advertised unless the brk() was actually needed
to free up backing store.  If you want to do that and you don't want to
add the vm_deallocate to your kernel sources, you should simply call
vm_deallocate explicitly after your call to brk.

-Rick

Rick.Rashid@CS.CMU.EDU (11/16/89)

I should also comment (since someone else certainly will) that the
brk() call has been labeled as "defunct" in bsd kernels for some time.
CMU's standard C libraries don't even allow it (although the trap
remains for compatibility).
-Rick