Date: Tue, 15 Dec 2009 03:08:41 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Robert Watson <rwatson@FreeBSD.org> Cc: svn-src-stable@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org, svn-src-stable-8@FreeBSD.org Subject: Re: svn commit: r200509 - stable/8/libexec/rtld-elf Message-ID: <20091215013718.D984@besplex.bde.org> In-Reply-To: <200912141219.nBECJLfJ026164@svn.freebsd.org> References: <200912141219.nBECJLfJ026164@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 14 Dec 2009, Robert Watson wrote: > Log: > Merge r197808 from head to stable/8: > > In rtld's map_object(), use pread(..., 0) rather than read() to read the > ELF header from the front of the file. As all other I/O on the binary > is done using mmap(), this avoids the need for seek privileges on the > file descriptor during run-time linking. Doesn't/shouldn't pread() require seek privileges? It certainly uses them. BTW, its man page contradicts and/or is incomplete about what happens for unseekable files: % On objects capable of seeking, the read() starts at a position given by ^^^^^^^^^^^^^^^^^^^^^^ Should say "read() and readv() start at the" % the pointer associated with d (see lseek(2)). Upon return from read(), ... or readv() % the pointer is incremented by the number of bytes actually read. % % Objects that are not capable of seeking always read from the current % position. The value of the pointer associated with such an object is % undefined. The second paragraph applies to all members of the read() family (though perhaps it was only intended intended to apply to read() and readv() like it did before pread() existed), and is wrong for pread() and preadv(). Instead, pread() attemps to determine seekability using the DFLAG_SEEKABLE flag in the same way as lseek(); if this is set, then pread() correctly determines non-seekability and returns ESPIPE, but if this is not set the pread() assumes that the file is seekable even if it isn't, and I think the error is not detected later. (For the corresponding bug in lseek(2), the error is certainly not detected later, since there is no "later". pread() is presumably bug for bug compatible with this and reads from the current non-position for unseekable files when the error is not detected.) % ERRORS % The read(), readv(), pread() and preadv() system calls will succeed % unless: % ... % The pread() and preadv() system calls may also return the following % errors: % % [EINVAL] The offset value was negative. % % [ESPIPE] The file descriptor is associated with a pipe, socket, % or FIFO. This says that pread() may work correctly for some non-seekable files. Since it only says "may", it doesn't quite contradict the above. Also, the list of file types for which it may work correctly is incomplete. It is unclear exactly which file types work correctly, since DFLAG_SEEKABLE is set for all files of type "vnop" (see struct fileops vnops). I think this covers lots of unseekable irregular regular files in weird file systems like procfs. It is also set for all device files, but most devices aren't seekable. It is not set for uipc shm and sem files, so I think ESPIPE can be returned for these file types, contradicting the above and the corresponding list in lseek.2, but this is unimportant since pread[v] would fail with EOPNOTSUPP if it got past the ESPIPE. Similarly for write.2 and lseek.2. Extra for lseek.2: it says "some devices are incapable of seeking" where it should say "some files are incapable of seeking" and/or give more details as above (even current man page for pread gives more details relevant to lseek than does lseek's man page!). Extra for write.2 (unrelated): where read.2 gives some details for short reads (it says that they don't happen for "normal" files, write.2 says less and doesn't mention "normal" files, but it should say more because "normal" operation is more important. Which files are normal is undocumented and unclear. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20091215013718.D984>