kern/68690: write(2) returns wrong vlalue when EFAULT

KOIE Hidetaka koie at suri.co.jp
Mon Jul 5 05:30:23 PDT 2004


>Number:         68690
>Category:       kern
>Synopsis:       write(2) returns wrong vlalue when EFAULT
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 05 12:30:22 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     KOIE Hidetaka
>Release:        FreeBSD-5.2 CURRENT
>Organization:
SURIGIKEN
>Environment:
FreeBSD sakura.suri.co.jp 5.2-CURRENT FreeBSD 5.2-CURRENT #1: Tue Jun 15 11:43:02 JST 2004     koie at sakura.suri.co.jp:/usr/obj/usr/src/sys/SAKURA  i386
>Description:
Invoking write(fd, buf, size), if buf has both validand invalid segment,
write return -1, but it's file pointer has been advanced.
The caller mistakes the pointer stays.

>How-To-Repeat:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>

int
main()
{
    const int PAGESIZE = sysconf(_SC_PAGESIZE);
    const int N = 5;
    const int SIZE = N * PAGESIZE;
    int ifd = open("in.dat", O_RDWR|O_CREAT|O_TRUNC, 0600);
    if (ifd < 0) {
        perror("open");
        goto out;
    }
    int should = 0;
    for (int i = 0; i < N - 2; i++) {
        char buf[PAGESIZE];
        if (write(ifd, buf, sizeof buf) != sizeof buf) {
            perror("write");
            goto out;
        }
        should += sizeof buf;
    }

    int ofd = open("out.dat", O_WRONLY|O_CREAT|O_TRUNC, 0600);
    if (ofd < 0) {
        perror("open");
        goto out;
    }

    void *addr = mmap(0, SIZE, PROT_READ, MAP_PRIVATE, ifd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        goto out;
    }
    fprintf(stderr, "pos=%ld\n", (long)lseek(ofd, 0, SEEK_CUR));
    int n = write(ofd, addr, SIZE);
    fprintf(stderr, "write(%d)->%d (should be %d)\n", SIZE, n, should);
    perror("write");
    fprintf(stderr, "pos=%ld (should be %d)\n", (long)lseek(ofd, 0, SEEK_CUR), should);
 out:
    exit(0);
}

>Fix:
Sorry, I don't know.
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list