Date: Fri, 1 Mar 1996 22:35:26 +1100 From: Bruce Evans <bde@zeta.org.au> To: hackers@FreeBSD.ORG, msmith@atrad.adelaide.edu.au Subject: Re: Linuxulator unhappiness... Message-ID: <199603011135.WAA10457@godzilla.zeta.org.au>
next in thread | raw e-mail | index | archive | help
>Heyho people; got a problem here. I can't be sure whether this has been >fixed in -current; I don't have the latest 2.2 snap installed (yet). I seem to remember this being reported and fixed before, but it doesn't seem to be fixed in -current: > 4912 idl CALL read(0x3,0x3ed008,0x8000) > 4912 idl GIO fd 3 read 32768 bytes > "SR\0\^D\0\0\0 >... remainder of 32K read ... > 4912 idl RET read 32768/0x8000 > 4912 idl CALL old.lseek(0x3,0xffff8004,0x1) > 4912 idl RET old.lseek 4 > 4912 idl CALL read(0x3,0x3ed008,0x8000) > 4912 idl RET read -1 errno 27 File too large > 4912 idl CALL read(0x3,0x3ed008,0x8000) > 4912 idl RET read -1 errno 27 File too large This is probably caused by bogus types and overflow bugs in linux_file.c function linux_lseek(): 1) the offset is declared as `unsigned long' in `struct linux_seek_args'. File offsets should normally be signed to avoid problems like the current one (that's why off_t is signed). 2) the offset is converted to an off_t and passed to lseek. Its value began as -32764 and became 0xffff8004 when it was implicitly converted to an unsigned long and converting it to an off_t leaves it as 0xffff8004. 3) lseek returns the final offset in an array of 2 ints. The value of 0x10000004 isn't representable as a Linux off_t, so it should be an error if it occurs. It shouldn't be allowed to occur - the final offset and the result should both be 4. No error checking is done, so this value is implicitly converted to 4 and there is no sign of an error until the next read. The read fails because the file offset is 0x100000004 and that is too big for the file system. On a big file system, read would return EOF. linux_lseek should use olseek() to do the error checking. However, olseek() has similar bugs. E.g., if the file offset is 0x7fffffff and the seek is 1 forward, then the final offset is 0x80000000 (+2GB) but the application is told that it is (long)0x80000000 == (off_t) 0xffffffff80000000 (-2GB). It should be what the application asked for, i.e., -2GB. >Any ideas? This is under -stable built yesterday. linux_lseek() in -stable is essentially the same as in -current. The implicit cast of the final value is explicit. This is a no-op on the i386 because the i386 is little-endian and ints have the same size as Linux off_t's and the unportable explicit and implicit casts all work... Reporting lseek as "old.lseek" is another bug. The linux syscall number for lseek is 19, which happens to agree with the FreeBSD syscall number for old.lseek. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199603011135.WAA10457>