Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Jul 1998 21:53:18 -0700 (PDT)
From:      Matthew Dillon <dillon@backplane.com>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/7422: VM system fails to remove mapped page on truncate in some situations
Message-ID:  <199807280453.VAA18002@apollo.backplane.com>

next in thread | raw e-mail | index | archive | help

>Number:         7422
>Category:       kern
>Synopsis:       FreeBSD-current VM systems do not properly remove mapped pages on truncate in some situations.  -stable does.
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 27 22:00:02 PDT 1998
>Last-Modified:
>Originator:     Matthew Dillon
>Organization:
Best Internet Communications, Inc.
>Release:        FreeBSD 3.0-CURRENT i386
>Environment:

	Generic FreeBSD-current machine (CVS as of 26 Jul 98)
	Generic FreeBSD-stable machine (CVS somewhere between 2.2.6 and 2.2.7)

>Description:

	ON a -current machine:

	If you open a file and use write() to write to it and either
	you or another process mmap()'s the file, if the file is then
	truncated mmap()'d pages that should have been removed (made
	illegal) are sometimes not and can still be referenced with
	the original data still intact.

	Example:  create a file, write 4096+(512 to 4095) bytes to it.
	mmap the file, reference the second page of the mmap 
	(volatile x = ptr[4096];), then ftruncate the file to 4096
	bytes.  You can still reference the second page of the mmap
	(which should now be illegal) and it still contains the 
	original data written to it.  

	Now repeat the process but write 4096+4096 bytes to the
	file.  now when you ftruncate, referencing ptr[4096]
	after the ftruncate call will correctly segfault.

	(NOTE:  This is different from the file corruption bug
	previously reported.  This bug does not corrupt the file
	but does 'corrupt' the mmap.  It may or may not be
	related to the previously reported file corruption-on-
	mmap while appending bug).

	(NOTE:  The program properly segfaults in both cases on
	a -stable machine).

>How-To-Repeat:


/*
 * BADVM.C
 */

#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>

int
main(int ac, char **av)
{
    int fd;
    char buf[4096 + 4096];
    volatile char *base;
    volatile int x;
    int n;

    if (ac == 1) {
	printf("Run with an argument of '512' and then run with an argument of '4096'\n");
	exit(1);
    }
    n = strtol(av[1], NULL, 0);
    if (n < 0 || n > 4096) {
	printf("argument out of bounds\n");
	exit(1);
    }

    remove("test");
    if ((fd = open("test", O_RDWR|O_CREAT, 0644)) < 0)
	perror("open");
    memset(buf, 1, sizeof(buf));
    if (write(fd, buf, 4096 + n) != 4096 + n)
	perror("write");
    base = mmap((caddr_t)0, 8192, PROT_READ, MAP_SHARED, fd, 0);
    printf("map: %08lx\n", (long)base);
    printf("base[4096] should be 1: %d\n", base[4096]);
    ftruncate(fd, 4096);
    printf("base[4096] should fault: ");
    fflush(stdout);
    printf("%d\n", base[4096]);
    puts("oops, it didn't");
    lseek(fd, 4096, 0);
    memset(buf, 2, sizeof(buf));
    if (write(fd, buf, 4096) != 4096)
	perror("write");
    printf("base[4096] should be 2: %d\n", base[4096]);
    return(0);
}

>Fix:
	

>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199807280453.VAA18002>