]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Aug 2021 08:57:29 +0000 (10:57 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Aug 2021 08:57:29 +0000 (10:57 +0200)
added patches:
ceph-add-some-lockdep-assertions-around-snaprealm-handling.patch
ceph-clean-up-locking-annotation-for-ceph_get_snap_realm-and-__lookup_snap_realm.patch
ceph-take-snap_empty_lock-atomically-with-snaprealm-refcount-change.patch
vboxsf-add-support-for-the-atomic_open-directory-inode-op.patch
vboxsf-add-vboxsf__sf_handle-helpers.patch
vmlinux.lds.h-handle-clang-s-module.-c-d-tor-sections.patch

queue-5.10/ceph-add-some-lockdep-assertions-around-snaprealm-handling.patch [new file with mode: 0644]
queue-5.10/ceph-clean-up-locking-annotation-for-ceph_get_snap_realm-and-__lookup_snap_realm.patch [new file with mode: 0644]
queue-5.10/ceph-take-snap_empty_lock-atomically-with-snaprealm-refcount-change.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/vboxsf-add-support-for-the-atomic_open-directory-inode-op.patch [new file with mode: 0644]
queue-5.10/vboxsf-add-vboxsf__sf_handle-helpers.patch [new file with mode: 0644]
queue-5.10/vmlinux.lds.h-handle-clang-s-module.-c-d-tor-sections.patch [new file with mode: 0644]

diff --git a/queue-5.10/ceph-add-some-lockdep-assertions-around-snaprealm-handling.patch b/queue-5.10/ceph-add-some-lockdep-assertions-around-snaprealm-handling.patch
new file mode 100644 (file)
index 0000000..7ba60d8
--- /dev/null
@@ -0,0 +1,93 @@
+From a6862e6708c15995bc10614b2ef34ca35b4b9078 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Tue, 1 Jun 2021 08:13:38 -0400
+Subject: ceph: add some lockdep assertions around snaprealm handling
+
+From: Jeff Layton <jlayton@kernel.org>
+
+commit a6862e6708c15995bc10614b2ef34ca35b4b9078 upstream.
+
+Turn some comments into lockdep asserts.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/snap.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/fs/ceph/snap.c
++++ b/fs/ceph/snap.c
+@@ -65,6 +65,8 @@
+ void ceph_get_snap_realm(struct ceph_mds_client *mdsc,
+                        struct ceph_snap_realm *realm)
+ {
++      lockdep_assert_held_write(&mdsc->snap_rwsem);
++
+       dout("get_realm %p %d -> %d\n", realm,
+            atomic_read(&realm->nref), atomic_read(&realm->nref)+1);
+       /*
+@@ -113,6 +115,8 @@ static struct ceph_snap_realm *ceph_crea
+ {
+       struct ceph_snap_realm *realm;
++      lockdep_assert_held_write(&mdsc->snap_rwsem);
++
+       realm = kzalloc(sizeof(*realm), GFP_NOFS);
+       if (!realm)
+               return ERR_PTR(-ENOMEM);
+@@ -143,6 +147,8 @@ static struct ceph_snap_realm *__lookup_
+       struct rb_node *n = mdsc->snap_realms.rb_node;
+       struct ceph_snap_realm *r;
++      lockdep_assert_held_write(&mdsc->snap_rwsem);
++
+       while (n) {
+               r = rb_entry(n, struct ceph_snap_realm, node);
+               if (ino < r->ino)
+@@ -176,6 +182,8 @@ static void __put_snap_realm(struct ceph
+ static void __destroy_snap_realm(struct ceph_mds_client *mdsc,
+                                struct ceph_snap_realm *realm)
+ {
++      lockdep_assert_held_write(&mdsc->snap_rwsem);
++
+       dout("__destroy_snap_realm %p %llx\n", realm, realm->ino);
+       rb_erase(&realm->node, &mdsc->snap_realms);
+@@ -198,6 +206,8 @@ static void __destroy_snap_realm(struct
+ static void __put_snap_realm(struct ceph_mds_client *mdsc,
+                            struct ceph_snap_realm *realm)
+ {
++      lockdep_assert_held_write(&mdsc->snap_rwsem);
++
+       dout("__put_snap_realm %llx %p %d -> %d\n", realm->ino, realm,
+            atomic_read(&realm->nref), atomic_read(&realm->nref)-1);
+       if (atomic_dec_and_test(&realm->nref))
+@@ -236,6 +246,8 @@ static void __cleanup_empty_realms(struc
+ {
+       struct ceph_snap_realm *realm;
++      lockdep_assert_held_write(&mdsc->snap_rwsem);
++
+       spin_lock(&mdsc->snap_empty_lock);
+       while (!list_empty(&mdsc->snap_empty)) {
+               realm = list_first_entry(&mdsc->snap_empty,
+@@ -269,6 +281,8 @@ static int adjust_snap_realm_parent(stru
+ {
+       struct ceph_snap_realm *parent;
++      lockdep_assert_held_write(&mdsc->snap_rwsem);
++
+       if (realm->parent_ino == parentino)
+               return 0;
+@@ -686,6 +700,8 @@ int ceph_update_snap_trace(struct ceph_m
+       int err = -ENOMEM;
+       LIST_HEAD(dirty_realms);
++      lockdep_assert_held_write(&mdsc->snap_rwsem);
++
+       dout("update_snap_trace deletion=%d\n", deletion);
+ more:
+       ceph_decode_need(&p, e, sizeof(*ri), bad);
diff --git a/queue-5.10/ceph-clean-up-locking-annotation-for-ceph_get_snap_realm-and-__lookup_snap_realm.patch b/queue-5.10/ceph-clean-up-locking-annotation-for-ceph_get_snap_realm-and-__lookup_snap_realm.patch
new file mode 100644 (file)
index 0000000..4a9f993
--- /dev/null
@@ -0,0 +1,61 @@
+From df2c0cb7f8e8c83e495260ad86df8c5da947f2a7 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Tue, 1 Jun 2021 09:24:38 -0400
+Subject: ceph: clean up locking annotation for ceph_get_snap_realm and __lookup_snap_realm
+
+From: Jeff Layton <jlayton@kernel.org>
+
+commit df2c0cb7f8e8c83e495260ad86df8c5da947f2a7 upstream.
+
+They both say that the snap_rwsem must be held for write, but I don't
+see any real reason for it, and it's not currently always called that
+way.
+
+The lookup is just walking the rbtree, so holding it for read should be
+fine there. The "get" is bumping the refcount and (possibly) removing
+it from the empty list. I see no need to hold the snap_rwsem for write
+for that.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/snap.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/ceph/snap.c
++++ b/fs/ceph/snap.c
+@@ -60,12 +60,12 @@
+ /*
+  * increase ref count for the realm
+  *
+- * caller must hold snap_rwsem for write.
++ * caller must hold snap_rwsem.
+  */
+ void ceph_get_snap_realm(struct ceph_mds_client *mdsc,
+                        struct ceph_snap_realm *realm)
+ {
+-      lockdep_assert_held_write(&mdsc->snap_rwsem);
++      lockdep_assert_held(&mdsc->snap_rwsem);
+       dout("get_realm %p %d -> %d\n", realm,
+            atomic_read(&realm->nref), atomic_read(&realm->nref)+1);
+@@ -139,7 +139,7 @@ static struct ceph_snap_realm *ceph_crea
+ /*
+  * lookup the realm rooted at @ino.
+  *
+- * caller must hold snap_rwsem for write.
++ * caller must hold snap_rwsem.
+  */
+ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,
+                                                  u64 ino)
+@@ -147,7 +147,7 @@ static struct ceph_snap_realm *__lookup_
+       struct rb_node *n = mdsc->snap_realms.rb_node;
+       struct ceph_snap_realm *r;
+-      lockdep_assert_held_write(&mdsc->snap_rwsem);
++      lockdep_assert_held(&mdsc->snap_rwsem);
+       while (n) {
+               r = rb_entry(n, struct ceph_snap_realm, node);
diff --git a/queue-5.10/ceph-take-snap_empty_lock-atomically-with-snaprealm-refcount-change.patch b/queue-5.10/ceph-take-snap_empty_lock-atomically-with-snaprealm-refcount-change.patch
new file mode 100644 (file)
index 0000000..e8932e7
--- /dev/null
@@ -0,0 +1,107 @@
+From 8434ffe71c874b9c4e184b88d25de98c2bf5fe3f Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@kernel.org>
+Date: Tue, 3 Aug 2021 12:47:34 -0400
+Subject: ceph: take snap_empty_lock atomically with snaprealm refcount change
+
+From: Jeff Layton <jlayton@kernel.org>
+
+commit 8434ffe71c874b9c4e184b88d25de98c2bf5fe3f upstream.
+
+There is a race in ceph_put_snap_realm. The change to the nref and the
+spinlock acquisition are not done atomically, so you could decrement
+nref, and before you take the spinlock, the nref is incremented again.
+At that point, you end up putting it on the empty list when it
+shouldn't be there. Eventually __cleanup_empty_realms runs and frees
+it when it's still in-use.
+
+Fix this by protecting the 1->0 transition with atomic_dec_and_lock,
+and just drop the spinlock if we can get the rwsem.
+
+Because these objects can also undergo a 0->1 refcount transition, we
+must protect that change as well with the spinlock. Increment locklessly
+unless the value is at 0, in which case we take the spinlock, increment
+and then take it off the empty list if it did the 0->1 transition.
+
+With these changes, I'm removing the dout() messages from these
+functions, as well as in __put_snap_realm. They've always been racy, and
+it's better to not print values that may be misleading.
+
+Cc: stable@vger.kernel.org
+URL: https://tracker.ceph.com/issues/46419
+Reported-by: Mark Nelson <mnelson@redhat.com>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Luis Henriques <lhenriques@suse.de>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/snap.c |   34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+--- a/fs/ceph/snap.c
++++ b/fs/ceph/snap.c
+@@ -67,19 +67,19 @@ void ceph_get_snap_realm(struct ceph_mds
+ {
+       lockdep_assert_held(&mdsc->snap_rwsem);
+-      dout("get_realm %p %d -> %d\n", realm,
+-           atomic_read(&realm->nref), atomic_read(&realm->nref)+1);
+       /*
+-       * since we _only_ increment realm refs or empty the empty
+-       * list with snap_rwsem held, adjusting the empty list here is
+-       * safe.  we do need to protect against concurrent empty list
+-       * additions, however.
++       * The 0->1 and 1->0 transitions must take the snap_empty_lock
++       * atomically with the refcount change. Go ahead and bump the
++       * nref here, unless it's 0, in which case we take the spinlock
++       * and then do the increment and remove it from the list.
+        */
+-      if (atomic_inc_return(&realm->nref) == 1) {
+-              spin_lock(&mdsc->snap_empty_lock);
++      if (atomic_inc_not_zero(&realm->nref))
++              return;
++
++      spin_lock(&mdsc->snap_empty_lock);
++      if (atomic_inc_return(&realm->nref) == 1)
+               list_del_init(&realm->empty_item);
+-              spin_unlock(&mdsc->snap_empty_lock);
+-      }
++      spin_unlock(&mdsc->snap_empty_lock);
+ }
+ static void __insert_snap_realm(struct rb_root *root,
+@@ -208,28 +208,28 @@ static void __put_snap_realm(struct ceph
+ {
+       lockdep_assert_held_write(&mdsc->snap_rwsem);
+-      dout("__put_snap_realm %llx %p %d -> %d\n", realm->ino, realm,
+-           atomic_read(&realm->nref), atomic_read(&realm->nref)-1);
++      /*
++       * We do not require the snap_empty_lock here, as any caller that
++       * increments the value must hold the snap_rwsem.
++       */
+       if (atomic_dec_and_test(&realm->nref))
+               __destroy_snap_realm(mdsc, realm);
+ }
+ /*
+- * caller needn't hold any locks
++ * See comments in ceph_get_snap_realm. Caller needn't hold any locks.
+  */
+ void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
+                        struct ceph_snap_realm *realm)
+ {
+-      dout("put_snap_realm %llx %p %d -> %d\n", realm->ino, realm,
+-           atomic_read(&realm->nref), atomic_read(&realm->nref)-1);
+-      if (!atomic_dec_and_test(&realm->nref))
++      if (!atomic_dec_and_lock(&realm->nref, &mdsc->snap_empty_lock))
+               return;
+       if (down_write_trylock(&mdsc->snap_rwsem)) {
++              spin_unlock(&mdsc->snap_empty_lock);
+               __destroy_snap_realm(mdsc, realm);
+               up_write(&mdsc->snap_rwsem);
+       } else {
+-              spin_lock(&mdsc->snap_empty_lock);
+               list_add(&realm->empty_item, &mdsc->snap_empty);
+               spin_unlock(&mdsc->snap_empty_lock);
+       }
index 78e04a96cbd26a39b545d1ebe15ff778d94ca0fc..4a49f5144415d003163988edb9a258f505301b38 100644 (file)
@@ -88,3 +88,9 @@ powerpc-smp-fix-oops-in-topology_init.patch
 efi-libstub-arm64-double-check-image-alignment-at-entry.patch
 kvm-vmx-use-current-vmcs-to-query-waitpkg-support-for-msr-emulation.patch
 kvm-nvmx-use-vmx_need_pf_intercept-when-deciding-if-l0-wants-a-pf.patch
+vboxsf-add-vboxsf__sf_handle-helpers.patch
+vboxsf-add-support-for-the-atomic_open-directory-inode-op.patch
+ceph-add-some-lockdep-assertions-around-snaprealm-handling.patch
+ceph-clean-up-locking-annotation-for-ceph_get_snap_realm-and-__lookup_snap_realm.patch
+ceph-take-snap_empty_lock-atomically-with-snaprealm-refcount-change.patch
+vmlinux.lds.h-handle-clang-s-module.-c-d-tor-sections.patch
diff --git a/queue-5.10/vboxsf-add-support-for-the-atomic_open-directory-inode-op.patch b/queue-5.10/vboxsf-add-support-for-the-atomic_open-directory-inode-op.patch
new file mode 100644 (file)
index 0000000..0318c43
--- /dev/null
@@ -0,0 +1,120 @@
+From 52dfd86aa568e433b24357bb5fc725560f1e22d8 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 21 Jan 2021 12:54:18 +0100
+Subject: vboxsf: Add support for the atomic_open directory-inode op
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 52dfd86aa568e433b24357bb5fc725560f1e22d8 upstream.
+
+Opening a new file is done in 2 steps on regular filesystems:
+
+1. Call the create inode-op on the parent-dir to create an inode
+to hold the meta-data related to the file.
+2. Call the open file-op to get a handle for the file.
+
+vboxsf however does not really use disk-backed inodes because it
+is based on passing through file-related system-calls through to
+the hypervisor. So both steps translate to an open(2) call being
+passed through to the hypervisor. With the handle returned by
+the first call immediately being closed again.
+
+Making 2 open calls for a single open(..., O_CREATE, ...) calls
+has 2 problems:
+
+a) It is not really efficient.
+b) It actually breaks some apps.
+
+An example of b) is doing a git clone inside a vboxsf mount.
+When git clone tries to create a tempfile to store the pak
+files which is downloading the following happens:
+
+1. vboxsf_dir_mkfile() gets called with a mode of 0444 and succeeds.
+2. vboxsf_file_open() gets called with file->f_flags containing
+O_RDWR. When the host is a Linux machine this fails because doing
+a open(..., O_RDWR) on a file which exists and has mode 0444 results
+in an -EPERM error.
+
+Other network-filesystems and fuse avoid the problem of needing to
+pass 2 open() calls to the other side by using the atomic_open
+directory-inode op.
+
+This commit fixes git clone not working inside a vboxsf mount,
+by adding support for the atomic_open directory-inode op.
+As an added bonus this should also make opening new files faster.
+
+The atomic_open implementation is modelled after the atomic_open
+implementations from the 9p and fuse code.
+
+Fixes: 0fd169576648 ("fs: Add VirtualBox guest shared folder (vboxsf) support")
+Reported-by: Ludovic Pouzenc <bugreports@pouzenc.fr>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/vboxsf/dir.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+
+--- a/fs/vboxsf/dir.c
++++ b/fs/vboxsf/dir.c
+@@ -306,6 +306,53 @@ static int vboxsf_dir_mkdir(struct inode
+       return vboxsf_dir_create(parent, dentry, mode, true, true, NULL);
+ }
++static int vboxsf_dir_atomic_open(struct inode *parent, struct dentry *dentry,
++                                struct file *file, unsigned int flags, umode_t mode)
++{
++      struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
++      struct vboxsf_handle *sf_handle;
++      struct dentry *res = NULL;
++      u64 handle;
++      int err;
++
++      if (d_in_lookup(dentry)) {
++              res = vboxsf_dir_lookup(parent, dentry, 0);
++              if (IS_ERR(res))
++                      return PTR_ERR(res);
++
++              if (res)
++                      dentry = res;
++      }
++
++      /* Only creates */
++      if (!(flags & O_CREAT) || d_really_is_positive(dentry))
++              return finish_no_open(file, res);
++
++      err = vboxsf_dir_create(parent, dentry, mode, false, flags & O_EXCL, &handle);
++      if (err)
++              goto out;
++
++      sf_handle = vboxsf_create_sf_handle(d_inode(dentry), handle, SHFL_CF_ACCESS_READWRITE);
++      if (IS_ERR(sf_handle)) {
++              vboxsf_close(sbi->root, handle);
++              err = PTR_ERR(sf_handle);
++              goto out;
++      }
++
++      err = finish_open(file, dentry, generic_file_open);
++      if (err) {
++              /* This also closes the handle passed to vboxsf_create_sf_handle() */
++              vboxsf_release_sf_handle(d_inode(dentry), sf_handle);
++              goto out;
++      }
++
++      file->private_data = sf_handle;
++      file->f_mode |= FMODE_CREATED;
++out:
++      dput(res);
++      return err;
++}
++
+ static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry)
+ {
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
+@@ -424,6 +471,7 @@ const struct inode_operations vboxsf_dir
+       .lookup  = vboxsf_dir_lookup,
+       .create  = vboxsf_dir_mkfile,
+       .mkdir   = vboxsf_dir_mkdir,
++      .atomic_open = vboxsf_dir_atomic_open,
+       .rmdir   = vboxsf_dir_unlink,
+       .unlink  = vboxsf_dir_unlink,
+       .rename  = vboxsf_dir_rename,
diff --git a/queue-5.10/vboxsf-add-vboxsf__sf_handle-helpers.patch b/queue-5.10/vboxsf-add-vboxsf__sf_handle-helpers.patch
new file mode 100644 (file)
index 0000000..edf7ff5
--- /dev/null
@@ -0,0 +1,156 @@
+From 02f840f90764f22f5c898901849bdbf0cee752ba Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 21 Jan 2021 10:55:03 +0100
+Subject: vboxsf: Add vboxsf_[create|release]_sf_handle() helpers
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 02f840f90764f22f5c898901849bdbf0cee752ba upstream.
+
+Factor out the code to create / release a struct vboxsf_handle into
+2 new helper functions.
+
+This is a preparation patch for adding atomic_open support.
+
+Fixes: 0fd169576648 ("fs: Add VirtualBox guest shared folder (vboxsf) support")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/vboxsf/file.c   |   71 ++++++++++++++++++++++++++++++++---------------------
+ fs/vboxsf/vfsmod.h |    7 +++++
+ 2 files changed, 51 insertions(+), 27 deletions(-)
+
+--- a/fs/vboxsf/file.c
++++ b/fs/vboxsf/file.c
+@@ -20,17 +20,39 @@ struct vboxsf_handle {
+       struct list_head head;
+ };
+-static int vboxsf_file_open(struct inode *inode, struct file *file)
++struct vboxsf_handle *vboxsf_create_sf_handle(struct inode *inode,
++                                            u64 handle, u32 access_flags)
+ {
+       struct vboxsf_inode *sf_i = VBOXSF_I(inode);
+-      struct shfl_createparms params = {};
+       struct vboxsf_handle *sf_handle;
+-      u32 access_flags = 0;
+-      int err;
+       sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL);
+       if (!sf_handle)
+-              return -ENOMEM;
++              return ERR_PTR(-ENOMEM);
++
++      /* the host may have given us different attr then requested */
++      sf_i->force_restat = 1;
++
++      /* init our handle struct and add it to the inode's handles list */
++      sf_handle->handle = handle;
++      sf_handle->root = VBOXSF_SBI(inode->i_sb)->root;
++      sf_handle->access_flags = access_flags;
++      kref_init(&sf_handle->refcount);
++
++      mutex_lock(&sf_i->handle_list_mutex);
++      list_add(&sf_handle->head, &sf_i->handle_list);
++      mutex_unlock(&sf_i->handle_list_mutex);
++
++      return sf_handle;
++}
++
++static int vboxsf_file_open(struct inode *inode, struct file *file)
++{
++      struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
++      struct shfl_createparms params = {};
++      struct vboxsf_handle *sf_handle;
++      u32 access_flags = 0;
++      int err;
+       /*
+        * We check the value of params.handle afterwards to find out if
+@@ -83,23 +105,14 @@ static int vboxsf_file_open(struct inode
+       err = vboxsf_create_at_dentry(file_dentry(file), &params);
+       if (err == 0 && params.handle == SHFL_HANDLE_NIL)
+               err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT;
+-      if (err) {
+-              kfree(sf_handle);
++      if (err)
+               return err;
+-      }
+-      /* the host may have given us different attr then requested */
+-      sf_i->force_restat = 1;
+-
+-      /* init our handle struct and add it to the inode's handles list */
+-      sf_handle->handle = params.handle;
+-      sf_handle->root = VBOXSF_SBI(inode->i_sb)->root;
+-      sf_handle->access_flags = access_flags;
+-      kref_init(&sf_handle->refcount);
+-
+-      mutex_lock(&sf_i->handle_list_mutex);
+-      list_add(&sf_handle->head, &sf_i->handle_list);
+-      mutex_unlock(&sf_i->handle_list_mutex);
++      sf_handle = vboxsf_create_sf_handle(inode, params.handle, access_flags);
++      if (IS_ERR(sf_handle)) {
++              vboxsf_close(sbi->root, params.handle);
++              return PTR_ERR(sf_handle);
++      }
+       file->private_data = sf_handle;
+       return 0;
+@@ -114,22 +127,26 @@ static void vboxsf_handle_release(struct
+       kfree(sf_handle);
+ }
+-static int vboxsf_file_release(struct inode *inode, struct file *file)
++void vboxsf_release_sf_handle(struct inode *inode, struct vboxsf_handle *sf_handle)
+ {
+       struct vboxsf_inode *sf_i = VBOXSF_I(inode);
+-      struct vboxsf_handle *sf_handle = file->private_data;
++      mutex_lock(&sf_i->handle_list_mutex);
++      list_del(&sf_handle->head);
++      mutex_unlock(&sf_i->handle_list_mutex);
++
++      kref_put(&sf_handle->refcount, vboxsf_handle_release);
++}
++
++static int vboxsf_file_release(struct inode *inode, struct file *file)
++{
+       /*
+        * When a file is closed on our (the guest) side, we want any subsequent
+        * accesses done on the host side to see all changes done from our side.
+        */
+       filemap_write_and_wait(inode->i_mapping);
+-      mutex_lock(&sf_i->handle_list_mutex);
+-      list_del(&sf_handle->head);
+-      mutex_unlock(&sf_i->handle_list_mutex);
+-
+-      kref_put(&sf_handle->refcount, vboxsf_handle_release);
++      vboxsf_release_sf_handle(inode, file->private_data);
+       return 0;
+ }
+--- a/fs/vboxsf/vfsmod.h
++++ b/fs/vboxsf/vfsmod.h
+@@ -18,6 +18,8 @@
+ #define VBOXSF_SBI(sb)        ((struct vboxsf_sbi *)(sb)->s_fs_info)
+ #define VBOXSF_I(i)   container_of(i, struct vboxsf_inode, vfs_inode)
++struct vboxsf_handle;
++
+ struct vboxsf_options {
+       unsigned long ttl;
+       kuid_t uid;
+@@ -80,6 +82,11 @@ extern const struct file_operations vbox
+ extern const struct address_space_operations vboxsf_reg_aops;
+ extern const struct dentry_operations vboxsf_dentry_ops;
++/* from file.c */
++struct vboxsf_handle *vboxsf_create_sf_handle(struct inode *inode,
++                                            u64 handle, u32 access_flags);
++void vboxsf_release_sf_handle(struct inode *inode, struct vboxsf_handle *sf_handle);
++
+ /* from utils.c */
+ struct inode *vboxsf_new_inode(struct super_block *sb);
+ void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
diff --git a/queue-5.10/vmlinux.lds.h-handle-clang-s-module.-c-d-tor-sections.patch b/queue-5.10/vmlinux.lds.h-handle-clang-s-module.-c-d-tor-sections.patch
new file mode 100644 (file)
index 0000000..446c573
--- /dev/null
@@ -0,0 +1,51 @@
+From foo@baz Mon Aug 16 10:53:15 AM CEST 2021
+From: Nathan Chancellor <nathan@kernel.org>
+Date: Fri, 30 Jul 2021 19:31:08 -0700
+Subject: vmlinux.lds.h: Handle clang's module.{c,d}tor sections
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+commit 848378812e40152abe9b9baf58ce2004f76fb988 upstream.
+
+A recent change in LLVM causes module_{c,d}tor sections to appear when
+CONFIG_K{A,C}SAN are enabled, which results in orphan section warnings
+because these are not handled anywhere:
+
+ld.lld: warning: arch/x86/pci/built-in.a(legacy.o):(.text.asan.module_ctor) is being placed in '.text.asan.module_ctor'
+ld.lld: warning: arch/x86/pci/built-in.a(legacy.o):(.text.asan.module_dtor) is being placed in '.text.asan.module_dtor'
+ld.lld: warning: arch/x86/pci/built-in.a(legacy.o):(.text.tsan.module_ctor) is being placed in '.text.tsan.module_ctor'
+
+Fangrui explains: "the function asan.module_ctor has the SHF_GNU_RETAIN
+flag, so it is in a separate section even with -fno-function-sections
+(default)".
+
+Place them in the TEXT_TEXT section so that these technologies continue
+to work with the newer compiler versions. All of the KASAN and KCSAN
+KUnit tests continue to pass after this change.
+
+Cc: stable@vger.kernel.org
+Link: https://github.com/ClangBuiltLinux/linux/issues/1432
+Link: https://github.com/llvm/llvm-project/commit/7b789562244ee941b7bf2cefeb3fc08a59a01865
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Reviewed-by: Fangrui Song <maskray@google.com>
+Acked-by: Marco Elver <elver@google.com>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Link: https://lore.kernel.org/r/20210731023107.1932981-1-nathan@kernel.org
+[nc: Resolve conflict due to lack of cf68fffb66d60]
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/asm-generic/vmlinux.lds.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -599,6 +599,7 @@
+               NOINSTR_TEXT                                            \
+               *(.text..refcount)                                      \
+               *(.ref.text)                                            \
++              *(.text.asan.* .text.tsan.*)                            \
+       MEM_KEEP(init.text*)                                            \
+       MEM_KEEP(exit.text*)                                            \