Merge tag 'v6.4/vfs.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 24 Apr 2023 20:39:58 +0000 (13:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 24 Apr 2023 20:39:58 +0000 (13:39 -0700)
Pull misc vfs updates from Christian Brauner:
 "This contains a pile of various smaller fixes. Most of them aren't
  very interesting so this just highlights things worth mentioning:

   - Various filesystems contained the same little helper to convert
     from the mode of a dentry to the DT_* type of that dentry.

     They have now all been switched to rely on the generic
     fs_umode_to_dtype() helper. All custom helpers are removed (Jeff)

   - Fsnotify now reports ACCESS and MODIFY events for splice
     (Chung-Chiang Cheng)

   - After converting timerfd a long time ago to rely on
     wait_event_interruptible_*() apis, convert eventfd as well. This
     removes the complex open-coded wait code (Wen Yang)

   - Simplify sysctl registration for devpts, avoiding the declaration
     of two tables. Instead, just use a prefixed path with
     register_sysctl() (Luis)

   - The setattr_should_drop_sgid() helper is now exported so NFS can
     use it. By switching NFS to this helper an NFS setgid inheritance
     bug is fixed (me)"

* tag 'v6.4/vfs.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  fs: hfsplus: remove WARN_ON() from hfsplus_cat_{read,write}_inode()
  pnode: pass mountpoint directly
  eventfd: use wait_event_interruptible_locked_irq() helper
  splice: report related fsnotify events
  fs: consolidate duplicate dt_type helpers
  nfs: use vfs setgid helper
  Update relatime comments to include equality
  fs/buffer: Remove redundant assignment to err
  fs_context: drop the unused lsm_flags member
  fs/namespace: fnic: Switch to use %ptTd
  Documentation: update idmappings.rst
  devpts: simplify two-level sysctl registration for pty_kern_table
  eventpoll: align comment with nested epoll limitation

21 files changed:
Documentation/filesystems/idmappings.rst
Documentation/filesystems/mount_api.rst
fs/attr.c
fs/buffer.c
fs/configfs/dir.c
fs/devpts/inode.c
fs/eventfd.c
fs/eventpoll.c
fs/hfsplus/inode.c
fs/inode.c
fs/internal.h
fs/kernfs/dir.c
fs/libfs.c
fs/namespace.c
fs/nfs/inode.c
fs/nfs/super.c
fs/pnode.c
fs/splice.c
include/linux/fs.h
include/linux/fs_context.h
include/linux/security.h

index b9b31066aef2ce828f0b3288c78ced482a23b85b..ad6d216405768ea46aa28e069de233516187274a 100644 (file)
@@ -241,7 +241,7 @@ according to the filesystem's idmapping as this would give the wrong owner if
 the caller is using an idmapping.
 
 So the kernel will map the id back up in the idmapping of the caller. Let's
-assume the caller has the slighly unconventional idmapping
+assume the caller has the somewhat unconventional idmapping
 ``u3000:k20000:r10000`` then ``k21000`` would map back up to ``u4000``.
 Consequently the user would see that this file is owned by ``u4000``.
 
@@ -320,6 +320,10 @@ and equally wrong::
  from_kuid(u20000:k0:r10000, u1000) = k21000
                              ~~~~~
 
+Since userspace ids have type ``uid_t`` and ``gid_t`` and kernel ids have type
+``kuid_t`` and ``kgid_t`` the compiler will throw an error when they are
+conflated. So the two examples above would cause a compilation failure.
+
 Idmappings when creating filesystem objects
 -------------------------------------------
 
@@ -623,42 +627,105 @@ privileged users in the initial user namespace.
 However, it is perfectly possible to combine idmapped mounts with filesystems
 mountable inside user namespaces. We will touch on this further below.
 
