1
0
Fork 0

io_uring: Fix current->fs handling in io_sq_wq_submit_work()

No upstream commit, this is a fix to a stable 5.4 specific backport.

The intention of backport commit cac68d12c5 ("io_uring: grab ->fs as part
of async offload") as found in the stable 5.4 tree was to make
io_sq_wq_submit_work() to switch the workqueue task's ->fs over to the
submitting task's one during the IO operation.

However, due to a small logic error, this change turned out to not have any
actual effect. From a high level, the relevant code in
io_sq_wq_submit_work() looks like

  old_fs_struct = current->fs;
  do {
          ...
          if (req->fs != current->fs && current->fs != old_fs_struct) {
                  task_lock(current);
                  if (req->fs)
                          current->fs = req->fs;
                  else
                          current->fs = old_fs_struct;
                  task_unlock(current);
          }
          ...
  } while (req);

The if condition is supposed to cover the case that current->fs doesn't
match what's needed for processing the request, but observe how it fails
to ever evaluate to true due to the second clause:
current->fs != old_fs_struct will be false in the first iteration as per
the initialization of old_fs_struct and because this prevents current->fs
from getting replaced, the same follows inductively for all subsequent
iterations.

Fix said if condition such that
- if req->fs is set and doesn't match current->fs, the latter will be
  switched to the former
- or if req->fs is unset, the switch back to the initial old_fs_struct
  will be made, if necessary.

While at it, also correct the condition for the ->fs related cleanup right
before the return of io_sq_wq_submit_work(): currently, old_fs_struct is
restored only if it's non-NULL. It is always non-NULL though and thus, the
if-condition is rendundant. Supposedly, the motivation had been to optimize
and avoid switching current->fs back to the initial old_fs_struct in case
it is found to have the desired value already. Make it so.

Cc: stable@vger.kernel.org # v5.4
Fixes: cac68d12c5 ("io_uring: grab ->fs as part of async offload")
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Nicolai Stange <nstange@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
5.4-rM2-2.2.x-imx-squashed
Nicolai Stange 2021-01-27 14:34:43 +01:00 committed by Greg Kroah-Hartman
parent 336bb7dc5a
commit c4a23c852e
1 changed files with 3 additions and 2 deletions

View File

@ -2226,7 +2226,8 @@ restart:
/* Ensure we clear previously set non-block flag */
req->rw.ki_flags &= ~IOCB_NOWAIT;
if (req->fs != current->fs && current->fs != old_fs_struct) {
if ((req->fs && req->fs != current->fs) ||
(!req->fs && current->fs != old_fs_struct)) {
task_lock(current);
if (req->fs)
current->fs = req->fs;
@ -2351,7 +2352,7 @@ out:
mmput(cur_mm);
}
revert_creds(old_cred);
if (old_fs_struct) {
if (old_fs_struct != current->fs) {
task_lock(current);
current->fs = old_fs_struct;
task_unlock(current);