From patchwork Tue Feb 19 23:23:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Sandeen X-Patchwork-Id: 10820853 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7054F1399 for ; Tue, 19 Feb 2019 23:23:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5A97D2D305 for ; Tue, 19 Feb 2019 23:23:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 49A202D53C; Tue, 19 Feb 2019 23:23:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,RCVD_IN_RP_RNBL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E6DDB2D305 for ; Tue, 19 Feb 2019 23:23:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727375AbfBSXXk (ORCPT ); Tue, 19 Feb 2019 18:23:40 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45839 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726405AbfBSXXk (ORCPT ); Tue, 19 Feb 2019 18:23:40 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E24FF81DF9 for ; Tue, 19 Feb 2019 23:23:39 +0000 (UTC) Received: from [IPv6:::1] (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id B5F59600C0 for ; Tue, 19 Feb 2019 23:23:39 +0000 (UTC) Subject: [PATCH 2/3] xfs_io: fix TOCTOU in openfile() To: linux-xfs References: From: Eric Sandeen Message-ID: Date: Tue, 19 Feb 2019 17:23:38 -0600 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Thunderbird/60.5.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 19 Feb 2019 23:23:39 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP openfile() stats a path to determine whether it is a pipe, and then opens it with flags based on the type it saw during the stat. It's possible that the file at that path changes in between, and Coverity points this out. Instead, always open O_NONBLOCK, stat the fd we got, and turn the flag back off via fcntl() if it's not a pipe. Addresses-Coverity-ID: 1442788 ("Time of check time of use") Signed-off-by: Eric Sandeen diff --git a/io/open.c b/io/open.c index f5fbd2c..856018b 100644 --- a/io/open.c +++ b/io/open.c @@ -62,6 +62,12 @@ openfile( int oflags; oflags = flags & IO_READONLY ? O_RDONLY : O_RDWR; + /* + * In case we've been passed a pipe to open, don't block waiting for a + * reader or writer to appear. We want to either succeed or error out + * immediately. We'll clear O_NONBLOCK if it's not a pipe. + */ + oflags |= O_NONBLOCK; if (flags & IO_APPEND) oflags |= O_APPEND; if (flags & IO_CREAT) @@ -81,18 +87,6 @@ openfile( if (flags & IO_NOFOLLOW) oflags |= O_NOFOLLOW; - /* - * if we've been passed a pipe to open, don't block waiting for a - * reader or writer to appear. We want to either succeed or error out - * immediately. - */ - if (stat(path, &st) < 0 && errno != ENOENT) { - perror("stat"); - return -1; - } - if (S_ISFIFO(st.st_mode)) - oflags |= O_NONBLOCK; - fd = open(path, oflags, mode); if (fd < 0) { if (errno == EISDIR && @@ -112,6 +106,22 @@ openfile( } } + if (fstat(fd, &st) < 0) { + perror("stat"); + close(fd); + return -1; + } + + /* We only want to keep nonblocking behavior for pipes */ + if (!S_ISFIFO(st.st_mode)) { + oflags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, oflags) < 0) { + perror("fcntl"); + close(fd); + return -1; + } + } + if (!geom || !platform_test_xfs_fd(fd)) return fd;