+Filesystem types vs idmapped mount types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+With the introduction of idmapped mounts we need to distinguish between
+filesystem ownership and mount ownership of a VFS object such as an inode. The
+owner of a inode might be different when looked at from a filesystem
+perspective than when looked at from an idmapped mount. Such fundamental
+conceptual distinctions should almost always be clearly expressed in the code.
+So, to distinguish idmapped mount ownership from filesystem ownership separate
+types have been introduced.
+
+If a uid or gid has been generated using the filesystem or caller's idmapping
+then we will use the ``kuid_t`` and ``kgid_t`` types. However, if a uid or gid
+has been generated using a mount idmapping then we will be using the dedicated
+``vfsuid_t`` and ``vfsgid_t`` types.
+
+All VFS helpers that generate or take uids and gids as arguments use the
+``vfsuid_t`` and ``vfsgid_t`` types and we will be able to rely on the compiler
+to catch errors that originate from conflating filesystem and VFS uids and gids.
+
+The ``vfsuid_t`` and ``vfsgid_t`` types are often mapped from and to ``kuid_t``
+and ``kgid_t`` types similar how ``kuid_t`` and ``kgid_t`` types are mapped
+from and to ``uid_t`` and ``gid_t`` types::
+
+ uid_t <--> kuid_t <--> vfsuid_t
+ gid_t <--> kgid_t <--> vfsgid_t
+
+Whenever we report ownership based on a ``vfsuid_t`` or ``vfsgid_t`` type,
+e.g., during ``stat()``, or store ownership information in a shared VFS object
+based on a ``vfsuid_t`` or ``vfsgid_t`` type, e.g., during ``chown()`` we can
+use the ``vfsuid_into_kuid()`` and ``vfsgid_into_kgid()`` helpers.
+
+To illustrate why this helper currently exists, consider what happens when we
+change ownership of an inode from an idmapped mount. After we generated
+a ``vfsuid_t`` or ``vfsgid_t`` based on the mount idmapping we later commit to
+this ``vfsuid_t`` or ``vfsgid_t`` to become the new filesytem wide ownership.
+Thus, we are turning the ``vfsuid_t`` or ``vfsgid_t`` into a global ``kuid_t``
+or ``kgid_t``. And this can be done by using ``vfsuid_into_kuid()`` and
+``vfsgid_into_kgid()``.
+
+Note, whenever a shared VFS object, e.g., a cached ``struct inode`` or a cached
+``struct posix_acl``, stores ownership information a filesystem or "global"
+``kuid_t`` and ``kgid_t`` must be used. Ownership expressed via ``vfsuid_t``
+and ``vfsgid_t`` is specific to an idmapped mount.
+
+We already noted that ``vfsuid_t`` and ``vfsgid_t`` types are generated based
+on mount idmappings whereas ``kuid_t`` and ``kgid_t`` types are generated based
+on filesystem idmappings. To prevent abusing filesystem idmappings to generate
+``vfsuid_t`` or ``vfsgid_t`` types or mount idmappings to generate ``kuid_t``
+or ``kgid_t`` types filesystem idmappings and mount idmappings are different
+types as well.
+
+All helpers that map to or from ``vfsuid_t`` and ``vfsgid_t`` types require
+a mount idmapping to be passed which is of type ``struct mnt_idmap``. Passing
+a filesystem or caller idmapping will cause a compilation error.
+
+Similar to how we prefix all userspace ids in this document with ``u`` and all
+kernel ids with ``k`` we will prefix all VFS ids with ``v``. So a mount
+idmapping will be written as: ``u0:v10000:r10000``.
+
 Remapping helpers
 ~~~~~~~~~~~~~~~~~
 
 Idmapping functions were added that translate between idmappings. They make use
-of the remapping algorithm we've introduced earlier. We're going to look at
-two:
+of the remapping algorithm we've introduced earlier. We're going to look at:
 
-- ``i_uid_into_mnt()`` and ``i_gid_into_mnt()``
+- ``i_uid_into_vfsuid()`` and ``i_gid_into_vfsgid()``
 
-  The ``i_*id_into_mnt()`` functions translate filesystem's kernel ids into
-  kernel ids in the mount's idmapping::
+  The ``i_*id_into_vfs*id()`` functions translate filesystem's kernel ids into
+  VFS ids in the mount's idmapping::
 
    /* Map the filesystem's kernel id up into a userspace id in the filesystem's idmapping. */
    from_kuid(filesystem, kid) = uid
 
-   /* Map the filesystem's userspace id down ito a kernel id in the mount's idmapping. */
+   /* Map the filesystem's userspace id down ito a VFS id in the mount's idmapping. */
    make_kuid(mount, uid) = kuid
 
 - ``mapped_fsuid()`` and ``mapped_fsgid()``
 
   The ``mapped_fs*id()`` functions translate the caller's kernel ids into
   kernel ids in the filesystem's idmapping. This translation is achieved by
-  remapping the caller's kernel ids using the mount's idmapping::
+  remapping the caller's VFS ids using the mount's idmapping::
 
-   /* Map the caller's kernel id up into a userspace id in the mount's idmapping. */
+   /* Map the caller's VFS id up into a userspace id in the mount's idmapping. */
    from_kuid(mount, kid) = uid
 
    /* Map the mount's userspace id down into a kernel id in the filesystem's idmapping. */
    make_kuid(filesystem, uid) = kuid
 
+- ``vfsuid_into_kuid()`` and ``vfsgid_into_kgid()``
+
+   Whenever
+
 Note that these two functions invert each other. Consider the following
 idmappings::
 
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k20000:r10000
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 Assume a file owned by ``u1000`` is read from disk. The filesystem maps this id
 to ``k21000`` according to its idmapping. This is what is stored in the
@@ -669,20 +736,21 @@ would usually simply use the crossmapping algorithm and map the filesystem's
 kernel id up to a userspace id in the caller's idmapping.
 
 But when the caller is accessing the file on an idmapped mount the kernel will
-first call ``i_uid_into_mnt()`` thereby translating the filesystem's kernel id
-into a kernel id in the mount's idmapping::
+first call ``i_uid_into_vfsuid()`` thereby translating the filesystem's kernel
+id into a VFS id in the mount's idmapping::
 
- i_uid_into_mnt(k21000):
+ i_uid_into_vfsuid(k21000):
    /* Map the filesystem's kernel id up into a userspace id. */
    from_kuid(u0:k20000:r10000, k21000) = u1000
 
-   /* Map the filesystem's userspace id down ito a kernel id in the mount's idmapping. */
-   make_kuid(u0:k10000:r10000, u1000) = k11000
+   /* Map the filesystem's userspace id down into a VFS id in the mount's idmapping. */
+   make_kuid(u0:v10000:r10000, u1000) = v11000
 
 Finally, when the kernel reports the owner to the caller it will turn the
-kernel id in the mount's idmapping into a userspace id in the caller's
+VFS id in the mount's idmapping into a userspace id in the caller's
 idmapping::
 
+  k11000 = vfsuid_into_kuid(v11000)
   from_kuid(u0:k10000:r10000, k11000) = u1000
 
 We can test whether this algorithm really works by verifying what happens when
@@ -696,18 +764,19 @@ fails.
 
 But when the caller is accessing the file on an idmapped mount the kernel will
 first call ``mapped_fs*id()`` thereby translating the caller's kernel id into
-a kernel id according to the mount's idmapping::
+a VFS id according to the mount's idmapping::
 
  mapped_fsuid(k11000):
     /* Map the caller's kernel id up into a userspace id in the mount's idmapping. */
     from_kuid(u0:k10000:r10000, k11000) = u1000
 
     /* Map the mount's userspace id down into a kernel id in the filesystem's idmapping. */
-    make_kuid(u0:k20000:r10000, u1000) = k21000
+    make_kuid(u0:v20000:r10000, u1000) = v21000
 
-When finally writing to disk the kernel will then map ``k21000`` up into a
+When finally writing to disk the kernel will then map ``v21000`` up into a
 userspace id in the filesystem's idmapping::
 
+   k21000 = vfsuid_into_kuid(v21000)
    from_kuid(u0:k20000:r10000, k21000) = u1000
 
 As we can see, we end up with an invertible and therefore information
@@ -725,7 +794,7 @@ Example 2 reconsidered
  caller id:            u1000
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k20000:r10000
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 When the caller is using a non-initial idmapping the common case is to attach
 the same idmapping to the mount. We now perform three steps:
@@ -734,12 +803,12 @@ the same idmapping to the mount. We now perform three steps:
 
     make_kuid(u0:k10000:r10000, u1000) = k11000
 
-2. Translate the caller's kernel id into a kernel id in the filesystem's
+2. Translate the caller's VFS id into a kernel id in the filesystem's
    idmapping::
 
-    mapped_fsuid(k11000):
-      /* Map the kernel id up into a userspace id in the mount's idmapping. */
-      from_kuid(u0:k10000:r10000, k11000) = u1000
+    mapped_fsuid(v11000):
+      /* Map the VFS id up into a userspace id in the mount's idmapping. */
+      from_kuid(u0:v10000:r10000, v11000) = u1000
 
       /* Map the userspace id down into a kernel id in the filesystem's idmapping. */
       make_kuid(u0:k20000:r10000, u1000) = k21000
@@ -759,7 +828,7 @@ Example 3 reconsidered
  caller id:            u1000
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k0:r4294967295
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 The same translation algorithm works with the third example.
 
@@ -767,12 +836,12 @@ The same translation algorithm works with the third example.
 
     make_kuid(u0:k10000:r10000, u1000) = k11000
 
-2. Translate the caller's kernel id into a kernel id in the filesystem's
+2. Translate the caller's VFS id into a kernel id in the filesystem's
    idmapping::
 
-    mapped_fsuid(k11000):
-       /* Map the kernel id up into a userspace id in the mount's idmapping. */
-       from_kuid(u0:k10000:r10000, k11000) = u1000
+    mapped_fsuid(v11000):
+       /* Map the VFS id up into a userspace id in the mount's idmapping. */
+       from_kuid(u0:v10000:r10000, v11000) = u1000
 
        /* Map the userspace id down into a kernel id in the filesystem's idmapping. */
        make_kuid(u0:k0:r4294967295, u1000) = k1000
@@ -792,7 +861,7 @@ Example 4 reconsidered
  file id:              u1000
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k0:r4294967295
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 In order to report ownership to userspace the kernel now does three steps using
 the translation algorithm we introduced earlier:
@@ -802,17 +871,18 @@ the translation algorithm we introduced earlier:
 
     make_kuid(u0:k0:r4294967295, u1000) = k1000
 
-2. Translate the kernel id into a kernel id in the mount's idmapping::
+2. Translate the kernel id into a VFS id in the mount's idmapping::
 
-    i_uid_into_mnt(k1000):
+    i_uid_into_vfsuid(k1000):
       /* Map the kernel id up into a userspace id in the filesystem's idmapping. */
       from_kuid(u0:k0:r4294967295, k1000) = u1000
 
-      /* Map the userspace id down into a kernel id in the mounts's idmapping. */
-      make_kuid(u0:k10000:r10000, u1000) = k11000
+      /* Map the userspace id down into a VFS id in the mounts's idmapping. */
+      make_kuid(u0:v10000:r10000, u1000) = v11000
 
-3. Map the kernel id up into a userspace id in the caller's idmapping::
+3. Map the VFS id up into a userspace id in the caller's idmapping::
 
+    k11000 = vfsuid_into_kuid(v11000)
     from_kuid(u0:k10000:r10000, k11000) = u1000
 
 Earlier, the caller's kernel id couldn't be crossmapped in the filesystems's
@@ -828,7 +898,7 @@ Example 5 reconsidered
  file id:              u1000
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k20000:r10000
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 Again, in order to report ownership to userspace the kernel now does three
 steps using the translation algorithm we introduced earlier:
