diff options
author | Rasmus Villemoes <linux@rasmusvillemoes.dk> | 2020-01-15 19:41:49 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-01-22 15:28:14 +0100 |
commit | c9d6b287d786db3a6bf3d99c1d99cd7e1d639485 (patch) | |
tree | 658824f220627ff2647968b6784266f55b385dc0 /drivers/base/devtmpfs.c | |
parent | 0707cfa5c3ef58effb143db9db6d6e20503f9dec (diff) | |
download | linux-c9d6b287d786db3a6bf3d99c1d99cd7e1d639485.tar.bz2 |
devtmpfs: fix theoretical stale pointer deref in devtmpfsd()
After complete(&setup_done), devtmpfs_init proceeds and may actually
return, invalidating the *err pointer, before devtmpfsd() proceeds to
reading back *err.
This is of course completely theoretical since the error conditions
never trigger in practice, and even if they did, nobody cares about
the exit value from a kernel thread, so it doesn't matter if we happen
to read back some garbage from some other stack frame. Still, this
isn't a pattern that should be copy-pasted, so fix it.
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Link: https://lore.kernel.org/r/20200115184154.3492-2-linux@rasmusvillemoes.dk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/devtmpfs.c')
-rw-r--r-- | drivers/base/devtmpfs.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 6cdbf1531238..ccb046fe12b7 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -390,12 +390,13 @@ static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid, static int devtmpfsd(void *p) { - int *err = p; - *err = ksys_unshare(CLONE_NEWNS); - if (*err) + int err; + + err = ksys_unshare(CLONE_NEWNS); + if (err) goto out; - *err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL); - if (*err) + err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL); + if (err) goto out; ksys_chdir("/.."); /* will traverse into overmounted root */ ksys_chroot("."); @@ -421,8 +422,9 @@ static int devtmpfsd(void *p) } return 0; out: + *(int *)p = err; complete(&setup_done); - return *err; + return err; } /* |