Re: [PATCH v2 16/16] fs: create {sb,file}_write_not_started() helpers

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

 



On Fri, Nov 24, 2023 at 6:17 AM Jan Kara <jack@xxxxxxx> wrote:
>
> On Wed 22-11-23 14:27:15, Amir Goldstein wrote:
> > Create new helpers {sb,file}_write_not_started() that can be used
> > to assert that sb_start_write() is not held.
> >
> > This is needed for fanotify "pre content" events.
> >
> > Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
>
> I'm not against this but I'm somewhat wondering, where exactly do you plan
> to use this :) (does not seem to be in this patch set).

As I wrote in the cover letter:
"The last 3 patches are helpers that I used in fanotify patches to
 assert that permission hooks are called with expected locking scope."

But this is just half of the story.

The full story is that I added it in fsnotify_file_perm() hook to check
that we caught all the places that permission hook was called with
sb_writers held:

 static inline int fsnotify_file_perm(struct file *file, int mask)
 {
       struct inode *inode = file_inode(file);
       __u32 fsnotify_mask;

       /*
        * Content of file may be written on pre-content events, so sb freeze
        * protection must not be held.
        */
       lockdep_assert_once(file_write_not_started(file));

       /*
        * Pre-content events are only reported for regular files and dirs.
        */
       if (mask & MAY_READ) {


And the assert triggered in a nested overlay case (overlay over overlay).
So I cannot keep the assert in the final patch as is.
I can probably move it into (mask & MAY_WRITE) case, because
I don't know of any existing write permission hook that is called with
sb_wrtiers held.

I also plan to use sb_write_not_started() in fsnotify_lookup_perm().

I think that:
"This is needed for fanotify "pre content" events."
sums this up nicely without getting into gory details ;)

> Because one easily
> forgets about the subtle implementation details and uses
> !sb_write_started() instead of sb_write_not_started()...
>

I think I had a comment in one version that said:
"This is NOT the same as !sb_write_started()"

We can add it back if you think it is useful, but FWIW, anyone
can use !sb_write_started() wrongly today whether we add
sb_write_not_started() or not.

But this would be pretty easy to detect - running a build without
CONFIG_LOCKDEP will catch this misuse pretty quickly.

Thanks,
Amir.

>
> > ---
> >  include/linux/fs.h | 26 ++++++++++++++++++++++++++
> >  1 file changed, 26 insertions(+)
> >
> > diff --git a/include/linux/fs.h b/include/linux/fs.h
> > index 05780d993c7d..c085172f832f 100644
> > --- a/include/linux/fs.h
> > +++ b/include/linux/fs.h
> > @@ -1669,6 +1669,17 @@ static inline bool sb_write_started(const struct super_block *sb)
> >       return __sb_write_started(sb, SB_FREEZE_WRITE);
> >  }
> >
> > +/**
> > + * sb_write_not_started - check if SB_FREEZE_WRITE is not held
> > + * @sb: the super we write to
> > + *
> > + * May be false positive with !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN.
> > + */
> > +static inline bool sb_write_not_started(const struct super_block *sb)
> > +{
> > +     return __sb_write_started(sb, SB_FREEZE_WRITE) <= 0;
> > +}
> > +
> >  /**
> >   * file_write_started - check if SB_FREEZE_WRITE is held
> >   * @file: the file we write to
> > @@ -1684,6 +1695,21 @@ static inline bool file_write_started(const struct file *file)
> >       return sb_write_started(file_inode(file)->i_sb);
> >  }
> >
> > +/**
> > + * file_write_not_started - check if SB_FREEZE_WRITE is not held
> > + * @file: the file we write to
> > + *
> > + * May be false positive with !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN.
> > + * May be false positive with !S_ISREG, because file_start_write() has
> > + * no effect on !S_ISREG.
> > + */
> > +static inline bool file_write_not_started(const struct file *file)
> > +{
> > +     if (!S_ISREG(file_inode(file)->i_mode))
> > +             return true;
> > +     return sb_write_not_started(file_inode(file)->i_sb);
> > +}
> > +
> >  /**
> >   * sb_end_write - drop write access to a superblock
> >   * @sb: the super we wrote to
> > --
> > 2.34.1
> >
> --
> Jan Kara <jack@xxxxxxxx>
> SUSE Labs, CR





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux