From 358142dd8cbbfa2abb1090aca1b636b98ed75ef5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 3 Nov 2011 10:09:57 -0700 Subject: [PATCH 1/7] scripts/tags.sh: Add Page flag function magic It takes a while to find the macro-magically defined Page*() functions defined in include/linux/page-flags.h if you're new to the kernel. Add some magic to the tags script to transform these macros into the actual functions they are, so that tag jumping in the mm code is a bit easier. Signed-off-by: Stephen Boyd Signed-off-by: Michal Marek --- scripts/tags.sh | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/scripts/tags.sh b/scripts/tags.sh index 38f6617a2cb1..028dc5ca857d 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -132,7 +132,28 @@ exuberant() --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ - --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' + --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ + --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' all_kconfigs | xargs $1 -a \ --langdef=kconfig --language-force=kconfig \ @@ -154,7 +175,28 @@ emacs() --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \ --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ - --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' + --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ + --regex='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ + --regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ + --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ + --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ + --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' all_kconfigs | xargs $1 -a \ --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' From ff894e396b4d0b5383127c1bcb2cd3879946526e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 26 Nov 2011 22:02:00 +0300 Subject: [PATCH 2/7] ctags: remove struct forward declarations They're quite pointless and obscure location of real structure definition. Signed-off-by: Alexey Dobriyan Signed-off-by: Michal Marek --- scripts/tags.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/tags.sh b/scripts/tags.sh index 028dc5ca857d..833813a99e7c 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -167,6 +167,8 @@ exuberant() --langdef=dotconfig --language-force=dotconfig \ --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' + # Remove structure forward declarations. + LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' tags } emacs() From d0bc1fb4672b978b608400a5112249cdbc28f9ae Mon Sep 17 00:00:00 2001 From: Greg Dietsche Date: Sat, 5 Nov 2011 20:59:43 -0500 Subject: [PATCH 3/7] coccicheck: add M= option to control which dir is processed Examples: make coccicheck M=drivers/net/wireless/ make coccicheck SUBDIRS=drivers/net/wireless/ Version 2: fix patch file names when using M= tell coccinelle where the include files are Version 3: Add second include option to support out of tree development Fix error message Signed-off-by: Greg Dietsche Acked-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccicheck | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/coccicheck b/scripts/coccicheck index 1bb1a1bd2daa..3c2776466d87 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -9,14 +9,23 @@ if [ "$C" = "1" -o "$C" = "2" ]; then # FLAGS="-ignore_unknown_options -very_quiet" # OPTIONS=$* -# Workaround for Coccinelle < 0.2.3 - FLAGS="-I $srctree/include -very_quiet" - shift $(( $# - 1 )) - OPTIONS=$1 + if [ "$KBUILD_EXTMOD" = "" ] ; then + # Workaround for Coccinelle < 0.2.3 + FLAGS="-I $srctree/include -very_quiet" + shift $(( $# - 1 )) + OPTIONS=$1 + else + echo M= is not currently supported when C=1 or C=2 + exit 1 + fi else ONLINE=0 FLAGS="-very_quiet" - OPTIONS="-dir $srctree" + if [ "$KBUILD_EXTMOD" = "" ] ; then + OPTIONS="-dir $srctree" + else + OPTIONS="-dir $KBUILD_EXTMOD -patch $srctree -I $srctree/include -I $KBUILD_EXTMOD/include" + fi fi if [ ! -x "$SPATCH" ]; then From f95ab20972cfefa8ee5428d6c3afd4cb8eacabf4 Mon Sep 17 00:00:00 2001 From: Greg Dietsche Date: Sat, 5 Nov 2011 20:59:44 -0500 Subject: [PATCH 4/7] coccinelle.txt: update documentation to include M= option Adding documentation for the new M= option which limits Coccinelle to a specific set of directories. Signed-off-by: Greg Dietsche Acked-by: Julia Lawall Signed-off-by: Michal Marek --- Documentation/coccinelle.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/coccinelle.txt b/Documentation/coccinelle.txt index 96b690348ba1..cf44eb6499b4 100644 --- a/Documentation/coccinelle.txt +++ b/Documentation/coccinelle.txt @@ -102,9 +102,15 @@ or make coccicheck COCCI= MODE=report - Using Coccinelle on (modified) files -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Controlling Which Files are Processed by Coccinelle +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +By default the entire kernel source tree is checked. +To apply Coccinelle to a specific directory, M= can be used. +For example, to check drivers/net/wireless/ one may write: + + make coccicheck M=drivers/net/wireless/ + To apply Coccinelle on a file basis, instead of a directory basis, the following command may be used: From 22e0059af301ec163d563c3590d2277c2a557d4f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 27 Dec 2011 18:28:50 +0100 Subject: [PATCH 5/7] coccinelle: semantic patches related to devm_ functions (part 1) devm_ functions allocate memory that is to remain allocated until the device is detached. This patch checks for opportunities for using the function devm_request_and_ioremap. Signed-off-by: Julia Lawall Signed-off-by: Michal Marek --- .../api/devm_request_and_ioremap.cocci | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 scripts/coccinelle/api/devm_request_and_ioremap.cocci diff --git a/scripts/coccinelle/api/devm_request_and_ioremap.cocci b/scripts/coccinelle/api/devm_request_and_ioremap.cocci new file mode 100644 index 000000000000..46beb81406ab --- /dev/null +++ b/scripts/coccinelle/api/devm_request_and_ioremap.cocci @@ -0,0 +1,105 @@ +/// Reimplement a call to devm_request_mem_region followed by a call to ioremap +/// or ioremap_nocache by a call to devm_request_and_ioremap. +/// Devm_request_and_ioremap was introduced in +/// 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0. It makes the code much more +/// concise. +/// +/// +// Confidence: High +// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2. +// URL: http://coccinelle.lip6.fr/ +// Comments: +// Options: -no_includes -include_headers + +virtual patch +virtual org +virtual report +virtual context + +@nm@ +expression myname; +identifier i; +@@ + +struct platform_driver i = { .driver = { .name = myname } }; + +@depends on patch@ +expression dev,res,size; +@@ + +-if (!devm_request_mem_region(dev, res->start, size, +- \(res->name\|dev_name(dev)\))) { +- ... +- return ...; +-} +... when != res->start +( +-devm_ioremap(dev,res->start,size) ++devm_request_and_ioremap(dev,res) +| +-devm_ioremap_nocache(dev,res->start,size) ++devm_request_and_ioremap(dev,res) +) +... when any + when != res->start + +// this rule is separate from the previous one, because a single file can +// have multiple values of myname +@depends on patch@ +expression dev,res,size; +expression nm.myname; +@@ + +-if (!devm_request_mem_region(dev, res->start, size,myname)) { +- ... +- return ...; +-} +... when != res->start +( +-devm_ioremap(dev,res->start,size) ++devm_request_and_ioremap(dev,res) +| +-devm_ioremap_nocache(dev,res->start,size) ++devm_request_and_ioremap(dev,res) +) +... when any + when != res->start + + +@pb depends on org || report || context@ +expression dev,res,size; +expression nm.myname; +position p1,p2; +@@ + +*if + (!devm_request_mem_region@p1(dev, res->start, size, + \(res->name\|dev_name(dev)\|myname\))) { + ... + return ...; +} +... when != res->start +( +*devm_ioremap@p2(dev,res->start,size) +| +*devm_ioremap_nocache@p2(dev,res->start,size) +) +... when any + when != res->start + +@script:python depends on org@ +p1 << pb.p1; +p2 << pb.p2; +@@ + +cocci.print_main("INFO: replace by devm_request_and_ioremap",p1) +cocci.print_secs("",p2) + +@script:python depends on report@ +p1 << pb.p1; +p2 << pb.p2; +@@ + +msg = "INFO: devm_request_mem_region followed by ioremap on line %s can be replaced by devm_request_and_ioremap" % (p2[0].line) +coccilib.report.print_report(p1[0],msg) From fb3f8af4ff52faf9b31e6c4e8ca0b0b16332808c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 27 Dec 2011 18:28:51 +0100 Subject: [PATCH 6/7] coccinelle: semantic patches related to devm_ functions (part 2) devm_ functions allocate memory that is to remain allocated until the device is detached. This patch checks for freeing of such memory using standard memory freeing functions. Signed-off-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/free/devm_free.cocci | 71 +++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 scripts/coccinelle/free/devm_free.cocci diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci new file mode 100644 index 000000000000..0a1e36146d76 --- /dev/null +++ b/scripts/coccinelle/free/devm_free.cocci @@ -0,0 +1,71 @@ +/// Find uses of standard freeing functons on values allocated using devm_ +/// functions. Values allocated using the devm_functions are freed when +/// the device is detached, and thus the use of the standard freeing +/// function would cause a double free. +/// See Documentation/driver-model/devres.txt for more information. +/// +/// A difficulty of detecting this problem is that the standard freeing +/// function might be called from a different function than the one +/// containing the allocation function. It is thus necessary to make the +/// connection between the allocation function and the freeing function. +/// Here this is done using the specific argument text, which is prone to +/// false positives. There is no rule for the request_region and +/// request_mem_region variants because this heuristic seems to be a bit +/// less reliable in these cases. +/// +// Confidence: Moderate +// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2. +// URL: http://coccinelle.lip6.fr/ +// Comments: +// Options: -no_includes -include_headers + +virtual org +virtual report +virtual context + +@r depends on context || org || report@ +expression x; +@@ + +( + x = devm_kzalloc(...) +| + x = devm_request_irq(...) +| + x = devm_ioremap(...) +| + x = devm_ioremap_nocache(...) +| + x = devm_ioport_map(...) +) + +@pb@ +expression r.x; +position p; +@@ + +( +* kfree@p(x) +| +* free_irq@p(x) +| +* iounmap@p(x) +| +* ioport_unmap@p(x) +) + +@script:python depends on org@ +p << pb.p; +@@ + +msg="WARNING: invalid free of devm_ allocated data" +coccilib.org.print_todo(p[0], msg) + +@script:python depends on report@ +p << pb.p; +@@ + +msg="WARNING: invalid free of devm_ allocated data" +coccilib.report.print_report(p[0], msg) + From 29a36d4dec6cf7ad72e6e3337bf954096cbbb4cf Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 14 Jan 2012 23:41:54 +0100 Subject: [PATCH 7/7] scripts/coccinelle: improve the coverage of some semantic patches This patch ensures that all semantic patches in the scripts/coccinelle directory provide the report option. Report messages that include line numbers now have the line number preceded by "line" for easier subsequent processing. Signed-off-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/api/kstrdup.cocci | 75 +++++++++++++++++++++-- scripts/coccinelle/api/memdup.cocci | 34 ++++++++-- scripts/coccinelle/api/memdup_user.cocci | 39 +++++++++--- scripts/coccinelle/free/kfree.cocci | 14 +++-- scripts/coccinelle/iterators/fen.cocci | 73 +++++++++++++++++++--- scripts/coccinelle/iterators/itnull.cocci | 54 +++++++++++++--- scripts/coccinelle/locks/call_kern.cocci | 67 ++++++++++++++------ scripts/coccinelle/locks/flags.cocci | 12 ++-- scripts/coccinelle/locks/mini_lock.cocci | 15 ++--- scripts/coccinelle/misc/doubleinit.cocci | 8 +-- scripts/coccinelle/null/eno.cocci | 36 +++++++++-- 11 files changed, 351 insertions(+), 76 deletions(-) diff --git a/scripts/coccinelle/api/kstrdup.cocci b/scripts/coccinelle/api/kstrdup.cocci index e0805ad08d39..07a74b2c6196 100644 --- a/scripts/coccinelle/api/kstrdup.cocci +++ b/scripts/coccinelle/api/kstrdup.cocci @@ -1,16 +1,19 @@ /// Use kstrdup rather than duplicating its implementation /// // Confidence: High -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers virtual patch +virtual context +virtual org +virtual report -@@ +@depends on patch@ expression from,to; expression flag,E1,E2; statement S; @@ -23,7 +26,7 @@ statement S; ... when != \(from = E2 \| to = E2 \) - strcpy(to, from); -@@ +@depends on patch@ expression x,from,to; expression flag,E1,E2,E3; statement S; @@ -37,3 +40,65 @@ statement S; if (to==NULL || ...) S ... when != \(x = E3 \| from = E3 \| to = E3 \) - memcpy(to, from, x); + +// --------------------------------------------------------------------- + +@r1 depends on !patch exists@ +expression from,to; +expression flag,E1,E2; +statement S; +position p1,p2; +@@ + +* to = kmalloc@p1(strlen(from) + 1,flag); + ... when != \(from = E1 \| to = E1 \) + if (to==NULL || ...) S + ... when != \(from = E2 \| to = E2 \) +* strcpy@p2(to, from); + +@r2 depends on !patch exists@ +expression x,from,to; +expression flag,E1,E2,E3; +statement S; +position p1,p2; +@@ + +* x = strlen(from) + 1; + ... when != \( x = E1 \| from = E1 \) +* to = \(kmalloc@p1\|kzalloc@p2\)(x,flag); + ... when != \(x = E2 \| from = E2 \| to = E2 \) + if (to==NULL || ...) S + ... when != \(x = E3 \| from = E3 \| to = E3 \) +* memcpy@p2(to, from, x); + +@script:python depends on org@ +p1 << r1.p1; +p2 << r1.p2; +@@ + +cocci.print_main("WARNING opportunity for kstrdep",p1) +cocci.print_secs("strcpy",p2) + +@script:python depends on org@ +p1 << r2.p1; +p2 << r2.p2; +@@ + +cocci.print_main("WARNING opportunity for kstrdep",p1) +cocci.print_secs("memcpy",p2) + +@script:python depends on report@ +p1 << r1.p1; +p2 << r1.p2; +@@ + +msg = "WARNING opportunity for kstrdep (strcpy on line %s)" % (p2[0].line) +coccilib.report.print_report(p1[0], msg) + +@script:python depends on report@ +p1 << r2.p1; +p2 << r2.p2; +@@ + +msg = "WARNING opportunity for kstrdep (memcpy on line %s)" % (p2[0].line) +coccilib.report.print_report(p1[0], msg) diff --git a/scripts/coccinelle/api/memdup.cocci b/scripts/coccinelle/api/memdup.cocci index b5d722077dc1..4dceab6d54de 100644 --- a/scripts/coccinelle/api/memdup.cocci +++ b/scripts/coccinelle/api/memdup.cocci @@ -1,14 +1,17 @@ /// Use kmemdup rather than duplicating its implementation /// // Confidence: High -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers virtual patch +virtual context +virtual org +virtual report @r1@ expression from,to; @@ -28,7 +31,7 @@ position p; ... when != \( x = E1 \| from = E1 \) to = \(kmalloc@p\|kzalloc@p\)(x,flag); -@@ +@depends on patch@ expression from,to,size,flag; position p != {r1.p,r2.p}; statement S; @@ -38,3 +41,26 @@ statement S; + to = kmemdup(from,size,flag); if (to==NULL || ...) S - memcpy(to, from, size); + +@r depends on !patch@ +expression from,to,size,flag; +position p != {r1.p,r2.p}; +statement S; +@@ + +* to = \(kmalloc@p\|kzalloc@p\)(size,flag); + to = kmemdup(from,size,flag); + if (to==NULL || ...) S +* memcpy(to, from, size); + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING opportunity for kmemdep") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING opportunity for kmemdep") diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci index 72ce012e878a..2efac289fd59 100644 --- a/scripts/coccinelle/api/memdup_user.cocci +++ b/scripts/coccinelle/api/memdup_user.cocci @@ -1,23 +1,25 @@ -/// Use kmemdup_user rather than duplicating its implementation +/// Use memdup_user rather than duplicating its implementation /// This is a little bit restricted to reduce false positives /// // Confidence: High -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers virtual patch +virtual context +virtual org +virtual report -@@ +@depends on patch@ expression from,to,size,flag; -position p; identifier l1,l2; @@ -- to = \(kmalloc@p\|kzalloc@p\)(size,flag); +- to = \(kmalloc\|kzalloc\)(size,flag); + to = memdup_user(from,size); if ( - to==NULL @@ -33,3 +35,26 @@ identifier l1,l2; - -EFAULT - ...+> - } + +@r depends on !patch@ +expression from,to,size,flag; +position p; +statement S1,S2; +@@ + +* to = \(kmalloc@p\|kzalloc@p\)(size,flag); + if (to==NULL || ...) S1 + if (copy_from_user(to, from, size) != 0) + S2 + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING opportunity for memdep_user") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING opportunity for memdep_user") diff --git a/scripts/coccinelle/free/kfree.cocci b/scripts/coccinelle/free/kfree.cocci index f9f79d9245ee..d9ae6d89c2f5 100644 --- a/scripts/coccinelle/free/kfree.cocci +++ b/scripts/coccinelle/free/kfree.cocci @@ -5,9 +5,9 @@ //# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument /// // Confidence: Moderate -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers @@ -23,7 +23,7 @@ position p1; kfree@p1(E) @print expression@ -constant char *c; +constant char [] c; expression free.E,E2; type T; position p; @@ -36,6 +36,10 @@ identifier f; E@p == E2 | E@p != E2 +| + E2 == E@p +| + E2 != E@p | !E@p | @@ -113,5 +117,5 @@ p1 << free.p1; p2 << r.p2; @@ -msg = "reference preceded by free on line %s" % (p1[0].line) +msg = "ERROR: reference preceded by free on line %s" % (p1[0].line) coccilib.report.print_report(p2[0],msg) diff --git a/scripts/coccinelle/iterators/fen.cocci b/scripts/coccinelle/iterators/fen.cocci index 77bc108c3f59..0a40af828c43 100644 --- a/scripts/coccinelle/iterators/fen.cocci +++ b/scripts/coccinelle/iterators/fen.cocci @@ -2,16 +2,19 @@ /// is no point to call of_node_put on the final value. /// // Confidence: High -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers virtual patch +virtual context +virtual org +virtual report -@@ +@depends on patch@ iterator name for_each_node_by_name; expression np,E; identifier l; @@ -24,7 +27,7 @@ for_each_node_by_name(np,...) { ... when != np = E - of_node_put(np); -@@ +@depends on patch@ iterator name for_each_node_by_type; expression np,E; identifier l; @@ -37,7 +40,7 @@ for_each_node_by_type(np,...) { ... when != np = E - of_node_put(np); -@@ +@depends on patch@ iterator name for_each_compatible_node; expression np,E; identifier l; @@ -50,7 +53,7 @@ for_each_compatible_node(np,...) { ... when != np = E - of_node_put(np); -@@ +@depends on patch@ iterator name for_each_matching_node; expression np,E; identifier l; @@ -62,3 +65,59 @@ for_each_matching_node(np,...) { } ... when != np = E - of_node_put(np); + +// ---------------------------------------------------------------------- + +@r depends on !patch forall@ +//iterator name for_each_node_by_name; +//iterator name for_each_node_by_type; +//iterator name for_each_compatible_node; +//iterator name for_each_matching_node; +expression np,E; +identifier l; +position p1,p2; +@@ + +( +*for_each_node_by_name@p1(np,...) +{ + ... when != break; + when != goto l; +} +| +*for_each_node_by_type@p1(np,...) +{ + ... when != break; + when != goto l; +} +| +*for_each_compatible_node@p1(np,...) +{ + ... when != break; + when != goto l; +} +| +*for_each_matching_node@p1(np,...) +{ + ... when != break; + when != goto l; +} +) +... when != np = E +* of_node_put@p2(np); + +@script:python depends on org@ +p1 << r.p1; +p2 << r.p2; +@@ + +cocci.print_main("unneeded of_node_put",p2) +cocci.print_secs("iterator",p1) + +@script:python depends on report@ +p1 << r.p1; +p2 << r.p2; +@@ + +msg = "ERROR: of_node_put not needed after iterator on line %s" % (p1[0].line) +coccilib.report.print_report(p2[0], msg) diff --git a/scripts/coccinelle/iterators/itnull.cocci b/scripts/coccinelle/iterators/itnull.cocci index baa4297a4ed1..259899f6838e 100644 --- a/scripts/coccinelle/iterators/itnull.cocci +++ b/scripts/coccinelle/iterators/itnull.cocci @@ -1,20 +1,24 @@ /// Many iterators have the property that the first argument is always bound -/// to a real list element, never NULL. False positives arise for some -/// iterators that do not have this property, or in cases when the loop -/// cursor is reassigned. The latter should only happen when the matched -/// code is on the way to a loop exit (break, goto, or return). +/// to a real list element, never NULL. +//# False positives arise for some iterators that do not have this property, +//# or in cases when the loop cursor is reassigned. The latter should only +//# happen when the matched code is on the way to a loop exit (break, goto, +//# or return). /// // Confidence: Moderate -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers virtual patch +virtual context +virtual org +virtual report -@@ +@depends on patch@ iterator I; expression x,E,E1,E2; statement S,S1,S2; @@ -55,4 +59,36 @@ I(x,...) { <... x != NULL + ) ) - ...> } \ No newline at end of file + ...> } + +@r depends on !patch exists@ +iterator I; +expression x,E; +position p1,p2; +@@ + +*I@p1(x,...) +{ ... when != x = E +( +* x@p2 == NULL +| +* x@p2 != NULL +) + ... when any +} + +@script:python depends on org@ +p1 << r.p1; +p2 << r.p2; +@@ + +cocci.print_main("iterator-bound variable",p1) +cocci.print_secs("useless NULL test",p2) + +@script:python depends on report@ +p1 << r.p1; +p2 << r.p2; +@@ + +msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line) +coccilib.report.print_report(p2[0], msg) diff --git a/scripts/coccinelle/locks/call_kern.cocci b/scripts/coccinelle/locks/call_kern.cocci index 00af5344a68f..8f10b49603c3 100644 --- a/scripts/coccinelle/locks/call_kern.cocci +++ b/scripts/coccinelle/locks/call_kern.cocci @@ -1,17 +1,20 @@ /// Find functions that refer to GFP_KERNEL but are called with locks held. -/// The proposed change of converting the GFP_KERNEL is not necessarily the -/// correct one. It may be desired to unlock the lock, or to not call the -/// function under the lock in the first place. +//# The proposed change of converting the GFP_KERNEL is not necessarily the +//# correct one. It may be desired to unlock the lock, or to not call the +//# function under the lock in the first place. /// // Confidence: Moderate -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers virtual patch +virtual context +virtual org +virtual report @gfp exists@ identifier fn; @@ -32,28 +35,29 @@ fn(...) { ... when any } -@locked@ +@locked exists@ identifier gfp.fn; +position p1,p2; @@ ( -read_lock_irq +read_lock_irq@p1 | -write_lock_irq +write_lock_irq@p1 | -read_lock_irqsave +read_lock_irqsave@p1 | -write_lock_irqsave +write_lock_irqsave@p1 | -spin_lock +spin_lock@p1 | -spin_trylock +spin_trylock@p1 | -spin_lock_irq +spin_lock_irq@p1 | -spin_lock_irqsave +spin_lock_irqsave@p1 | -local_irq_disable +local_irq_disable@p1 ) (...) ... when != read_unlock_irq(...) @@ -64,11 +68,38 @@ local_irq_disable when != spin_unlock_irq(...) when != spin_unlock_irqrestore(...) when != local_irq_enable(...) -fn(...) +fn@p2(...) -@depends on locked@ +@depends on locked && patch@ position gfp.p; @@ - GFP_KERNEL@p + GFP_ATOMIC + +@depends on locked && !patch@ +position gfp.p; +@@ + +* GFP_KERNEL@p + +@script:python depends on !patch && org@ +p << gfp.p; +fn << gfp.fn; +p1 << locked.p1; +p2 << locked.p2; +@@ + +cocci.print_main("lock",p1) +cocci.print_secs("call",p2) +cocci.print_secs("GFP_KERNEL",p) + +@script:python depends on !patch && report@ +p << gfp.p; +fn << gfp.fn; +p1 << locked.p1; +p2 << locked.p2; +@@ + +msg = "ERROR: function %s called on line %s inside lock on line %s but uses GFP_KERNEL" % (fn,p2[0].line,p1[0].line) +coccilib.report.print_report(p[0], msg) diff --git a/scripts/coccinelle/locks/flags.cocci b/scripts/coccinelle/locks/flags.cocci index b4344d838097..1c4ffe6fd846 100644 --- a/scripts/coccinelle/locks/flags.cocci +++ b/scripts/coccinelle/locks/flags.cocci @@ -1,9 +1,9 @@ /// Find nested lock+irqsave functions that use the same flags variables /// // Confidence: High -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers @@ -12,7 +12,7 @@ virtual context virtual org virtual report -@r@ +@r exists@ expression lock1,lock2,flags; position p1,p2; @@ @@ -39,7 +39,7 @@ read_lock_irqsave@p2(lock2,flags) write_lock_irqsave@p2(lock2,flags) ) -@d@ +@d exists@ expression f <= r.flags; expression lock1,lock2,flags; position r.p1, r.p2; @@ -76,5 +76,5 @@ p1 << r.p1; p2 << r.p2; @@ -msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line) +msg="ERROR: nested lock+irqsave that reuses flags from line %s." % (p1[0].line) coccilib.report.print_report(p2[0], msg) diff --git a/scripts/coccinelle/locks/mini_lock.cocci b/scripts/coccinelle/locks/mini_lock.cocci index 7641a2925434..3267d7410bd5 100644 --- a/scripts/coccinelle/locks/mini_lock.cocci +++ b/scripts/coccinelle/locks/mini_lock.cocci @@ -6,13 +6,14 @@ /// function call that releases the lock. /// // Confidence: Moderate -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers +virtual context virtual org virtual report @@ -57,7 +58,7 @@ position r; for(...;...;...) { <+... return@r ...; ...+> } -@err@ +@err exists@ expression E1; position prelocked.p; position up != prelocked.p1; @@ -65,14 +66,14 @@ position r!=looped.r; identifier lock,unlock; @@ -lock(E1@p,...); +*lock(E1@p,...); <+... when != E1 if (...) { ... when != E1 - return@r ...; +* return@r ...; } ...+> -unlock@up(E1,...); +*unlock@up(E1,...); @script:python depends on org@ p << prelocked.p1; diff --git a/scripts/coccinelle/misc/doubleinit.cocci b/scripts/coccinelle/misc/doubleinit.cocci index 156b20adb351..cf74a00cf597 100644 --- a/scripts/coccinelle/misc/doubleinit.cocci +++ b/scripts/coccinelle/misc/doubleinit.cocci @@ -3,9 +3,9 @@ /// initialization. /// // Confidence: Low -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise // Options: -no_includes -include_headers @@ -49,5 +49,5 @@ pr << r.p; @@ if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)): - msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line) + msg = "%s: first occurrence line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line) coccilib.report.print_report(p0[0],msg) diff --git a/scripts/coccinelle/null/eno.cocci b/scripts/coccinelle/null/eno.cocci index 4c9c52b9c413..ed961a1f7d11 100644 --- a/scripts/coccinelle/null/eno.cocci +++ b/scripts/coccinelle/null/eno.cocci @@ -1,16 +1,19 @@ /// The various basic memory allocation functions don't return ERR_PTR /// // Confidence: High -// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. -// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. -// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. +// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2. +// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: // Options: -no_includes -include_headers virtual patch +virtual context +virtual org +virtual report -@@ +@depends on patch@ expression x,E; @@ @@ -18,3 +21,28 @@ x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache ... when != x = E - IS_ERR(x) + !x + +@r depends on !patch exists@ +expression x,E; +position p1,p2; +@@ + +*x = \(kmalloc@p1\|kzalloc@p1\|kcalloc@p1\|kmem_cache_alloc@p1\|kmem_cache_zalloc@p1\|kmem_cache_alloc_node@p1\|kmalloc_node@p1\|kzalloc_node@p1\)(...) +... when != x = E +* IS_ERR@p2(x) + +@script:python depends on org@ +p1 << r.p1; +p2 << r.p2; +@@ + +cocci.print_main("alloc call",p1) +cocci.print_secs("IS_ERR that should be NULL tests",p2) + +@script:python depends on report@ +p1 << r.p1; +p2 << r.p2; +@@ + +msg = "ERROR: allocation function on line %s returns NULL not ERR_PTR on failure" % (p1[0].line) +coccilib.report.print_report(p2[0], msg)