From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 98795 invoked by alias); 17 Sep 2015 15:37:57 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 97743 invoked by uid 89); 17 Sep 2015 15:37:56 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=AWL,BAYES_50,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-qk0-f171.google.com Received: from mail-qk0-f171.google.com (HELO mail-qk0-f171.google.com) (209.85.220.171) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Thu, 17 Sep 2015 15:37:54 +0000 Received: by qkap81 with SMTP id p81so8048146qka.2; Thu, 17 Sep 2015 08:37:52 -0700 (PDT) X-Received: by 10.55.31.65 with SMTP id f62mr53005039qkf.6.1442504272154; Thu, 17 Sep 2015 08:37:52 -0700 (PDT) Received: from [192.168.0.26] (97-122-175-227.hlrn.qwest.net. [97.122.175.227]) by smtp.gmail.com with ESMTPSA id e131sm1493951qhc.10.2015.09.17.08.37.50 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2015 08:37:51 -0700 (PDT) Message-ID: <55FADE4C.5000404@gmail.com> Date: Thu, 17 Sep 2015 15:40:00 -0000 From: Martin Sebor User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Jonathan Wakely CC: libstdc++ , gcc-patches Subject: Re: [patch] libstdc++/67173 Fix filesystem::canonical for Solaris 10. References: <20150911142140.GL2631@redhat.com> <55F311D2.8050405@gmail.com> <55F469CF.9010503@gmail.com> <20150916144207.GY2631@redhat.com> <55F9A8A8.3060502@gmail.com> <20150916185844.GD2631@redhat.com> <55F9E75F.10602@gmail.com> <20150916221727.GF2631@redhat.com> <55F9FE71.1060901@gmail.com> <20150917111615.GH2631@redhat.com> In-Reply-To: <20150917111615.GH2631@redhat.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2015-09/txt/msg01300.txt.bz2 On 09/17/2015 05:16 AM, Jonathan Wakely wrote: > On 16/09/15 17:42 -0600, Martin Sebor wrote: >> I see now the first exists test will detect symlink loops in >> the original path. But I'm not convinced there isn't a corner >> case that's subject to a TOCTOU race condition between the first >> exists test and the while loop during which a symlink loop can >> be introduced. >> >> Suppose we call the function with /foo/bar as an argument and >> the path exists and contains no symlinks. result is / and cmpts >> is set to { foo, bar }. Just as the loop is entered, /foo/bar >> is replaced with a symlink containing /foo/bar. The loop then >> proceeds like so: >> >> 1. The first iteration removes foo from cmpts and sets result >> to /foo. cmpts is { bar }. >> >> 2. The second iteration removes bar from cmpts, sets result to >> /foo/bar, determines it's a symlink, reads its contents, sees >> it's an absolute pathname and replaces result with /. It then >> inserts the symlink's components { foo, bar } into cmpts. cmpts >> becomes { foo, bar }. exists(result) succeeds. >> >> 3. The next iteration of the loop has the same initial state >> as the first. >> >> But I could have very easily missed something that takes care >> of this corner case. If I did, sorry for the false alarm! > > No, you're right. The TS says such filesystem races are undefined: > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4099.html#fs.race.behavior > > but it would be nice to fail gracefully rather than DOS the > application. > > The simplest approach would be to increment a counter every time we > follow a symlink, and if it reaches some limit decide something is > wrong and fail with ELOOP. > > I don't see how anything else can be 100% bulletproof, because a truly > evil attacker could just keep altering the contents of symlinks so we > keep ping-ponging between two or more paths. If we keep track of paths > we've seen before the attacker could just keep changing the contents > to a unique path each time, that initially exists as a file, but by > the time we get to is_symlink() its become a symlink to a new path. > > So if we use a counter, what's a sane maximum? Is MAXSYMLINKS in > the value the kernel uses? 20 seems quite low, I was > thinking of a much higher number. Yes, it is a corner case, and it's not really avoidable in the case of hard links. For symlinks, POSIX defines the SYMLOOP_MAX constant as the maximum, with the _SC_SYMLOOP_MAX and _PC_SYMLOOP_MAX sysconf and pathconf variables. Otherwise 40 seems reasonable. With this, I'll let you get back to work -- I think we've beat this function to death ;) Martin