@@ -838,17 +908,18 @@ steps using the translation algorithm we introduced earlier:
 
     make_kuid(u0:k20000:r10000, u1000) = k21000
 
-2. Translate the kernel id into a kernel id in the mount's idmapping::
+2. Translate the kernel id into a VFS id in the mount's idmapping::
 
-    i_uid_into_mnt(k21000):
+    i_uid_into_vfsuid(k21000):
       /* Map the kernel id up into a userspace id in the filesystem's idmapping. */
       from_kuid(u0:k20000:r10000, k21000) = u1000
 
-      /* Map the userspace id down into a kernel id in the mounts's idmapping. */
-      make_kuid(u0:k10000:r10000, u1000) = k11000
+      /* Map the userspace id down into a VFS id in the mounts's idmapping. */
+      make_kuid(u0:v10000:r10000, u1000) = v11000
 
-3. Map the kernel id up into a userspace id in the caller's idmapping::
+3. Map the VFS id up into a userspace id in the caller's idmapping::
 
+    k11000 = vfsuid_into_kuid(v11000)
     from_kuid(u0:k10000:r10000, k11000) = u1000
 
 Earlier, the file's kernel id couldn't be crossmapped in the filesystems's
@@ -899,23 +970,23 @@ from above:::
  caller id:            u1125
  caller idmapping:     u0:k0:r4294967295
  filesystem idmapping: u0:k0:r4294967295
- mount idmapping:      u1000:k1125:r1
+ mount idmapping:      u1000:v1125:r1
 
 1. Map the caller's userspace ids into kernel ids in the caller's idmapping::
 
     make_kuid(u0:k0:r4294967295, u1125) = k1125
 
-2. Translate the caller's kernel id into a kernel id in the filesystem's
+2. Translate the caller's VFS id into a kernel id in the filesystem's
    idmapping::
 
-    mapped_fsuid(k1125):
-      /* Map the kernel id up into a userspace id in the mount's idmapping. */
-      from_kuid(u1000:k1125:r1, k1125) = u1000
+    mapped_fsuid(v1125):
+      /* Map the VFS id up into a userspace id in the mount's idmapping. */
+      from_kuid(u1000:v1125:r1, v1125) = u1000
 
       /* Map the userspace id down into a kernel id in the filesystem's idmapping. */
       make_kuid(u0:k0:r4294967295, u1000) = k1000
 
-2. Verify that the caller's kernel ids can be mapped to userspace ids in the
+2. Verify that the caller's filesystem ids can be mapped to userspace ids in the
    filesystem's idmapping::
 
     from_kuid(u0:k0:r4294967295, k1000) = u1000
@@ -930,24 +1001,25 @@ on their work computer:
  file id:              u1000
  caller idmapping:     u0:k0:r4294967295
  filesystem idmapping: u0:k0:r4294967295
- mount idmapping:      u1000:k1125:r1
+ mount idmapping:      u1000:v1125:r1
 
 1. Map the userspace id on disk down into a kernel id in the filesystem's
    idmapping::
 
     make_kuid(u0:k0:r4294967295, u1000) = k1000
 
-2. Translate the kernel id into a kernel id in the mount's idmapping::
+2. Translate the kernel id into a VFS id in the mount's idmapping::
 
-    i_uid_into_mnt(k1000):
+    i_uid_into_vfsuid(k1000):
       /* Map the kernel id up into a userspace id in the filesystem's idmapping. */
       from_kuid(u0:k0:r4294967295, k1000) = u1000
 
-      /* Map the userspace id down into a kernel id in the mounts's idmapping. */
-      make_kuid(u1000:k1125:r1, u1000) = k1125
+      /* Map the userspace id down into a VFS id in the mounts's idmapping. */
+      make_kuid(u1000:v1125:r1, u1000) = v1125
 
-3. Map the kernel id up into a userspace id in the caller's idmapping::
+3. Map the VFS id up into a userspace id in the caller's idmapping::
 
+    k1125 = vfsuid_into_kuid(v1125)
     from_kuid(u0:k0:r4294967295, k1125) = u1125
 
 So ultimately the caller will be reported that the file belongs to ``u1125``
index 63204d2094fdf4c75ffc5c4131304f960959bdcb..9aaf6ef75eb53b1ef25f20a0641479c48823183e 100644 (file)
@@ -79,7 +79,6 @@ context.  This is represented by the fs_context structure::
                unsigned int            sb_flags;
                unsigned int            sb_flags_mask;
                unsigned int            s_iflags;
-               unsigned int            lsm_flags;
                enum fs_context_purpose purpose:8;
                ...
        };
index aca9ff7aed3331c31848cf6bf7480bd4b9e27187..d60dc1edb526885584bf62b74da1542e271a8f7d 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -47,6 +47,7 @@ int setattr_should_drop_sgid(struct mnt_idmap *idmap,
                return ATTR_KILL_SGID;
        return 0;
 }
