misc/131099: [patch] readdir broken on Linux emulation.
Andreas Kies
andikies at gmail.com
Wed Jan 28 15:50:02 PST 2009
>Number: 131099
>Category: misc
>Synopsis: [patch] readdir broken on Linux emulation.
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Jan 28 23:50:01 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator: Andreas Kies
>Release: 7.1
>Organization:
>Environment:
FreeBSD andiunx.local 7.1-RELEASE FreeBSD 7.1-RELEASE #0: Thu Jan 1 14:37:25 UTC 2009 root at logan.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386
>Description:
The system call readdir does not return any data if a Linux binary is run.
The internally calculated space for returning an entry is
sizeof(struct dirent *), but it should be sizeof(struct dirent).
Please consider applying the attached patch.
>How-To-Repeat:
/*Compile the following program */
/* Compile with -fno-stack-protector if you want to run it as a Linux binary
* on FreeBSD 7.1
* Assembly part might be broken if optimization is used.
*/
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
int myreaddir( int fd, unsigned char *buf, int c)
{
int res;
__asm__ __volatile__ ("\
mov $0x59,%%eax \n\
int $0x80 \n"
: "=a" (res) : "b" (fd), "c" (buf), "d" (c)
);
return res;
}
int main()
{
int fd;
int i, j;
unsigned char inparr[512];
DIR *dipo;
int respar;
dipo=opendir(".");
for (j=0; j < 10; j++) {
memset( inparr, 0x55, sizeof(inparr));
respar=myreaddir(dirfd(dipo),inparr, 1);
if ( respar == 0 )
break;
if ( respar != 1 )
printf("respar %d\n", respar);
for (i=0; i < 25; i++)
printf( "%02x ", inparr[i]);
printf( "\n");
}
}
>Fix:
Apply attached patch.
Patch attached with submission follows:
--- linux_file.c.orig 2009-01-29 00:24:33.000000000 +0100
+++ linux_file.c 2009-01-29 00:24:55.000000000 +0100
@@ -438,7 +438,7 @@
/* readdir(2) case. Always struct dirent. */
if (is64bit)
return (EINVAL);
- nbytes = sizeof(linux_dirent);
+ nbytes = sizeof(*linux_dirent);
justone = 1;
} else
justone = 0;
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list