Thread (26 messages) 26 messages, 5 authors, 2018-11-11

Re: [PATCH v3 resend 1/2] mm: Add an F_SEAL_FUTURE_WRITE seal to memfd

From: Andy Lutomirski <luto@amacapital.net>
Date: 2018-11-10 19:55:10
Also in: linux-fsdevel, linux-kselftest, linux-mm, lkml

Possibly related (same subject, not in this thread)

On Nov 10, 2018, at 11:11 AM, Daniel Colascione [off-list ref] wrote:
quoted
On Sat, Nov 10, 2018 at 10:45 AM, Daniel Colascione [off-list ref] wrote:
quoted
On Sat, Nov 10, 2018 at 10:24 AM, Joel Fernandes [off-list ref] wrote:
Thanks Andy for your thoughts, my comments below:
[snip]
quoted
quoted
I don't see it as warty, different seals will work differently. It works
quite well for our usecase, and since Linux is all about solving real
problems in the real work, it would be useful to have it.
quoted
- causes a probably-observable effect in the file mode in F_GETFL.
Wouldn't that be the right thing to observe anyway?
quoted
- causes reopen to fail.
So this concern isn't true anymore if we make reopen fail only for WRITE
opens as Daniel suggested. I will make this change so that the security fix
is a clean one.
quoted
- does *not* affect other struct files that may already exist on the same inode.
TBH if you really want to block all writes to the file, then you want
F_SEAL_WRITE, not this seal. The usecase we have is the fd is sent over IPC
to another process and we want to prevent any new writes in the receiver
side. There is no way this other receiving process can have an existing fd
unless it was already sent one without the seal applied.  The proposed seal
could be renamed to F_SEAL_FD_WRITE if that is preferred.
quoted
- mysteriously malfunctions if you try to set it again on another struct
file that already exists
I didn't follow this, could you explain more?
quoted
- probably is insecure when used on hugetlbfs.
The usecase is not expected to prevent all writes, indeed the usecase
requires existing mmaps to continue to be able to write into the memory map.
So would you call that a security issue too? The use of the seal wants to
allow existing mmap regions to be continue to be written into (I mentioned
more details in the cover letter).
quoted
I see two reasonable solutions:

1. Don’t fiddle with the struct file at all. Instead make the inode flag
work by itself.
Currently, the various VFS paths check only the struct file's f_mode to deny
writes of already opened files. This would mean more checking in all those
paths (and modification of all those paths).

Anyway going with that idea, we could
1. call deny_write_access(file) from the memfd's seal path which decrements
the inode::i_writecount.
2. call get_write_access(inode) in the various VFS paths in addition to
checking for FMODE_*WRITE and deny the write (incase i_writecount is negative)

That will prevent both reopens, and writes from succeeding. However I worry a
bit about 2 not being too familiar with VFS internals, about what the
consequences of doing that may be.
IMHO, modifying both the inode and the struct file separately is fine,
since they mean different things. In regular filesystems, it's fine to
have a read-write open file description for a file whose inode grants
write permission to nobody. Speaking of which: is fchmod enough to
prevent this attack?
Well, yes and no. fchmod does prevent reopening the file RW, but
anyone with permissions (owner, CAP_FOWNER) can just fchmod it back. A
seal is supposed to be irrevocable, so fchmod-as-inode-seal probably
isn't sufficient by itself. While it might be good enough for Android
(in the sense that it'll prevent RW-reopens from other security
contexts to which we send an open memfd file), it's still conceptually
ugly, IMHO. Let's go with the original approach of just tweaking the
inode so that open-for-write is permanently blocked.
This should be straightforward. Just add a new seal type and wire it up. It should be considerably simpler than SEAL_WRITE.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help