+EXPORT_SYMBOL(setattr_should_drop_sgid);
 
 /**
  * setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to
index 9e1e2add541e07a593bcc743d73eb05ed51bfbd9..10390f53f3f529321dada7eec6593a27d0054ca4 100644 (file)
@@ -2581,7 +2581,7 @@ int block_truncate_page(struct address_space *mapping,
        struct inode *inode = mapping->host;
        struct page *page;
        struct buffer_head *bh;
-       int err;
+       int err = 0;
 
        blocksize = i_blocksize(inode);
        length = offset & (blocksize - 1);
@@ -2594,9 +2594,8 @@ int block_truncate_page(struct address_space *mapping,
        iblock = (sector_t)index << (PAGE_SHIFT - inode->i_blkbits);
        
        page = grab_cache_page(mapping, index);
-       err = -ENOMEM;
        if (!page)
-               goto out;
+               return -ENOMEM;
 
        if (!page_has_buffers(page))
                create_empty_buffers(page, blocksize, 0);
@@ -2610,7 +2609,6 @@ int block_truncate_page(struct address_space *mapping,
                pos += blocksize;
        }
 
-       err = 0;
        if (!buffer_mapped(bh)) {
                WARN_ON(bh->b_size != blocksize);
                err = get_block(inode, iblock, bh, 0);
@@ -2634,12 +2632,11 @@ int block_truncate_page(struct address_space *mapping,
 
        zero_user(page, offset, length);
        mark_buffer_dirty(bh);
-       err = 0;
 
 unlock:
        unlock_page(page);
        put_page(page);
-out:
+
        return err;
 }
 EXPORT_SYMBOL(block_truncate_page);
index 4afcbbe63e685f8b4e2d225e3f86360b55bda4ac..18677cd4e62f543187966501bb52364b5f6b3a55 100644 (file)
@@ -1599,12 +1599,6 @@ static int configfs_dir_close(struct inode *inode, struct file *file)
        return 0;
 }
 
-/* Relationship between s_mode and the DT_xxx types */
-static inline unsigned char dt_type(struct configfs_dirent *sd)
-{
-       return (sd->s_mode >> 12) & 15;
-}
-
 static int configfs_readdir(struct file *file, struct dir_context *ctx)
 {
        struct dentry *dentry = file->f_path.dentry;
@@ -1654,7 +1648,8 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)
                name = configfs_get_name(next);
                len = strlen(name);
 
-               if (!dir_emit(ctx, name, len, ino, dt_type(next)))
+               if (!dir_emit(ctx, name, len, ino,
+                             fs_umode_to_dtype(next->s_mode)))
                        return 0;
 
                spin_lock(&configfs_dirent_lock);
index 4f25015aa5342a332c76ad7d931a507784eea764..fe3db0eda8e47e00384ad352a97c9df360175a9a 100644 (file)
@@ -72,24 +72,6 @@ static struct ctl_table pty_table[] = {
        {}
 };
 
-static struct ctl_table pty_kern_table[] = {
-       {
-               .procname       = "pty",
-               .mode           = 0555,
-               .child          = pty_table,
-       },
-       {}
-};
-
-static struct ctl_table pty_root_table[] = {
-       {
-               .procname       = "kernel",
-               .mode           = 0555,
-               .child          = pty_kern_table,
-       },
-       {}
-};
-
 struct pts_mount_opts {
        int setuid;
        int setgid;
@@ -630,7 +612,7 @@ static int __init init_devpts_fs(void)
 {
        int err = register_filesystem(&devpts_fs_type);
        if (!err) {
-               register_sysctl_table(pty_root_table);
+               register_sysctl("kernel/pty", pty_table);
        }
        return err;
 }
index 249ca6c0b7843ff1fa9d102ad14c15e54c0ad578..95850a13ce8d01a79658a7c04748f12914d6a199 100644 (file)
@@ -228,7 +228,6 @@ static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to)
        struct file *file = iocb->ki_filp;
        struct eventfd_ctx *ctx = file->private_data;
        __u64 ucnt = 0;
-       DECLARE_WAITQUEUE(wait, current);
 
        if (iov_iter_count(to) < sizeof(ucnt))
                return -EINVAL;
@@ -239,23 +238,11 @@ static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to)
                        spin_unlock_irq(&ctx->wqh.lock);
                        return -EAGAIN;
                }
-               __add_wait_queue(&ctx->wqh, &wait);
-               for (;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       if (ctx->count)
-                               break;
-                       if (signal_pending(current)) {
-                               __remove_wait_queue(&ctx->wqh, &wait);
-                               __set_current_state(TASK_RUNNING);
-                               spin_unlock_irq(&ctx->wqh.lock);
-                               return -ERESTARTSYS;
-                       }
+
+               if (wait_event_interruptible_locked_irq(ctx->wqh, ctx->count)) {
                        spin_unlock_irq(&ctx->wqh.lock);
-                       schedule();
-                       spin_lock_irq(&ctx->wqh.lock);
+                       return -ERESTARTSYS;
                }
-               __remove_wait_queue(&ctx->wqh, &wait);
-               __set_current_state(TASK_RUNNING);
        }
        eventfd_ctx_do_read(ctx, &ucnt);
        current->in_eventfd = 1;
@@ -275,7 +262,6 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
        struct eventfd_ctx *ctx = file->private_data;
        ssize_t res;
        __u64 ucnt;
-       DECLARE_WAITQUEUE(wait, current);
 
        if (count < sizeof(ucnt))
                return -EINVAL;
