]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Mar 2018 10:02:17 +0000 (11:02 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Mar 2018 10:02:17 +0000 (11:02 +0100)
added patches:
alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch
alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch
alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch
fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch
fs-aio-use-rcu-accessors-for-kioctx_table-table.patch
lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch

queue-3.18/alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch [new file with mode: 0644]
queue-3.18/alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch [new file with mode: 0644]
queue-3.18/alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch [new file with mode: 0644]
queue-3.18/fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch [new file with mode: 0644]
queue-3.18/fs-aio-use-rcu-accessors-for-kioctx_table-table.patch [new file with mode: 0644]
queue-3.18/lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch [new file with mode: 0644]
queue-3.18/series

diff --git a/queue-3.18/alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch b/queue-3.18/alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch
new file mode 100644 (file)
index 0000000..2500723
--- /dev/null
@@ -0,0 +1,51 @@
+From 01c0b4265cc16bc1f43f475c5944c55c10d5768f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 10 Mar 2018 23:04:23 +0100
+Subject: ALSA: pcm: Fix UAF in snd_pcm_oss_get_formats()
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 01c0b4265cc16bc1f43f475c5944c55c10d5768f upstream.
+
+snd_pcm_oss_get_formats() has an obvious use-after-free around
+snd_mask_test() calls, as spotted by syzbot.  The passed format_mask
+argument is a pointer to the hw_params object that is freed before the
+loop.  What a surprise that it has been present since the original
+code of decades ago...
+
+Reported-by: syzbot+4090700a4f13fccaf648@syzkaller.appspotmail.com
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/oss/pcm_oss.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1815,10 +1815,9 @@ static int snd_pcm_oss_get_formats(struc
+               return -ENOMEM;
+       _snd_pcm_hw_params_any(params);
+       err = snd_pcm_hw_refine(substream, params);
+-      format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 
+-      kfree(params);
+       if (err < 0)
+-              return err;
++              goto error;
++      format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       for (fmt = 0; fmt < 32; ++fmt) {
+               if (snd_mask_test(&format_mask, fmt)) {
+                       int f = snd_pcm_oss_format_to(fmt);
+@@ -1826,7 +1825,10 @@ static int snd_pcm_oss_get_formats(struc
+                               formats |= f;
+               }
+       }
+-      return formats;
++
++ error:
++      kfree(params);
++      return err < 0 ? err : formats;
+ }
+ static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
diff --git a/queue-3.18/alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch b/queue-3.18/alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch
new file mode 100644 (file)
index 0000000..8db0639
--- /dev/null
@@ -0,0 +1,50 @@
+From a2ff19f7b70118ced291a28d5313469914de451b Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 9 Mar 2018 22:23:31 +0100
+Subject: ALSA: seq: Clear client entry before deleting else at closing
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit a2ff19f7b70118ced291a28d5313469914de451b upstream.
+
+When releasing a client, we need to clear the clienttab[] entry at
+first, then call snd_seq_queue_client_leave().  Otherwise, the
+in-flight cell in the queue might be picked up by the timer interrupt
+via snd_seq_check_queue() before calling snd_seq_queue_client_leave(),
+and it's delivered to another queue while the client is clearing
+queues.  This may eventually result in an uncleared cell remaining in
+a queue, and the later snd_seq_pool_delete() may need to wait for a
+long time until the event gets really processed.
+
+By moving the clienttab[] clearance at the beginning of release, any
+event delivery of a cell belonging to this client will fail at a later
+point, since snd_seq_client_ptr() returns NULL.  Thus the cell that
+was picked up by the timer interrupt will be returned immediately
+without further delivery, and the long stall of snd_seq_delete_pool()
+can be avoided, too.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/seq_clientmgr.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -270,12 +270,12 @@ static int seq_free_client1(struct snd_s
+       if (!client)
+               return 0;
+-      snd_seq_delete_all_ports(client);
+-      snd_seq_queue_client_leave(client->number);
+       spin_lock_irqsave(&clients_lock, flags);
+       clienttablock[client->number] = 1;
+       clienttab[client->number] = NULL;
+       spin_unlock_irqrestore(&clients_lock, flags);
++      snd_seq_delete_all_ports(client);
++      snd_seq_queue_client_leave(client->number);
+       snd_use_lock_sync(&client->use_lock);
+       snd_seq_queue_client_termination(client->number);
+       if (client->pool)
diff --git a/queue-3.18/alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch b/queue-3.18/alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch
new file mode 100644 (file)
index 0000000..742edf5
--- /dev/null
@@ -0,0 +1,170 @@
+From d0f833065221cbfcbadf19fd4102bcfa9330006a Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 9 Mar 2018 21:58:28 +0100
+Subject: ALSA: seq: Fix possible UAF in snd_seq_check_queue()
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit d0f833065221cbfcbadf19fd4102bcfa9330006a upstream.
+
+Although we've covered the races between concurrent write() and
+ioctl() in the previous patch series, there is still a possible UAF in
+the following scenario:
+
+A: user client closed          B: timer irq
+  -> snd_seq_release()           -> snd_seq_timer_interrupt()
+    -> snd_seq_free_client()       -> snd_seq_check_queue()
+                                     -> cell = snd_seq_prioq_cell_peek()
+      -> snd_seq_prioq_leave()
+         .... removing all cells
+      -> snd_seq_pool_done()
+         .... vfree()
+                                     -> snd_seq_compare_tick_time(cell)
+                                        ... Oops
+
+So the problem is that a cell is peeked and accessed without any
+protection until it's retrieved from the queue again via
+snd_seq_prioq_cell_out().
+
+This patch tries to address it, also cleans up the code by a slight
+refactoring.  snd_seq_prioq_cell_out() now receives an extra pointer
+argument.  When it's non-NULL, the function checks the event timestamp
+with the given pointer.  The caller needs to pass the right reference
+either to snd_seq_tick or snd_seq_realtime depending on the event
+timestamp type.
+
+A good news is that the above change allows us to remove the
+snd_seq_prioq_cell_peek(), too, thus the patch actually reduces the
+code size.
+
+Reviewed-by: Nicolai Stange <nstange@suse.de>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/seq_prioq.c |   28 ++++++++++++++--------------
+ sound/core/seq/seq_prioq.h |    6 ++----
+ sound/core/seq/seq_queue.c |   28 +++++++++-------------------
+ 3 files changed, 25 insertions(+), 37 deletions(-)
+
+--- a/sound/core/seq/seq_prioq.c
++++ b/sound/core/seq/seq_prioq.c
+@@ -87,7 +87,7 @@ void snd_seq_prioq_delete(struct snd_seq
+       if (f->cells > 0) {
+               /* drain prioQ */
+               while (f->cells > 0)
+-                      snd_seq_cell_free(snd_seq_prioq_cell_out(f));
++                      snd_seq_cell_free(snd_seq_prioq_cell_out(f, NULL));
+       }
+       
+       kfree(f);
+@@ -214,8 +214,18 @@ int snd_seq_prioq_cell_in(struct snd_seq
+       return 0;
+ }
++/* return 1 if the current time >= event timestamp */
++static int event_is_ready(struct snd_seq_event *ev, void *current_time)
++{
++      if ((ev->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK)
++              return snd_seq_compare_tick_time(current_time, &ev->time.tick);
++      else
++              return snd_seq_compare_real_time(current_time, &ev->time.time);
++}
++
+ /* dequeue cell from prioq */
+-struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f)
++struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f,
++                                                void *current_time)
+ {
+       struct snd_seq_event_cell *cell;
+       unsigned long flags;
+@@ -227,6 +237,8 @@ struct snd_seq_event_cell *snd_seq_prioq
+       spin_lock_irqsave(&f->lock, flags);
+       cell = f->head;
++      if (cell && current_time && !event_is_ready(&cell->event, current_time))
++              cell = NULL;
+       if (cell) {
+               f->head = cell->next;
+@@ -252,18 +264,6 @@ int snd_seq_prioq_avail(struct snd_seq_p
+       return f->cells;
+ }
+-
+-/* peek at cell at the head of the prioq */
+-struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq * f)
+-{
+-      if (f == NULL) {
+-              pr_debug("ALSA: seq: snd_seq_prioq_cell_in() called with NULL prioq\n");
+-              return NULL;
+-      }
+-      return f->head;
+-}
+-
+-
+ static inline int prioq_match(struct snd_seq_event_cell *cell,
+                             int client, int timestamp)
+ {
+--- a/sound/core/seq/seq_prioq.h
++++ b/sound/core/seq/seq_prioq.h
+@@ -44,14 +44,12 @@ void snd_seq_prioq_delete(struct snd_seq
+ int snd_seq_prioq_cell_in(struct snd_seq_prioq *f, struct snd_seq_event_cell *cell);
+ /* dequeue cell from prioq */ 
+-struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f);
++struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f,
++                                                void *current_time);
+ /* return number of events available in prioq */
+ int snd_seq_prioq_avail(struct snd_seq_prioq *f);
+-/* peek at cell at the head of the prioq */
+-struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq *f);
+-
+ /* client left queue */
+ void snd_seq_prioq_leave(struct snd_seq_prioq *f, int client, int timestamp);        
+--- a/sound/core/seq/seq_queue.c
++++ b/sound/core/seq/seq_queue.c
+@@ -271,30 +271,20 @@ void snd_seq_check_queue(struct snd_seq_
+       __again:
+       /* Process tick queue... */
+-      while ((cell = snd_seq_prioq_cell_peek(q->tickq)) != NULL) {
+-              if (snd_seq_compare_tick_time(&q->timer->tick.cur_tick,
+-                                            &cell->event.time.tick)) {
+-                      cell = snd_seq_prioq_cell_out(q->tickq);
+-                      if (cell)
+-                              snd_seq_dispatch_event(cell, atomic, hop);
+-              } else {
+-                      /* event remains in the queue */
++      for (;;) {
++              cell = snd_seq_prioq_cell_out(q->tickq,
++                                            &q->timer->tick.cur_tick);
++              if (!cell)
+                       break;
+-              }
++              snd_seq_dispatch_event(cell, atomic, hop);
+       }
+-
+       /* Process time queue... */
+-      while ((cell = snd_seq_prioq_cell_peek(q->timeq)) != NULL) {
+-              if (snd_seq_compare_real_time(&q->timer->cur_time,
+-                                            &cell->event.time.time)) {
+-                      cell = snd_seq_prioq_cell_out(q->timeq);
+-                      if (cell)
+-                              snd_seq_dispatch_event(cell, atomic, hop);
+-              } else {
+-                      /* event remains in the queue */
++      for (;;) {
++              cell = snd_seq_prioq_cell_out(q->timeq, &q->timer->cur_time);
++              if (!cell)
+                       break;
+-              }
++              snd_seq_dispatch_event(cell, atomic, hop);
+       }
+       /* free lock */
diff --git a/queue-3.18/fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch b/queue-3.18/fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch
new file mode 100644 (file)
index 0000000..cf7266c
--- /dev/null
@@ -0,0 +1,92 @@
+From a6d7cff472eea87d96899a20fa718d2bab7109f3 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Wed, 14 Mar 2018 12:10:17 -0700
+Subject: fs/aio: Add explicit RCU grace period when freeing kioctx
+
+From: Tejun Heo <tj@kernel.org>
+
+commit a6d7cff472eea87d96899a20fa718d2bab7109f3 upstream.
+
+While fixing refcounting, e34ecee2ae79 ("aio: Fix a trinity splat")
+incorrectly removed explicit RCU grace period before freeing kioctx.
+The intention seems to be depending on the internal RCU grace periods
+of percpu_ref; however, percpu_ref uses a different flavor of RCU,
+sched-RCU.  This can lead to kioctx being freed while RCU read
+protected dereferences are still in progress.
+
+Fix it by updating free_ioctx() to go through call_rcu() explicitly.
+
+v2: Comment added to explain double bouncing.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Jann Horn <jannh@google.com>
+Fixes: e34ecee2ae79 ("aio: Fix a trinity splat")
+Cc: Kent Overstreet <kent.overstreet@gmail.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: stable@vger.kernel.org # v3.13+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/aio.c |   23 +++++++++++++++++++----
+ 1 file changed, 19 insertions(+), 4 deletions(-)
+
+--- a/fs/aio.c
++++ b/fs/aio.c
+@@ -110,7 +110,8 @@ struct kioctx {
+       struct page             **ring_pages;
+       long                    nr_pages;
+-      struct work_struct      free_work;
++      struct rcu_head         free_rcu;
++      struct work_struct      free_work;      /* see free_ioctx() */
+       /*
+        * signals when all in-flight requests are done
+@@ -505,6 +506,12 @@ static int kiocb_cancel(struct kiocb *ki
+       return cancel(kiocb);
+ }
++/*
++ * free_ioctx() should be RCU delayed to synchronize against the RCU
++ * protected lookup_ioctx() and also needs process context to call
++ * aio_free_ring(), so the double bouncing through kioctx->free_rcu and
++ * ->free_work.
++ */
+ static void free_ioctx(struct work_struct *work)
+ {
+       struct kioctx *ctx = container_of(work, struct kioctx, free_work);
+@@ -518,6 +525,14 @@ static void free_ioctx(struct work_struc
+       kmem_cache_free(kioctx_cachep, ctx);
+ }
++static void free_ioctx_rcufn(struct rcu_head *head)
++{
++      struct kioctx *ctx = container_of(head, struct kioctx, free_rcu);
++
++      INIT_WORK(&ctx->free_work, free_ioctx);
++      schedule_work(&ctx->free_work);
++}
++
+ static void free_ioctx_reqs(struct percpu_ref *ref)
+ {
+       struct kioctx *ctx = container_of(ref, struct kioctx, reqs);
+@@ -526,8 +541,8 @@ static void free_ioctx_reqs(struct percp
+       if (ctx->requests_done)
+               complete(ctx->requests_done);
+-      INIT_WORK(&ctx->free_work, free_ioctx);
+-      schedule_work(&ctx->free_work);
++      /* Synchronize against RCU protected table->table[] dereferences */
++      call_rcu(&ctx->free_rcu, free_ioctx_rcufn);
+ }
+ /*
+@@ -749,7 +764,7 @@ static int kill_ioctx(struct mm_struct *
+       table->table[ctx->id] = NULL;
+       spin_unlock(&mm->ioctx_lock);
+-      /* percpu_ref_kill() will do the necessary call_rcu() */
++      /* free_ioctx_reqs() will do the necessary RCU synchronization */
+       wake_up_all(&ctx->wait);
+       /*
diff --git a/queue-3.18/fs-aio-use-rcu-accessors-for-kioctx_table-table.patch b/queue-3.18/fs-aio-use-rcu-accessors-for-kioctx_table-table.patch
new file mode 100644 (file)
index 0000000..2e1d2de
--- /dev/null
@@ -0,0 +1,87 @@
+From d0264c01e7587001a8c4608a5d1818dba9a4c11a Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Wed, 14 Mar 2018 12:10:17 -0700
+Subject: fs/aio: Use RCU accessors for kioctx_table->table[]
+
+From: Tejun Heo <tj@kernel.org>
+
+commit d0264c01e7587001a8c4608a5d1818dba9a4c11a upstream.
+
+While converting ioctx index from a list to a table, db446a08c23d
+("aio: convert the ioctx list to table lookup v3") missed tagging
+kioctx_table->table[] as an array of RCU pointers and using the
+appropriate RCU accessors.  This introduces a small window in the
+lookup path where init and access may race.
+
+Mark kioctx_table->table[] with __rcu and use the approriate RCU
+accessors when using the field.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Jann Horn <jannh@google.com>
+Fixes: db446a08c23d ("aio: convert the ioctx list to table lookup v3")
+Cc: Benjamin LaHaise <bcrl@kvack.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: stable@vger.kernel.org # v3.12+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/aio.c |   19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+--- a/fs/aio.c
++++ b/fs/aio.c
+@@ -68,9 +68,9 @@ struct aio_ring {
+ #define AIO_RING_PAGES        8
+ struct kioctx_table {
+-      struct rcu_head rcu;
+-      unsigned        nr;
+-      struct kioctx   *table[];
++      struct rcu_head         rcu;
++      unsigned                nr;
++      struct kioctx __rcu     *table[];
+ };
+ struct kioctx_cpu {
+@@ -583,9 +583,9 @@ static int ioctx_add_table(struct kioctx
+       while (1) {
+               if (table)
+                       for (i = 0; i < table->nr; i++)
+-                              if (!table->table[i]) {
++                              if (!rcu_access_pointer(table->table[i])) {
+                                       ctx->id = i;
+-                                      table->table[i] = ctx;
++                                      rcu_assign_pointer(table->table[i], ctx);
+                                       spin_unlock(&mm->ioctx_lock);
+                                       /* While kioctx setup is in progress,
+@@ -760,8 +760,8 @@ static int kill_ioctx(struct mm_struct *
+       spin_lock(&mm->ioctx_lock);
+       table = rcu_dereference_raw(mm->ioctx_table);
+-      WARN_ON(ctx != table->table[ctx->id]);
+-      table->table[ctx->id] = NULL;
++      WARN_ON(ctx != rcu_access_pointer(table->table[ctx->id]));
++      RCU_INIT_POINTER(table->table[ctx->id], NULL);
+       spin_unlock(&mm->ioctx_lock);
+       /* free_ioctx_reqs() will do the necessary RCU synchronization */
+@@ -817,7 +817,8 @@ void exit_aio(struct mm_struct *mm)
+               return;
+       for (i = 0; i < table->nr; ++i) {
+-              struct kioctx *ctx = table->table[i];
++              struct kioctx *ctx =
++                      rcu_dereference_protected(table->table[i], true);
+               struct completion requests_done =
+                       COMPLETION_INITIALIZER_ONSTACK(requests_done);
+@@ -1003,7 +1004,7 @@ static struct kioctx *lookup_ioctx(unsig
+       if (!table || id >= table->nr)
+               goto out;
+-      ctx = table->table[id];
++      ctx = rcu_dereference(table->table[id]);
+       if (ctx && ctx->user_id == ctx_id) {
+               percpu_ref_get(&ctx->users);
+               ret = ctx;
diff --git a/queue-3.18/lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch b/queue-3.18/lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch
new file mode 100644 (file)
index 0000000..146a4e8
--- /dev/null
@@ -0,0 +1,49 @@
+From 3b821409632ab778d46e807516b457dfa72736ed Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Fri, 23 Feb 2018 20:47:17 -0500
+Subject: lock_parent() needs to recheck if dentry got __dentry_kill'ed under it
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 3b821409632ab778d46e807516b457dfa72736ed upstream.
+
+In case when dentry passed to lock_parent() is protected from freeing only
+by the fact that it's on a shrink list and trylock of parent fails, we
+could get hit by __dentry_kill() (and subsequent dentry_kill(parent))
+between unlocking dentry and locking presumed parent.  We need to recheck
+that dentry is alive once we lock both it and parent *and* postpone
+rcu_read_unlock() until after that point.  Otherwise we could return
+a pointer to struct dentry that already is rcu-scheduled for freeing, with
+->d_lock held on it; caller's subsequent attempt to unlock it can end
+up with memory corruption.
+
+Cc: stable@vger.kernel.org # 3.12+, counting backports
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/dcache.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -581,11 +581,16 @@ again:
+               spin_unlock(&parent->d_lock);
+               goto again;
+       }
+-      rcu_read_unlock();
+-      if (parent != dentry)
++      if (parent != dentry) {
+               spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
+-      else
++              if (unlikely(dentry->d_lockref.count < 0)) {
++                      spin_unlock(&parent->d_lock);
++                      parent = NULL;
++              }
++      } else {
+               parent = NULL;
++      }
++      rcu_read_unlock();
+       return parent;
+ }
index 9471872be7e26e077e605e1160a7fe81209e7e82..e6cc4601b89232e1749469be9e0dc0f667a0d2f0 100644 (file)
@@ -57,3 +57,9 @@ mac80211-remove-bug-when-interface-type-is-invalid.patch
 asoc-nuc900-fix-a-loop-timeout-test.patch
 rcutorture-configinit-fix-build-directory-error-message.patch
 ima-relax-requiring-a-file-signature-for-new-files-with-zero-length.patch
+alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch
+alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch
+alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch
+lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch
+fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch
+fs-aio-use-rcu-accessors-for-kioctx_table-table.patch