Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp512489pxk; Sun, 30 Aug 2020 12:04:16 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwaRQxnsJwzD8Ci8iok+paCNADEvci3Pp2Uq+8cvMzkYKfKclE22iRnMYbSc99byxUdsOMd X-Received: by 2002:a17:906:69d5:: with SMTP id g21mr8346385ejs.461.1598814255836; Sun, 30 Aug 2020 12:04:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1598814255; cv=none; d=google.com; s=arc-20160816; b=Ww8P0tOplUjgDTfhurQ6PXyhkVpElFHukgNLOJL+kvLr0UHDmKTqnsa4zDVt5qeqXc Nm+kuF5UNXbKDC9ED1gZGXRCH7ysupsnEYgC8seZARtXFZNh8Nx4sHsUT6ljWIHPjf1E KmFxts/fvtAK4dgeBmYrbKPYSam1kec5d8lkm0qUC7g3Y3uUu2xClIKwYPT3FbJUWKDN Mj2f6dIovboeYM5yYo2i0ZjZIzSXr1cbzLKBkDLjl2VaP287Yh0OJ0UgmPPDWos7LnUB /XIjItsL0Hx8XN6c+GfWyTSrNm++ykHcvwFWXUW+6Eok8+H6Ti/ikANjVrzzgUvGIeFX 04mg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=kZKdmJoSrqH9H4OC01i8QEPZEiSSbw2/cpeusSfExI8=; b=c/Kgt5b+/N2gbnSid34DVUMDWtszNm25UJDB6BoMRyIbAbypRDlF43koha5GIVm/Om b73xjGqfjyvzvvt7ve0iip6P5BY6bzuueg59766P3r5WbyZJOWpa1K+2L7LhDsEShb7M KlL2Obh19MbL7BjliI7fQwNpEB/U66zbsP60oHDPW0JCGGb5iWOlnHsBtXqtHPyfLQ+w 2FHN/Nnw4UbPOZV4yyMdcjxYw53rSlAaPOQA8i+ktMxtvYr6lSex77rdhhOUw2078KO6 yNPPPk8kzmWxQAGGTa8DrSN32CfkHDbo50nRHaKZWu9JuRYTWkNQwCH7jrA1k+vlA6xc OBSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=ZebtGy+h; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w20si4147169ejj.711.2020.08.30.12.03.51; Sun, 30 Aug 2020 12:04:15 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=ZebtGy+h; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726412AbgH3TDG (ORCPT + 99 others); Sun, 30 Aug 2020 15:03:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726201AbgH3TDF (ORCPT ); Sun, 30 Aug 2020 15:03:05 -0400 Received: from mail-lj1-x242.google.com (mail-lj1-x242.google.com [IPv6:2a00:1450:4864:20::242]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DDBF1C061573 for ; Sun, 30 Aug 2020 12:03:04 -0700 (PDT) Received: by mail-lj1-x242.google.com with SMTP id c2so168498ljj.12 for ; Sun, 30 Aug 2020 12:03:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=kZKdmJoSrqH9H4OC01i8QEPZEiSSbw2/cpeusSfExI8=; b=ZebtGy+hRVgFT9b5YzuE6Bu4vNXZ9JfVwfXq203IY1zz6YVYlMvMexxdlXaFkSBZv6 KwQJSI+DidyJLBQMT5X9+ZQQk2lN+hMsvJqMrix+kSpHpT84YlSNzU0XpkarIOTIDH3o +UbAAP6DgYuU9jbkhTeoKhVrlGx3TGZVmG69DEtI6fBvRfEbdzq5AnU8iNJz7mjXYmXk 9anfz367rI51xOzKFAY9QV0NIoNUQ8p1l5BvDtrDCYp2Sz4cMmu+WQzpLQ8rIQLLQyqg tN2MWlFuWqye8xMtiRTjgsE6EsKO962SaCc2CplTaIXTGM7mdPFfJb+siLon+vig9e3+ xCyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=kZKdmJoSrqH9H4OC01i8QEPZEiSSbw2/cpeusSfExI8=; b=hzfhvSKUAg+4jWhgc3OpXIjmAtQ3FVevYp4KwGk5towuucUg8Zd/LWe9rKzZpQ/Sdn zZmY6WtxhdutChihXureLpkFHp602gsv259hIlKDXmeiUxypsaBC0eJlLU/tn6vav6xR GYqowNH6X6WcvzAJ2lrX/r8CkjtPP/xS6qLpLgmEIphb02dxd7qWKfHfvi5jo5RxV/js iMnkWexpMHSKrS0bIsTa7ZPR+AVnU932bWHl8/zXbeLu+wDtMrxV8Uvfril13Lzc04gX PeCgWke0QmsSjC/Y7hgQL6giCzke2AqwxBNzwR2XWjh1d5N9eBFv0R1UG/70Q23rzC3y sGlw== X-Gm-Message-State: AOAM531ejYv7Vwg686Lf5TWI8oJies7dUfmU9ZPbI0UNoAgBDC11CbxD 2a2PIf0oRr+Bey0keRi0JBrcMfmtlQxAdx/uXXETUD8fghM= X-Received: by 2002:a05:651c:543:: with SMTP id q3mr3599894ljp.145.1598814177899; Sun, 30 Aug 2020 12:02:57 -0700 (PDT) MIME-Version: 1.0 References: <20200829020002.GC3265@brightrain.aerifal.cx> <20200830163657.GD3265@brightrain.aerifal.cx> <20200830184334.GE3265@brightrain.aerifal.cx> In-Reply-To: <20200830184334.GE3265@brightrain.aerifal.cx> From: Jann Horn Date: Sun, 30 Aug 2020 21:02:31 +0200 Message-ID: Subject: Re: [RESEND PATCH] vfs: add RWF_NOAPPEND flag for pwritev2 To: Rich Felker Cc: linux-fsdevel , kernel list , Linux API , Alexander Viro Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sun, Aug 30, 2020 at 8:43 PM Rich Felker wrote: > On Sun, Aug 30, 2020 at 08:31:36PM +0200, Jann Horn wrote: > > On Sun, Aug 30, 2020 at 6:36 PM Rich Felker wrote: > > > On Sun, Aug 30, 2020 at 05:05:45PM +0200, Jann Horn wrote: > > > > On Sat, Aug 29, 2020 at 4:00 AM Rich Felker wrote: > > > > > The pwrite function, originally defined by POSIX (thus the "p"), is > > > > > defined to ignore O_APPEND and write at the offset passed as its > > > > > argument. However, historically Linux honored O_APPEND if set and > > > > > ignored the offset. This cannot be changed due to stability policy, > > > > > but is documented in the man page as a bug. > > > > > > > > > > Now that there's a pwritev2 syscall providing a superset of the pwrite > > > > > functionality that has a flags argument, the conforming behavior can > > > > > be offered to userspace via a new flag. > > [...] > > > > Linux enforces the S_APPEND flag (set by "chattr +a") only at open() > > > > time, not at write() time: > > [...] > > > > It seems to me like your patch will permit bypassing S_APPEND by > > > > opening an append-only file with O_WRONLY|O_APPEND, then calling > > > > pwritev2() with RWF_NOAPPEND? I think you'll have to add an extra > > > > check for IS_APPEND() somewhere. > > > > > > > > > > > > One could also argue that if an O_APPEND file descriptor is handed > > > > across privilege boundaries, a programmer might reasonably expect that > > > > the recipient will not be able to use the file descriptor for > > > > non-append writes; if that is not actually true, that should probably > > > > be noted in the open.2 manpage, at the end of the description of > > > > O_APPEND. > > > > > > fcntl F_SETFL can remove O_APPEND, so it is not a security boundary. > > > I'm not sure how this interacts with S_APPEND; presumably fcntl > > > rechecks it. > > > > Ah, good point, you're right. In fs/fcntl.c: > > > > 35 static int setfl(int fd, struct file * filp, unsigned long arg) > > 36 { > > 37 struct inode * inode = file_inode(filp); > > 38 int error = 0; > > 39 > > 40 /* > > 41 * O_APPEND cannot be cleared if the file is marked as append-only > > 42 * and the file is open for write. > > 43 */ > > 44 if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode)) > > 45 return -EPERM; > > FWIW I think this check is mildly wrong; it seems to disallow *adding* > O_APPEND if the file became chattr +a after it was opened. It should > probably be changed to only disallow removal. Yeah... > > > So just checking IS_APPEND in the code paths used by > > > pwritev2 (and erroring out rather than silently writing output at the > > > wrong place) should suffice to preserve all existing security > > > invariants. > > > > Makes sense. > > There are 3 places where kiocb_set_rw_flags is called with flags that > seem to be controlled by userspace: aio.c, io_uring.c, and > read_write.c. Presumably each needs to EPERM out on RWF_NOAPPEND if > the underlying inode is S_APPEND. To avoid repeating the same logic in > an error-prone way, should kiocb_set_rw_flags's signature be updated > to take the filp so that it can obtain the inode and check IS_APPEND > before accepting RWF_NOAPPEND? It's inline so this should avoid > actually loading anything except in the codepath where > flags&RWF_NOAPPEND is nonzero. You can get the file pointer from ki->ki_filp. See the RWF_NOWAIT branch of kiocb_set_rw_flags().