@@ -288,23 +274,10 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
        if (ULLONG_MAX - ctx->count > ucnt)
                res = sizeof(ucnt);
        else if (!(file->f_flags & O_NONBLOCK)) {
-               __add_wait_queue(&ctx->wqh, &wait);
-               for (res = 0;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       if (ULLONG_MAX - ctx->count > ucnt) {
-                               res = sizeof(ucnt);
-                               break;
-                       }
-                       if (signal_pending(current)) {
-                               res = -ERESTARTSYS;
-                               break;
-                       }
-                       spin_unlock_irq(&ctx->wqh.lock);
-                       schedule();
-                       spin_lock_irq(&ctx->wqh.lock);
-               }
-               __remove_wait_queue(&ctx->wqh, &wait);
-               __set_current_state(TASK_RUNNING);
+               res = wait_event_interruptible_locked_irq(ctx->wqh,
+                               ULLONG_MAX - ctx->count > ucnt);
+               if (!res)
+                       res = sizeof(ucnt);
        }
        if (likely(res > 0)) {
                ctx->count += ucnt;
index 64659b110973339dbbbbf061a2107e3a7246916b..f6d25050dd7aac42ab1dd59799a05827f2fd7e37 100644 (file)
@@ -483,8 +483,8 @@ static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
  * (efd1) notices that it may have some event ready, so it needs to wake up
  * the waiters on its poll wait list (efd2). So it calls ep_poll_safewake()
  * that ends up in another wake_up(), after having checked about the
- * recursion constraints. That are, no more than EP_MAX_POLLWAKE_NESTS, to
- * avoid stack blasting.
+ * recursion constraints. That are, no more than EP_MAX_NESTS, to avoid
+ * stack blasting.
  *
  * When CONFIG_DEBUG_LOCK_ALLOC is enabled, make sure lockdep can handle
  * this special case of epoll.
index abb91f5fae9211b752914df35a96e50dff846301..b21660475ac1cc703428cabf1f953b1ea3fb095a 100644 (file)
@@ -511,7 +511,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        if (type == HFSPLUS_FOLDER) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
-               WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_folder));
+               if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) {
+                       pr_err("bad catalog folder entry\n");
+                       res = -EIO;
+                       goto out;
+               }
                hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
                                        sizeof(struct hfsplus_cat_folder));
                hfsplus_get_perms(inode, &folder->permissions, 1);
@@ -531,7 +535,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        } else if (type == HFSPLUS_FILE) {
                struct hfsplus_cat_file *file = &entry.file;
 
-               WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_file));
+               if (fd->entrylength < sizeof(struct hfsplus_cat_file)) {
+                       pr_err("bad catalog file entry\n");
+                       res = -EIO;
+                       goto out;
+               }
                hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
                                        sizeof(struct hfsplus_cat_file));
 
@@ -562,6 +570,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
                pr_err("bad catalog entry used to create inode\n");
                res = -EIO;
        }
+out:
        return res;
 }
 
@@ -570,6 +579,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
        struct inode *main_inode = inode;
        struct hfs_find_data fd;
        hfsplus_cat_entry entry;
+       int res = 0;
 
        if (HFSPLUS_IS_RSRC(inode))
                main_inode = HFSPLUS_I(inode)->rsrc_inode;
@@ -588,7 +598,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
        if (S_ISDIR(main_inode->i_mode)) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
-               WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_folder));
+               if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
+                       pr_err("bad catalog folder entry\n");
+                       res = -EIO;
+                       goto out;
+               }
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                                        sizeof(struct hfsplus_cat_folder));
                /* simple node checks? */
@@ -613,7 +627,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
        } else {
                struct hfsplus_cat_file *file = &entry.file;
 
-               WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_file));
+               if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
+                       pr_err("bad catalog file entry\n");
+                       res = -EIO;
+                       goto out;
+               }
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                                        sizeof(struct hfsplus_cat_file));
                hfsplus_inode_write_fork(inode, &file->data_fork);
@@ -634,7 +652,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
        set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
 out:
        hfs_find_exit(&fd);
-       return 0;
+       return res;
 }
 
 int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa)
index 4558dc2f13557368fb0200d826fe2edba5de3f1e..3ec5a8f7b644d058ef23762f9a26fdfc137084ca 100644 (file)
@@ -1804,8 +1804,8 @@ EXPORT_SYMBOL(bmap);
 
 /*
  * With relative atime, only update atime if the previous atime is
- * earlier than either the ctime or mtime or if at least a day has
- * passed since the last atime update.
+ * earlier than or equal to either the ctime or mtime,
+ * or if at least a day has passed since the last atime update.
  */
 static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
                             struct timespec64 now)
@@ -1814,12 +1814,12 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
        if (!(mnt->mnt_flags & MNT_RELATIME))
                return 1;
        /*
-        * Is mtime younger than atime? If yes, update atime:
+        * Is mtime younger than or equal to atime? If yes, update atime:
         */
        if (timespec64_compare(&inode->i_mtime, &inode->i_atime) >= 0)
                return 1;
        /*
-        * Is ctime younger than atime? If yes, update atime:
+        * Is ctime younger than or equal to atime? If yes, update atime:
         */
        if (timespec64_compare(&inode->i_ctime, &inode->i_atime) >= 0)
                return 1;
