[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[SCM] Debian package checker branch, master, updated. 2.1.3-17-g3dc5876



The following commit has been merged in the master branch:
commit 3dc58767f21fec9df9f0f40cf1ea66175483e257
Author: Russ Allbery <rra@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


Reply to: