CHROMIUM: android: binder: Fix potential scheduling-while-atomic
authorAndrew Bresticker <abrestic@chromium.org>
Fri, 23 Oct 2015 22:13:42 +0000 (15:13 -0700)
committerStricted <info@stricted.net>
Thu, 11 Oct 2018 16:12:57 +0000 (18:12 +0200)
(cherry picked from commit 166b45af97359159f9585a836c9849e725e31fd6)

Commit f1e7f0a724f6 ("android: binder: Disable preemption while holding
the global binder lock.") re-enabled preemption around most of the sites
where calls to potentially sleeping functions were made, but missed
__alloc_fd(), which can sleep if the fdtable needs to be resized.
Re-enable preemption around __alloc_fd() as well as __fd_install() which
can now sleep in upstream kernels as of commit 8a81252b774b ("fs/file.c:
don't acquire files->file_lock in fd_install()").

BUG=chrome-os-partner:44012
TEST=Build and boot on Smaug.

Change-Id: I9819c4b95876f697e75b1b84810b6c520d9c33ec
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/308582
Reviewed-by: Stephen Barber <smbarber@chromium.org>
Reviewed-by: Riley Andrews <riandrews@google.com>
Bug: 30141999

drivers/android/binder.c

index e697701259753f4368675bf657f9fb1a02ca311c..deb932dea529f01467334e677a23c7d2021d5647 100644 (file)
@@ -379,6 +379,7 @@ static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
        struct files_struct *files = proc->files;
        unsigned long rlim_cur;
        unsigned long irqs;
+       int ret;
 
        if (files == NULL)
                return -ESRCH;
@@ -389,7 +390,11 @@ static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
        rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
        unlock_task_sighand(proc->tsk, &irqs);
 
-       return __alloc_fd(files, 0, rlim_cur, flags);
+       preempt_enable_no_resched();
+       ret = __alloc_fd(files, 0, rlim_cur, flags);
+       preempt_disable();
+
+       return ret;
 }
 
 /*
@@ -398,8 +403,11 @@ static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 static void task_fd_install(
        struct binder_proc *proc, unsigned int fd, struct file *file)
 {
-       if (proc->files)
+       if (proc->files) {
+               preempt_enable_no_resched();
                __fd_install(proc->files, fd, file);
+               preempt_disable();
+       }
 }
 
 /*