index dc4eb91a577a80f16a3f49729e8c6f6dec2aeb3b..ab36ed8fa41caf2134cb5a1f0599a7f80590bf7c 100644 (file)
@@ -259,8 +259,6 @@ ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *po
 /*
  * fs/attr.c
  */
-int setattr_should_drop_sgid(struct mnt_idmap *idmap,
-                            const struct inode *inode);
 struct mnt_idmap *alloc_mnt_idmap(struct user_namespace *mnt_userns);
 struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap);
 void mnt_idmap_put(struct mnt_idmap *idmap);
index ef00b5fe8ceea9d9dd3c16a76d89c151dec282fd..90de0e498371119769759d0d1dbb9d30e50d2660 100644 (file)
@@ -1748,12 +1748,6 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
        return error;
 }
 
-/* Relationship between mode and the DT_xxx types */
-static inline unsigned char dt_type(struct kernfs_node *kn)
-{
-       return (kn->mode >> 12) & 15;
-}
-
 static int kernfs_dir_fop_release(struct inode *inode, struct file *filp)
 {
        kernfs_put(filp->private_data);
@@ -1831,7 +1825,7 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
             pos;
             pos = kernfs_dir_next_pos(ns, parent, ctx->pos, pos)) {
                const char *name = pos->name;
-               unsigned int type = dt_type(pos);
+               unsigned int type = fs_umode_to_dtype(pos->mode);
                int len = strlen(name);
                ino_t ino = kernfs_ino(pos);
 
index 4eda519c30022f1a676869053a4ecda36b24dd53..89cf614a32715877c9bc500bffff502383db9d97 100644 (file)
@@ -174,12 +174,6 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
 }
 EXPORT_SYMBOL(dcache_dir_lseek);
 
-/* Relationship between i_mode and the DT_xxx types */
-static inline unsigned char dt_type(struct inode *inode)
-{
-       return (inode->i_mode >> 12) & 15;
-}
-
 /*
  * Directory is locked and all positive dentries in it are safe, since
  * for ramfs-type trees they can't go away without unlink() or rmdir(),
@@ -206,7 +200,8 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
 
        while ((next = scan_positives(cursor, p, 1, next)) != NULL) {
                if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
-                             d_inode(next)->i_ino, dt_type(d_inode(next))))
+                             d_inode(next)->i_ino,
+                             fs_umode_to_dtype(d_inode(next)->i_mode)))
                        break;
                ctx->pos++;
                p = &next->d_child;
index 6836e937ee613814bda7cef7c00cda14bcc17b82..c37a68f7ba7226f2252a89e62cb65065b82777e6 100644 (file)
@@ -2617,15 +2617,12 @@ static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount *
           (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) {
                char *buf = (char *)__get_free_page(GFP_KERNEL);
                char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM);
-               struct tm tm;
 
-               time64_to_tm(sb->s_time_max, 0, &tm);
-
-               pr_warn("%s filesystem being %s at %s supports timestamps until %04ld (0x%llx)\n",
+               pr_warn("%s filesystem being %s at %s supports timestamps until %ptTd (0x%llx)\n",
                        sb->s_type->name,
                        is_mounted(mnt) ? "remounted" : "mounted",
-                       mntpath,
-                       tm.tm_year+1900, (unsigned long long)sb->s_time_max);
+                       mntpath, &sb->s_time_max,
+                       (unsigned long long)sb->s_time_max);
 
                free_page((unsigned long)buf);
                sb->s_iflags |= SB_I_TS_EXPIRY_WARNED;
index 222a28320e1c211efd6c7898d26855931863cbab..97a76706fd542b9aa149a578a04aa8b42bbf2aad 100644 (file)
@@ -717,9 +717,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
                if ((attr->ia_valid & ATTR_KILL_SUID) != 0 &&
                    inode->i_mode & S_ISUID)
                        inode->i_mode &= ~S_ISUID;
-               if ((attr->ia_valid & ATTR_KILL_SGID) != 0 &&
-                   (inode->i_mode & (S_ISGID | S_IXGRP)) ==
-                    (S_ISGID | S_IXGRP))
+               if (setattr_should_drop_sgid(&nop_mnt_idmap, inode))
                        inode->i_mode &= ~S_ISGID;
                if ((attr->ia_valid & ATTR_MODE) != 0) {
                        int mode = attr->ia_mode & S_IALLUGO;
index 05ae23657527da80dc0c66469df936dfff92c5eb..397c096d874eb8fa0aa1849134570962090e62e1 100644 (file)
@@ -1274,9 +1274,6 @@ int nfs_get_tree_common(struct fs_context *fc)
                if (ctx->clone_data.sb->s_flags & SB_SYNCHRONOUS)
                        fc->sb_flags |= SB_SYNCHRONOUS;
 
-       if (server->caps & NFS_CAP_SECURITY_LABEL)
-               fc->lsm_flags |= SECURITY_LSM_NATIVE_LABELS;
-
        /* Get a superblock - note that we may end up sharing one that already exists */
        fc->s_fs_info = server;
        s = sget_fc(fc, compare_super, nfs_set_super);
