From 2a5a3c7b83d9596366ee5583784175f5867e05c4 Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Tue, 23 Jun 2015 06:51:35 -0400 Subject: [PATCH] dtrace: validate argument pointer to d_path() When an invalid pointer was being passed to d_path(), the system could crash with an OOPS. This was the result of the kernel implementation (reasonably) expecting the pointer to be referencing a valid path struct. We now validate the argument passed to d_path() against the paths for files known to the current task. Orabug: 21304207 Signed-off-by: Kris Van Hees Acked-by: Nick Alcock --- dtrace/NEWS | 31 +++++++++++++++++++++++++++++++ dtrace/dtrace-module.spec | 5 ++++- dtrace/dtrace_dif.c | 32 +++++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/dtrace/NEWS b/dtrace/NEWS index 180a05139a4c..6e8025234ec6 100644 --- a/dtrace/NEWS +++ b/dtrace/NEWS @@ -15,6 +15,10 @@ Changes: - The code has been restructured to facilitate supporting architectures other than x86_64 in future releases. + - The d_path() D subroutine requires its argument to be a pointer to a + path struct that corresponds to a file that is known to the current + task (see bugfixes below). + Bugfixes: - Fixed a (minor) memory leak problem with the help tracing facility in @@ -35,6 +39,12 @@ Bugfixes: obtained from the scratch area of memory that DTrace provides for probe processing. + - It was possible to cause a system crash by passing an invalid pointer + to d_path(). Due to its implementation, it is not possible to depend + on safe memory accesses to avoid this. Instead, the pointer passed as + argument must be validated prior to calling d_path() in the kernel. + + Release 0.4.4 (Mar 12th, 2015) ------------------------------ Kernel release: 3.8.13-69.el6uek @@ -45,6 +55,7 @@ Bugfixes: to work around problems in Yum where a symbol has had both versioned and unversioned provides over time. + Release 0.4.3 (May 1st, 2014) ----------------------------- Kernel release: 3.8.13-33.el6uek @@ -60,6 +71,7 @@ Changes: - The pid and ppid variables were being reported based on the kernel task PID, which is not the same as the userspace concept of a PID (for threaded applications). We now pass (more correctly) the thread group id (tgid). + - Since userspace doesn't know about thread kernel level) pids, we are now also passing the tgid in the result of ustack, usym, etc... We pass the tgid in the first slot, and the (kernel) pid in the second slot. @@ -79,6 +91,7 @@ Known problems: This is overall a non-harmful regression that will be addressed in a future release. + Release 0.4.2 (Dec 20th, 2013) ------------------------------ Kernel release: 3.8.13-22.el6uek @@ -86,8 +99,10 @@ Kernel release: 3.8.13-22.el6uek Changes: - SDT probe points in kernel modules are now supported. + - The 'vtimestamp' D variable has been implemented. + Release 0.4.1 (Nov 6th, 2013) ------------------------------ Kernel release: 3.8.13-16.2.1.el6uek @@ -98,6 +113,7 @@ Changes: context of a userspace process. I.e. it is not permissible for the main executable and a loaded shared library, or two loaded shared libraries, to list the same provider name in their DOF sections. + - A new cyclic implementation has been included in the UEK3 kernel, replacing the more error prone former version. The modules code has been updated to use that new implementation. @@ -105,15 +121,21 @@ Changes: Bugfixes: - Lock ordering problems that were inherited from the original code are fixed. + - Userspace stack memory accesses are now performed in a safe manner. + - A race condition between speculative tracing buffer cleaning and destroying consumer state has been resolved. + - A memory leak related to consumer state has been fixed. + - A provider reference counter calculation problem was resolved. + - The 'errno' D variable now holds the correct value during syscall:::return probe action execution, i.e. 0 if the syscall completed without an error, and a valid error code if the syscall failed. + Release 0.4.0 (Sep 20th, 2013) ------------------------------ Kernel release: 3.8.13-16.el6uek @@ -123,9 +145,11 @@ New features: - Support for meta-providers, such as fasttrap (used for userspace tracing). A meta-provider implements a framework to instantiate providers dynamically (on demand). + - Userspace Statically Defined Tracing (USDT) provides support for SDT-alike probes in userspace executable and libraries. Two types of probes are available: regular SDT-alike probes, and is-enabled probes. + - The fasttrap provider has been implemented, although it is currently only supporting USDT probes. @@ -136,22 +160,29 @@ Changes: multiple providers that essentially share (the majority of) a single implementation, such as SDT where probes are grouped together into providers even though they are all provided by the same provider (sdt). + - The DTrace header files in the kernel proper, the kernel modules, and the userspace utility have been restructured to avoid duplication and to offer a more consistent and clean design. This also offers better support for custom consumers or other DTrace-related utilities. + - The systrace provider has been updated to account for changes in the Linux kernel (between 2.6.39 and 3.8.13). Bugfixes: - It is now possible to get the correct value for the ERR registers. + - The ustack() and jstack() actions were not passing the PID correctly as the first element in the result array. + - The ustack() action implementation has been replaced. + - Several obscure locking problems have been resolved. + - Correct handling of arg5 through arg9. + Release 0.3.0 (Sep 14th, 2012) ------------------------------ Kernel release: 2.6.39-201.0.1.el6uek diff --git a/dtrace/dtrace-module.spec b/dtrace/dtrace-module.spec index 3a0d5771a6ab..b00419f5b411 100644 --- a/dtrace/dtrace-module.spec +++ b/dtrace/dtrace-module.spec @@ -42,7 +42,7 @@ if rpm.vercmp(kver, "3.8.13-87") >= 0 then rpm.define("srcver 0.4.5") - rpm.define("bldrel 1") + rpm.define("bldrel 2") rpm.define("dt_vcode "..rpm.expand("%{dt_0_4_5}")) elseif rpm.vercmp(kver, "3.8.13-69") >= 0 then rpm.define("srcver 0.4.4") @@ -244,6 +244,9 @@ rm -rf %{buildroot} %changelog %if %{dt_vcode} >= %{dt_0_4_5} +* Tue Jun 23 2015 Kris Van Hees - 0.4.5-2 +- Validate d_path() argument pointer to avoid crash. + [Orabug: 21304207] * Wed Jun 17 2015 Kris Van Hees - 0.4.5-1 - Support USDT for 32-bit applications on 64-bit hosts. [Orabug: 21219315] diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c index cb700dcf72e0..33c7e197e975 100644 --- a/dtrace/dtrace_dif.c +++ b/dtrace/dtrace_dif.c @@ -26,6 +26,7 @@ */ #include +#include #include #include #include @@ -3837,6 +3838,10 @@ inetout: char *dest = (char *)mstate->dtms_scratch_ptr; char *ptr; uint64_t size = state->dts_options[DTRACEOPT_STRSIZE]; + unsigned int fd; + struct files_struct + *files = current->files; + struct fdtable *fdt; if (!dtrace_canload((uintptr_t)path, sizeof(struct path), mstate, vstate)) { @@ -3850,9 +3855,34 @@ inetout: break; } + if (spin_is_locked(&files->file_lock) || + !spin_trylock(&files->file_lock)) { + regs[rd] = 0; + break; + } + + fdt = files->fdt; + + /* + * We (currently) limit the d_path() subroutine to paths that + * relate to open files in the current task. + */ + for (fd = 0; fd < fdt->max_fds; fd++) { + if (fdt->fd[fd] && &fdt->fd[fd]->f_path == path) + break; + } + + spin_unlock(&files->file_lock); + + if (fd >= fdt->max_fds) { + *flags |= CPU_DTRACE_BADADDR; + *illval = (uintptr_t)path; + regs[rd] = 0; + break; + } + ptr = d_path(path, dest, size); if (ptr < 0) { - DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH); regs[rd] = 0; break; } -- 2.50.1