1*4882a593Smuzhiyun// SPDX-License-Identifier: GPL-2.0-only 2*4882a593Smuzhiyun/// 3*4882a593Smuzhiyun/// Use kfree_sensitive, kvfree_sensitive rather than memset or 4*4882a593Smuzhiyun/// memzero_explicit followed by kfree. 5*4882a593Smuzhiyun/// 6*4882a593Smuzhiyun// Confidence: High 7*4882a593Smuzhiyun// Copyright: (C) 2020 Denis Efremov ISPRAS 8*4882a593Smuzhiyun// Options: --no-includes --include-headers 9*4882a593Smuzhiyun// 10*4882a593Smuzhiyun// Keywords: kfree_sensitive, kvfree_sensitive 11*4882a593Smuzhiyun// 12*4882a593Smuzhiyun 13*4882a593Smuzhiyunvirtual context 14*4882a593Smuzhiyunvirtual patch 15*4882a593Smuzhiyunvirtual org 16*4882a593Smuzhiyunvirtual report 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun@initialize:python@ 19*4882a593Smuzhiyun@@ 20*4882a593Smuzhiyun# kmalloc_oob_in_memset uses memset to explicitly trigger out-of-bounds access 21*4882a593Smuzhiyunfilter = frozenset(['kmalloc_oob_in_memset', 22*4882a593Smuzhiyun 'kfree_sensitive', 'kvfree_sensitive']) 23*4882a593Smuzhiyun 24*4882a593Smuzhiyundef relevant(p): 25*4882a593Smuzhiyun return not (filter & {el.current_element for el in p}) 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun@cond@ 28*4882a593Smuzhiyunposition ok; 29*4882a593Smuzhiyun@@ 30*4882a593Smuzhiyun 31*4882a593Smuzhiyunif (...) 32*4882a593Smuzhiyun \(memset@ok\|memzero_explicit@ok\)(...); 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun@r depends on !patch forall@ 35*4882a593Smuzhiyunexpression E; 36*4882a593Smuzhiyunposition p : script:python() { relevant(p) }; 37*4882a593Smuzhiyunposition m != cond.ok; 38*4882a593Smuzhiyuntype T; 39*4882a593Smuzhiyun@@ 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun( 42*4882a593Smuzhiyun* memset@m((T)E, 0, ...); 43*4882a593Smuzhiyun| 44*4882a593Smuzhiyun* memzero_explicit@m((T)E, ...); 45*4882a593Smuzhiyun) 46*4882a593Smuzhiyun ... when != E 47*4882a593Smuzhiyun when strict 48*4882a593Smuzhiyun* \(kfree\|vfree\|kvfree\)(E)@p; 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun@rp_memzero depends on patch@ 51*4882a593Smuzhiyunexpression E, size; 52*4882a593Smuzhiyunposition p : script:python() { relevant(p) }; 53*4882a593Smuzhiyunposition m != cond.ok; 54*4882a593Smuzhiyuntype T; 55*4882a593Smuzhiyun@@ 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun- memzero_explicit@m((T)E, size); 58*4882a593Smuzhiyun ... when != E 59*4882a593Smuzhiyun when strict 60*4882a593Smuzhiyun( 61*4882a593Smuzhiyun- kfree(E)@p; 62*4882a593Smuzhiyun+ kfree_sensitive(E); 63*4882a593Smuzhiyun| 64*4882a593Smuzhiyun- \(vfree\|kvfree\)(E)@p; 65*4882a593Smuzhiyun+ kvfree_sensitive(E, size); 66*4882a593Smuzhiyun) 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun@rp_memset depends on patch@ 69*4882a593Smuzhiyunexpression E, size; 70*4882a593Smuzhiyunposition p : script:python() { relevant(p) }; 71*4882a593Smuzhiyunposition m != cond.ok; 72*4882a593Smuzhiyuntype T; 73*4882a593Smuzhiyun@@ 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun- memset@m((T)E, 0, size); 76*4882a593Smuzhiyun ... when != E 77*4882a593Smuzhiyun when strict 78*4882a593Smuzhiyun( 79*4882a593Smuzhiyun- kfree(E)@p; 80*4882a593Smuzhiyun+ kfree_sensitive(E); 81*4882a593Smuzhiyun| 82*4882a593Smuzhiyun- \(vfree\|kvfree\)(E)@p; 83*4882a593Smuzhiyun+ kvfree_sensitive(E, size); 84*4882a593Smuzhiyun) 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun@script:python depends on report@ 87*4882a593Smuzhiyunp << r.p; 88*4882a593Smuzhiyunm << r.m; 89*4882a593Smuzhiyun@@ 90*4882a593Smuzhiyun 91*4882a593Smuzhiyunmsg = "WARNING opportunity for kfree_sensitive/kvfree_sensitive (memset at line %s)" 92*4882a593Smuzhiyuncoccilib.report.print_report(p[0], msg % (m[0].line)) 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun@script:python depends on org@ 95*4882a593Smuzhiyunp << r.p; 96*4882a593Smuzhiyunm << r.m; 97*4882a593Smuzhiyun@@ 98*4882a593Smuzhiyun 99*4882a593Smuzhiyunmsg = "WARNING opportunity for kfree_sensitive/kvfree_sensitive (memset at line %s)" 100*4882a593Smuzhiyuncoccilib.org.print_todo(p[0], msg % (m[0].line)) 101