]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: validate argument pointer to d_path()
authorKris Van Hees <kris.van.hees@oracle.com>
Tue, 23 Jun 2015 10:51:35 +0000 (06:51 -0400)
committerKris Van Hees <kris.van.hees@oracle.com>
Tue, 21 Jul 2015 06:51:24 +0000 (02:51 -0400)
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 <kris.van.hees@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
dtrace/NEWS
dtrace/dtrace-module.spec
dtrace/dtrace_dif.c

index 180a05139a4ca823643e3804bfd01967756d1347..6e8025234ec643119211e4b633aaa83cfaa116e5 100644 (file)
@@ -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
index 3a0d5771a6ab12dca6cbfff69ebc321e2c7e8067..b00419f5b411b3dd8d9d5f03a1475f970e8c1d1f 100644 (file)
@@ -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 <kris.van.hees@oracle.com> - 0.4.5-2
+- Validate d_path() argument pointer to avoid crash.
+  [Orabug: 21304207]
 * Wed Jun 17 2015 Kris Van Hees <kris.van.hees@oracle.com> - 0.4.5-1
 - Support USDT for 32-bit applications on 64-bit hosts.
   [Orabug: 21219315]
index cb700dcf72e08116346389dac73b221b927c8e15..33c7e197e975b607fe8da350eff9f0e1d91b1432 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <linux/dtrace_cpu.h>
+#include <linux/fdtable.h>
 #include <linux/hardirq.h>
 #include <linux/in6.h>
 #include <linux/inet.h>
@@ -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;
                }