From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/6195 Path: news.gmane.org!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general,gmane.linux.toybox Subject: faccessat and AT_SYM_NOFOLLOW Date: Thu, 25 Sep 2014 12:01:10 -0400 Message-ID: <20140925160110.GA25937@brightrain.aerifal.cx> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1411660899 4468 80.91.229.3 (25 Sep 2014 16:01:39 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 25 Sep 2014 16:01:39 +0000 (UTC) Cc: rob@landley.net, toybox@lists.landley.net To: musl@lists.openwall.com Original-X-From: musl-return-6208-gllmg-musl=m.gmane.org@lists.openwall.com Thu Sep 25 18:01:31 2014 Return-path: Envelope-to: gllmg-musl@plane.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1XXBTx-0003Xm-OE for gllmg-musl@plane.gmane.org; Thu, 25 Sep 2014 18:01:25 +0200 Original-Received: (qmail 30177 invoked by uid 550); 25 Sep 2014 16:01:23 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 30166 invoked from network); 25 Sep 2014 16:01:23 -0000 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Original-Sender: Rich Felker Xref: news.gmane.org gmane.linux.lib.musl.general:6195 gmane.linux.toybox:1367 Archived-At: This message is a follow-up to a discussion Rob Landley and I had on #musl regarding musl's returning an error of EINVAL when the AT_SYM_NOFOLLOW flag is passed to faccessat (a nonstandard usage), which is affecting toybox. Rob's idea for using it came from the Linux man pages, which document this flag as supported and do not make it clear that it's glibc, not Linux, providing the support. Issue 1: Is the inclusion of AT_SYM_NOFOLLOW in the man page a total documentation error (not actually supported by glibc at all) or just a failure to mark it as a glibc extension? Here's the relevant glibc file: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/faccessat.c;h=4a6048ec7930c8fc249ee629b1d2618cd81084b0;hb=HEAD As I read it: 1. It sets EINVAL for flags that are invalid, but considers AT_SYM_NOFOLLOW valid. So far so good... 2. It flag is 0 or the only flag set is AT_EACCESS and the binary is not suid, it just makes the syscall directly. OOPS, big bug -- it does not honor changes to the effective uid made by programs initially started as root! 3. Otherwise, it uses fstatat, possibly with the AT_SYM_NOFOLLOW flag, to get the file ownership and mode and performs its own access permissions check in userspace. This is imprecise and does not respect ACLs or any other advanced permission models provided by LSMs etc. I was not even aware that this imprecise emulation was used in the AT_SYM_NOFOLLOW case; I figured they would do it in an exact way, which is possible with some /proc/self/fd tricks. So my conclusion? There are some moderate-level documentation errors. glibc implements the flag, but not correctly. The changes I would recommend to the documentation: 1. Document that AT_SYM_NOFOLLOW is not standard for this function, and is a glibc extension. (uclibc is just a copy of glibc code) 2. Document that AT_SYM_NOFOLLOW and AT_EACCESS are emulated and unreliable on glibc. 3. Document that the man page is covering the POSIX/glibc function details, and the kernel syscall does not support flags at all. (This might aid in getting the kernel folks to add a new faccessat4 syscall that would do flags at the kernel level.) Do these sound reasonable? Issue 2: Should musl support or ignore the AT_SYM_NOFOLLOW with faccessat? If anyone would like to see support, I can consider it for a future agenda item (and of course: patches welcome), but I'm not going to add an implementation that reports incorrect information. Just ignoring the flag would give the wrong results (possibly dangerous) and would leave the application no way to know that the flag was ignored (whereas failing with EINVAL makes it clear, and is explicitly documented as an optional error condition for invalid flags). However: Issue 3: Does the AT_SYM_NOFOLLOW flag even make sense with faccessat? The whole point of AT_SYM_NOFOLLOW is to avoid TOCTOU races checking for symlinks. However, any use of faccessat is fundamentally a TOCTOU race -- the information it obtained is not necessarily correct by the time it returns. Reducing two TOCTOU issues in succession to one TOCTOU issue does not seem useful for most purposes. Issue 4: Does faccessat, with or without AT_SYM_NOFOLLOW, make sense for implementing rm -rf? No. At best it's a wasted syscall that slows you down, and at worst it gives you wrong information. The efficient and correct implementation is to simply _try_ the operation which might fail (openat?) and only change file permissions and retry if it failed with EACCESS. This requires zero extra syscalls in the success case (versus one extra with faccessat). As for AT_SYM_NOFOLLOW, I'm not clear why it was being used. Even if the inaccessible file is a symlink target, you'd need to use AT_SYM_NOFOLLOW or similar when doing the fchmodat, and that one's what actually protects you from races used to trick rm into changing permissions on files it shouldn't. Use of the result from faccessat to make the decision is a TOCTOU race. Rich