The following commit has been merged in the master branch: commit 3dc58767f21fec9df9f0f40cf1ea66175483e257 Author: Russ Allbery <r...@debian.org> Date: Mon Dec 29 16:25:38 2008 -0800
Check for scripts in /etc calling init scripts directly * checks/scripts{,.desc}: + [RA] Check for scripts in /etc that call init scripts directly without using invoke-rc.d. Based on a patch by Raphael Geissert. (Closes: #381485) diff --git a/checks/scripts b/checks/scripts index 2085b06..919f92d 100644 --- a/checks/scripts +++ b/checks/scripts @@ -185,6 +185,11 @@ our @depends_needed = ( [ 'xml-core' => '\bupdate-xmlcatalog\s' ], ); +# When detecting commands inside shell scripts, use this regex to match the +# beginning of the command rather than checking whether the command is at the +# beginning of a line. +our $LEADIN = qr'(?:(?:^|[`&;(|{])\s*|(?:if|then|do|while)\s+)'; + sub run { my %executable = (); @@ -327,6 +332,41 @@ for my $filename (sort keys %{$info->scripts}) { tag("unusual-interpreter", $filename, "#!$interpreter"); } + # Do some additional checks on shell scripts in /etc. This should + # probably be extended eventually to any script in a public directory. + # This also needs smarter processing of multiline quoted strings, + # heredocs, and so forth. Hopefully it will do for right now. + if ($filename =~ m,^./etc/, and $base =~ /^$known_shells_regex$/) { + my ($saw_init, $saw_invoke); + local $.; + open(FH, '<', 'unpacked/' . $filename); + while (<FH>) { + next if m,^\s*$,; # skip empty lines + next if m,^\s*\#,; # skip comment lines + s/\#.*$//; # eat comments + chomp; + + # Check for running init scripts directly instead of via + # invoke-rc.d. Scripts are allowed to reinvoke themselves with a + # different argument; some init scripts implement actions that + # way. Scripts are also allowed to do this for actions other than + # those defined for invoke-rc.d. + if (m,$LEADIN/etc/init.d/(\S+)\s+[\"\']?(\S+)[\"\']?,) { + my ($script, $action) = ($1, $2); + next if "./etc/init.d/$script" eq $filename; + next unless $action =~ /^(force-)?(start|stop|restart|reload|status)$/; + $saw_init = $.; + } + if (m%^\s*invoke-rc\.d\s+%) { + $saw_invoke = 1; + } + } + close(FH); + if ($saw_init and not $saw_invoke) { + tag 'script-calls-init-script-directly', "$filename:$saw_init"; + } + } + # If we found the interpreter and the script is executable, check # dependencies. This should be the last thing we do in the loop so that # we can use next for an early exit and reduce the nesting. @@ -491,7 +531,6 @@ while (<SCRIPTS>) { my %warned; my ($saw_init, $saw_invoke, $saw_debconf, $saw_sete, $has_code); my $cat_string = ""; - my $LEADIN = qr'(?:(?:^|[`&;(|{])\s*|(?:if|then|do|while)\s+)'; my $previous_line = ""; while (<C>) { @@ -547,7 +586,7 @@ while (<SCRIPTS>) { } # Collect information about init script invocations to catch running - # init scripts directory rather than through invoke-rc.d. Since the + # init scripts directly rather than through invoke-rc.d. Since the # script is allowed to run the init script directly if invoke-rc.d # doesn't exist, only tag direct invocations where invoke-rc.d is # never used in the same script. Lots of false negatives, but diff --git a/checks/scripts.desc b/checks/scripts.desc index 5889046..c215f5d 100644 --- a/checks/scripts.desc +++ b/checks/scripts.desc @@ -425,6 +425,15 @@ Info: This script apparently runs an init script directly rather than available. Ref: policy 9.3.3.2 +Tag: script-calls-init-script-directly +Severity: normal +Certainty: possible +Info: This script apparently runs an init script directly rather than + using <tt>invoke-rc.d</tt>. While use of <tt>invoke-rc.d</tt> is only + required for maintainer scripts, supporting the policy layer that it + implements is a good idea in any script. +Ref: policy 9.3.3.2 + Tag: gconftool-used-in-maintainer-script Severity: normal Certainty: possible diff --git a/debian/changelog b/debian/changelog index d485642..2a11e8a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,7 @@ lintian (2.1.4) UNRELEASED; urgency=low - desktop-mimetype-without-update-call - forbidden-postrm-interpreter - preinst-interpreter-without-predepends + - script-calls-init-script-directly - unknown-control-interpreter (split from unusual-interpreter) + Removed - desktop-file-but-no-dh_desktop-call @@ -31,6 +32,9 @@ lintian (2.1.4) UNRELEASED; urgency=low interpreter-in-usr-local since the severity is higher. - unusual-control-interpreter is certain, not possible. - Suppress some cases of multiple tags about the same basic problem. + + [RA] Check for scripts in /etc that call init scripts directly + without using invoke-rc.d. Based on a patch by Raphael Geissert. + (Closes: #381485) * debian/rules: + [RA] New check-tag target which runs all test cases in the new test diff --git a/t/tests/6000_scripts-calls-init-script.desc b/t/tests/6000_scripts-calls-init-script.desc new file mode 100644 index 0000000..d092bee --- /dev/null +++ b/t/tests/6000_scripts-calls-init-script.desc @@ -0,0 +1,7 @@ +Testname: scripts-calls-init-script +Version: 1.0 +Description: Test proper use of invoke-rc.d +Test-For: + maintainer-script-calls-init-script-directly + script-calls-init-script-directly +References: Debian Bug#381485 diff --git a/t/tests/scripts-calls-init-script/debian/bad b/t/tests/scripts-calls-init-script/debian/bad new file mode 100755 index 0000000..86c80a7 --- /dev/null +++ b/t/tests/scripts-calls-init-script/debian/bad @@ -0,0 +1,2 @@ +#!/bin/sh +/etc/init.d/ntp restart diff --git a/t/tests/scripts-calls-init-script/debian/debian/install b/t/tests/scripts-calls-init-script/debian/debian/install new file mode 100644 index 0000000..31e3a9e --- /dev/null +++ b/t/tests/scripts-calls-init-script/debian/debian/install @@ -0,0 +1,4 @@ +bad /etc/cron.daily +other-action /etc/cron.daily +test-first /etc/cron.daily +self-invoke /etc/init.d diff --git a/t/tests/scripts-calls-init-script/debian/debian/postinst b/t/tests/scripts-calls-init-script/debian/debian/postinst new file mode 100644 index 0000000..3feaa42 --- /dev/null +++ b/t/tests/scripts-calls-init-script/debian/debian/postinst @@ -0,0 +1,7 @@ +#!/bin/sh +set -e + +update-rc.d self-invoke defaults >/dev/null +/etc/init.d/self-invoke start + +#DEBHELPER# diff --git a/t/tests/scripts-calls-init-script/debian/debian/postrm b/t/tests/scripts-calls-init-script/debian/debian/postrm new file mode 100644 index 0000000..acba064 --- /dev/null +++ b/t/tests/scripts-calls-init-script/debian/debian/postrm @@ -0,0 +1,8 @@ +#!/bin/sh +set -e + +if [ "remove" = "$1" ] ; then + update-rc.d self-invoke remove >/dev/null +fi + +#DEBHELPER# diff --git a/t/tests/scripts-calls-init-script/debian/other-action b/t/tests/scripts-calls-init-script/debian/other-action new file mode 100755 index 0000000..cd58f75 --- /dev/null +++ b/t/tests/scripts-calls-init-script/debian/other-action @@ -0,0 +1,3 @@ +#!/bin/sh +# Only supported invoke-rc.d actions are required to go through invoke-rc.d. +/etc/init.d/foo frobnicate-the-bazerator diff --git a/t/tests/scripts-calls-init-script/debian/self-invoke b/t/tests/scripts-calls-init-script/debian/self-invoke new file mode 100755 index 0000000..dfceee5 --- /dev/null +++ b/t/tests/scripts-calls-init-script/debian/self-invoke @@ -0,0 +1,24 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: self-invoke +# Required-Start: +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Test init script +# Description: Test init script. +### END INIT INFO +case "$1" in + start) + : + ;; + stop) + : + ;; + restart) + /etc/init.d/self-invoke start + ;; + force-reload) + : + ;; +esac diff --git a/t/tests/scripts-calls-init-script/debian/test-first b/t/tests/scripts-calls-init-script/debian/test-first new file mode 100755 index 0000000..5019218 --- /dev/null +++ b/t/tests/scripts-calls-init-script/debian/test-first @@ -0,0 +1,6 @@ +#!/bin/sh +if which invoke-rc.d >/dev/null 2>&1 ; then + invoke-rc.d ntp restart +else + /etc/init.d/ntp restart +fi diff --git a/t/tests/scripts-calls-init-script/tags b/t/tests/scripts-calls-init-script/tags new file mode 100644 index 0000000..0fb370b --- /dev/null +++ b/t/tests/scripts-calls-init-script/tags @@ -0,0 +1,2 @@ +E: scripts-calls-init-script: maintainer-script-calls-init-script-directly postinst:5 +W: scripts-calls-init-script: script-calls-init-script-directly ./etc/cron.daily/bad:2 -- Debian package checker -- To UNSUBSCRIBE, email to debian-lint-maint-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org