index 468e4e65a615d770919e0d952e17d0f4f1a7c02f..3cede8b18c8b6ff385815ae51e911b6b6af81e56 100644 (file)
@@ -214,7 +214,6 @@ static struct mount *next_group(struct mount *m, struct mount *origin)
 
 /* all accesses are serialized by namespace_sem */
 static struct mount *last_dest, *first_source, *last_source, *dest_master;
-static struct mountpoint *mp;
 static struct hlist_head *list;
 
 static inline bool peers(struct mount *m1, struct mount *m2)
@@ -222,7 +221,7 @@ static inline bool peers(struct mount *m1, struct mount *m2)
        return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id;
 }
 
-static int propagate_one(struct mount *m)
+static int propagate_one(struct mount *m, struct mountpoint *dest_mp)
 {
        struct mount *child;
        int type;
@@ -230,7 +229,7 @@ static int propagate_one(struct mount *m)
        if (IS_MNT_NEW(m))
                return 0;
        /* skip if mountpoint isn't covered by it */
-       if (!is_subdir(mp->m_dentry, m->mnt.mnt_root))
+       if (!is_subdir(dest_mp->m_dentry, m->mnt.mnt_root))
                return 0;
        if (peers(m, last_dest)) {
                type = CL_MAKE_SHARED;
@@ -262,7 +261,7 @@ static int propagate_one(struct mount *m)
        if (IS_ERR(child))
                return PTR_ERR(child);
        read_seqlock_excl(&mount_lock);
-       mnt_set_mountpoint(m, mp, child);
+       mnt_set_mountpoint(m, dest_mp, child);
        if (m->mnt_master != dest_master)
                SET_MNT_MARK(m->mnt_master);
        read_sequnlock_excl(&mount_lock);
@@ -299,13 +298,12 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
        last_dest = dest_mnt;
        first_source = source_mnt;
        last_source = source_mnt;
-       mp = dest_mp;
        list = tree_list;
        dest_master = dest_mnt->mnt_master;
 
        /* all peers of dest_mnt, except dest_mnt itself */
        for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) {
-               ret = propagate_one(n);
+               ret = propagate_one(n, dest_mp);
                if (ret)
                        goto out;
        }
@@ -316,7 +314,7 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
                /* everything in that slave group */
                n = m;
                do {
-                       ret = propagate_one(n);
+                       ret = propagate_one(n, dest_mp);
                        if (ret)
                                goto out;
                        n = next_peer(n);
index 2c3dec2b6dfaf18477a0734bb08e6c0b79d5dcf2..0af8d150394f6a968ba37a7c2f88afad1b2914fa 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/export.h>
 #include <linux/syscalls.h>
 #include <linux/uio.h>
+#include <linux/fsnotify.h>
 #include <linux/security.h>
 #include <linux/gfp.h>
 #include <linux/socket.h>
@@ -1165,6 +1166,9 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out,
                ret = do_splice_from(ipipe, out, &offset, len, flags);
                file_end_write(out);
 
+               if (ret > 0)
+                       fsnotify_modify(out);
+
                if (!off_out)
                        out->f_pos = offset;
                else
@@ -1188,6 +1192,10 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out,
                        flags |= SPLICE_F_NONBLOCK;
 
                ret = splice_file_to_pipe(in, opipe, &offset, len, flags);
+
+               if (ret > 0)
+                       fsnotify_access(in);
+
                if (!off_in)
                        in->f_pos = offset;
                else
index c85916e9f7db500474d043c1f6a6b5e5c8d22020..af95b64fc810cce98d8cc9002944de781d396c15 100644 (file)
@@ -2675,6 +2675,8 @@ extern struct inode *new_inode(struct super_block *sb);
 extern void free_inode_nonrcu(struct inode *inode);
 extern int setattr_should_drop_suidgid(struct mnt_idmap *, struct inode *);
 extern int file_remove_privs(struct file *);
+int setattr_should_drop_sgid(struct mnt_idmap *idmap,
+                            const struct inode *inode);
 
 /*
  * This must be used for allocating filesystems specific inodes to set
index 5469ffee21c73f2b34d3bc8548a351e46e01f2f7..ff6341e09925bc84539351c560661400c032305d 100644 (file)
@@ -104,7 +104,6 @@ struct fs_context {
        unsigned int            sb_flags;       /* Proposed superblock flags (SB_*) */
        unsigned int            sb_flags_mask;  /* Superblock flags that were changed */
        unsigned int            s_iflags;       /* OR'd with sb->s_iflags */
-       unsigned int            lsm_flags;      /* Information flags from the fs to the LSM */
        enum fs_context_purpose purpose:8;
        enum fs_context_phase   phase:8;        /* The phase the context is in */
        bool                    need_free:1;    /* Need to call ops->free() */
index cd23221ce9e698d4e8e6a99b9b7aab7cd4ee58b7..e2734e9e44d5c7a4145712aa29b1bd163e598a12 100644 (file)
@@ -68,7 +68,7 @@ struct watch_notification;
 /* If capable is being called by a setid function */
 #define CAP_OPT_INSETID BIT(2)
 
-/* LSM Agnostic defines for fs_context::lsm_flags */
+/* LSM Agnostic defines for security_sb_set_mnt_opts() flags */
 #define SECURITY_LSM_NATIVE_LABELS     1
 
 struct ctl_table;