]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: ensure return value of access_process_vm() is > 0
authorTodd Vierling <todd.vierling@oracle.com>
Tue, 1 Dec 2015 20:59:59 +0000 (15:59 -0500)
committerKris Van Hees <kris.van.hees@oracle.com>
Tue, 1 Dec 2015 23:50:53 +0000 (18:50 -0500)
If access_process_vm() returns a value <= 0, the loop intended to replace
NULs with whitespace in the ps string could turn into a memory sprayer
by incrementing its loop counter all the way to (uintptr_t)-1. This
often shows up as crashes with PTEs showing 0x20 stuffed inside, e.g.:

[  630.136149] PGD 66f7f067 PUD 802a5067 PMD 18fff0067 PTE 2020200208ad2025
[  630.136194] Bad pagetable: 000d [#1] SMP

[ 1698.220469] PGD 5cebd067 PUD 5ced6067 PMD 17fe6d067 PTE 8020202032652867
[ 1698.220511] Bad pagetable: 000d [#1] SMP

[  438.486319] PGD 136cee067 PUD 136d9b067 PMD 13ba2067 PTE 802020012c8bf867
[  438.486364] Bad pagetable: 000d [#1] SMP

though it can cause other crashes. To fix, bracket the loop logic in
a test of access_process_vm()'s return value.

Orabug: 22295336

Signed-off-by: Todd Vierling <todd.vierling@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
kernel/dtrace/dtrace_os.c

index 577933abf824fa8309b529d91590500e5e3b3236..cb07fb10d92f23ea11109b1a8c3f9064db175bee 100644 (file)
@@ -125,15 +125,21 @@ void dtrace_psinfo_alloc(struct task_struct *tsk)
 
                        i = access_process_vm(tsk, mm->arg_start,
                                              psinfo->psargs, len, 0);
-                       if (i < len)
-                               len = i;
 
-                       for (i = 0, --len; i < len; i++) {
-                               if (psinfo->psargs[i] == '\0')
-                                       psinfo->psargs[i] = ' ';
+                       if (i > 0) {
+                               if (i < len)
+                                       len = i;
+
+                               for (i = 0, --len; i < len; i++) {
+                                       if (psinfo->psargs[i] == '\0')
+                                               psinfo->psargs[i] = ' ';
+                               }
                        }
                }
 
+               if (i < 0)
+                       i = 0;
+
                while (i < PR_PSARGS_SZ)
                        psinfo->psargs[i++] = 0;