tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: RFC: renameat2 emulation



> Date: Sat, 14 Sep 2024 16:47:01 +0530
> From: Shiv <coderaccords%gmail.com@localhost>
> 
> As part of my GSoC project, me and my mentor have
> decided to extend support for renameat2 in the compat_linux.
> We have decided to enable support for 2 newer flags, namely
> RENAME_NOREPLACE and RENAME_EXCHANGE.

For context, here is the Linux documentation:

https://man7.org/linux/man-pages/man2/rename.2.html

   renameat2()
       renameat2() has an additional flags argument.  A renameat2() call
       with a zero flags argument is equivalent to renameat().

       The flags argument is a bit mask consisting of zero or more of
       the following flags:

       RENAME_EXCHANGE
              Atomically exchange oldpath and newpath.  Both pathnames
              must exist but may be of different types (e.g., one could
              be a non-empty directory and the other a symbolic link).

       RENAME_NOREPLACE
              Don't overwrite newpath of the rename.  Return an error if
              newpath already exists.

How widely used are these operations in the real world?  Do important
applications rely on them or were they invented for theoretical needs
of test suites?

>                                       There are
> 2 particular questions, on which we would like to gather communities
> insights:
> 
> 1. To prevent TOCTOU attack and provide atomicity, most of the
> renameat code has been reimplemented in the compat layer. Is
> this an acceptable approach or are there some better alternatives?
> 
> 2. RENAME_EXCHANGE requires atomic swap of filenames and the
> filetypes need not be the same. Can any of the existing VFS operations
> be used to do so? And if this should be done in VFS layer or any specific
> support is expected from the file system to implement this?

I don't think either of these can be implemented correctly without
substantial changes to the vfs interface and all file systems.

In particular, the entire locking dance in do_sys_renameat is an
essentially useless artefact of the hopelessly broken VOP_RENAME
protocol which we haven't finished eliminating yet.

Even if you're careful to take locks in exactly the same way as
do_sys_renameat, the file systems that use genfs_rename -- i.e., the
ones that have a chance of working reliably -- will just drop all the
locks you'd taken and start over from scratch.  So you won't prevent
TOCTOU or achieve atomicity.

Once all file systems have been adapted to use genfs_rename, we can
get rid of the existing VOP_RENAME and replace it by something more
sensible, and then delete all that code in do_sys_renameat.  But
progress toward converting all file systems to genfs_rename has
stalled.

(Remaining file systems: coda (if it works), nilfs (which I thought
was read-only?), puffs, sysvbfs, v7fs, chfs, zfs, and the
pseudo-file-systems union/null/umap/layer/...)

If we wanted to make further changes to the rename protocol without
waiting to finish converting all file systems to genfs_rename, we
could:

1. change VOP_RENAME to VOP_RENAME_LEGACY,

2. add VOP_RENAME_MODERN or whatever with the signature of
   genfs_sane_rename (more or less),

3. create genfs_legacy_rename and move the current logic of
   do_sys_renameat into that (this implements VOP_RENAME_MODERN in
   terms of VOP_RENAME_LEGACY),

4. change do_sys_renameat to use VOP_RENAME_MODERN, and

5. do a switcheroo in every file system (implement VOP_RENAME_MODERN
   using genfs_sane_rename where it's already done, or using
   genfs_legacy_rename where it's not).

And then we could pass flags through the new VOP_RENAME_MODERN, with
some care to make sure file systems don't claim success for flags they
don't understand.  We already have one weird flag in genfs_rename --
posixly_correct -- so it's not that much of a stretch to pass others
through.


Home | Main Index | Thread Index | Old Index