lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200830163657.GD3265@brightrain.aerifal.cx>
Date:   Sun, 30 Aug 2020 12:36:58 -0400
From:   Rich Felker <dalias@...c.org>
To:     Jann Horn <jannh@...gle.com>
Cc:     linux-fsdevel <linux-fsdevel@...r.kernel.org>,
        kernel list <linux-kernel@...r.kernel.org>,
        Linux API <linux-api@...r.kernel.org>,
        Alexander Viro <viro@...iv.linux.org.uk>
Subject: Re: [RESEND PATCH] vfs: add RWF_NOAPPEND flag for pwritev2

On Sun, Aug 30, 2020 at 05:05:45PM +0200, Jann Horn wrote:
> On Sat, Aug 29, 2020 at 4:00 AM Rich Felker <dalias@...c.org> 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.
> [...]
> > diff --git a/include/linux/fs.h b/include/linux/fs.h
> [...]
> > @@ -3411,6 +3413,8 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags)
> >                 ki->ki_flags |= (IOCB_DSYNC | IOCB_SYNC);
> >         if (flags & RWF_APPEND)
> >                 ki->ki_flags |= IOCB_APPEND;
> > +       if (flags & RWF_NOAPPEND)
> > +               ki->ki_flags &= ~IOCB_APPEND;
> >         return 0;
> >  }
> 
> Linux enforces the S_APPEND flag (set by "chattr +a") only at open()
> time, not at write() time:
> 
> # touch testfile
> # exec 100>testfile
> # echo foo > testfile
> # cat testfile
> foo
> # chattr +a testfile
> # echo bar > testfile
> bash: testfile: Operation not permitted
> # echo bar >&100
> # cat testfile
> bar
> #
> 
> At open() time, the kernel enforces that you can't use O_WRONLY/O_RDWR
> without also setting O_APPEND if the file is marked as append-only:
> 
> static int may_open(const struct path *path, int acc_mode, int flag)
> {
> [...]
>   /*
>    * An append-only file must be opened in append mode for writing.
>    */
>   if (IS_APPEND(inode)) {
>     if  ((flag & O_ACCMODE) != O_RDONLY && !(flag & O_APPEND))
>       return -EPERM;
>     if (flag & O_TRUNC)
>       return -EPERM;
>   }
> [...]
> }
> 
> 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. 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.

Rich

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