linux-stable/arch
Michael Ellerman 6385564306 powerpc/32: Fix overread/overwrite of thread_struct via ptrace
commit 8e12784444 upstream.

The ptrace PEEKUSR/POKEUSR (aka PEEKUSER/POKEUSER) API allows a process
to read/write registers of another process.

To get/set a register, the API takes an index into an imaginary address
space called the "USER area", where the registers of the process are
laid out in some fashion.

The kernel then maps that index to a particular register in its own data
structures and gets/sets the value.

The API only allows a single machine-word to be read/written at a time.
So 4 bytes on 32-bit kernels and 8 bytes on 64-bit kernels.

The way floating point registers (FPRs) are addressed is somewhat
complicated, because double precision float values are 64-bit even on
32-bit CPUs. That means on 32-bit kernels each FPR occupies two
word-sized locations in the USER area. On 64-bit kernels each FPR
occupies one word-sized location in the USER area.

Internally the kernel stores the FPRs in an array of u64s, or if VSX is
enabled, an array of pairs of u64s where one half of each pair stores
the FPR. Which half of the pair stores the FPR depends on the kernel's
endianness.

To handle the different layouts of the FPRs depending on VSX/no-VSX and
big/little endian, the TS_FPR() macro was introduced.

Unfortunately the TS_FPR() macro does not take into account the fact
that the addressing of each FPR differs between 32-bit and 64-bit
kernels. It just takes the index into the "USER area" passed from
userspace and indexes into the fp_state.fpr array.

On 32-bit there are 64 indexes that address FPRs, but only 32 entries in
the fp_state.fpr array, meaning the user can read/write 256 bytes past
the end of the array. Because the fp_state sits in the middle of the
thread_struct there are various fields than can be overwritten,
including some pointers. As such it may be exploitable.

It has also been observed to cause systems to hang or otherwise
misbehave when using gdbserver, and is probably the root cause of this
report which could not be easily reproduced:
  https://lore.kernel.org/linuxppc-dev/dc38afe9-6b78-f3f5-666b-986939e40fc6@keymile.com/

Rather than trying to make the TS_FPR() macro even more complicated to
fix the bug, or add more macros, instead add a special-case for 32-bit
kernels. This is more obvious and hopefully avoids a similar bug
happening again in future.

Note that because 32-bit kernels never have VSX enabled the code doesn't
need to consider TS_FPRWIDTH/OFFSET at all. Add a BUILD_BUG_ON() to
ensure that 32-bit && VSX is never enabled.

Fixes: 87fec0514f ("powerpc: PTRACE_PEEKUSR/PTRACE_POKEUSER of FPR registers in little endian builds")
Cc: stable@vger.kernel.org # v3.13+
Reported-by: Ariel Miculas <ariel.miculas@belden.com>
Tested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220609133245.573565-1-mpe@ellerman.id.au
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-06-14 18:41:51 +02:00
..
alpha alpha: fix alloc_zeroed_user_highpage_movable() 2022-06-09 10:25:34 +02:00
arc ARC: entry: fix syscall_trace_exit argument 2022-04-27 14:41:15 +02:00
arm ep93xx: clock: Do not return the address of the freed memory 2022-06-14 18:41:21 +02:00
arm64 bpf, arm64: Clear prog->jited_len along prog->jited 2022-06-14 18:41:31 +02:00
csky csky: patch_text: Fixup last cpu should be master 2022-06-09 10:26:25 +02:00
h8300 bitmap patches for 5.17-rc1 2022-01-23 06:20:44 +02:00
hexagon uaccess: fix integer overflow on access_ok() 2022-03-28 10:03:21 +02:00
ia64 ia64: define get_cycles macro for arch-override 2022-05-30 09:27:13 +02:00
m68k m68knommu: fix undefined reference to `mach_get_rtc_pll' 2022-06-14 18:41:28 +02:00
microblaze uaccess: fix nios2 and microblaze get_user_8() 2022-04-08 13:57:49 +02:00
mips mips: cpc: Fix refcount leak in mips_cpc_default_phys_base 2022-06-14 18:41:26 +02:00
nds32 nds32: fix access_ok() checks in get/put_user 2022-03-28 10:03:22 +02:00
nios2 nios2: use fallback for random_get_entropy() instead of zero 2022-05-30 09:27:14 +02:00
openrisc openrisc: start CPU timer early in boot 2022-06-09 10:25:28 +02:00
parisc parisc/stifb: Implement fb_is_primary_device() 2022-06-09 10:25:12 +02:00
powerpc powerpc/32: Fix overread/overwrite of thread_struct via ptrace 2022-06-14 18:41:51 +02:00
riscv RISC-V: use memcpy for kexec_file mode 2022-06-14 18:41:28 +02:00
s390 s390/gmap: voluntarily schedule during key setting 2022-06-14 18:41:41 +02:00
sh bitmap patches for 5.17-rc1 2022-01-23 06:20:44 +02:00
sparc signal: Deliver SIGTRAP on perf event asynchronously if blocked 2022-06-09 10:25:41 +02:00
um um: line: Use separate IRQs per line 2022-06-14 18:41:39 +02:00
x86 x86/cpu: Elide KCSAN for cpu_has() and friends 2022-06-14 18:41:39 +02:00
xtensa xtensa/simdisk: fix proc_read_simdisk() 2022-06-09 10:26:28 +02:00
.gitignore
Kconfig stack: Constrain and fix stack offset randomization with Clang builds 2022-04-08 13:57:34 +02:00