Browse Source

script: Handle \ escapes in unit names properly

Unit names can contain valid \ escapes in systemd. See systemd-escape(1)
for examples. Text::ParseWords::shellwords breaks that since it strips \
in addition to quotes. Instead, just use split as the only fields parsed
will contain unit names, which can't have whitespace. Any
leading/trailing quotes are then stripped separately.

Closes: #820359
tags/1.34
Dan Nicholson Felipe Sateler 5 years ago
parent
commit
c167d9498a
5 changed files with 28 additions and 9 deletions
  1. +8
    -0
      debian/changelog
  2. +10
    -4
      script/deb-systemd-helper
  3. +0
    -1
      script/dh_systemd_enable
  4. +9
    -2
      script/dh_systemd_start
  5. +1
    -2
      script/update-rc.d

+ 8
- 0
debian/changelog View File

@@ -1,11 +1,19 @@
init-system-helpers (1.34) UNRELEASED; urgency=medium

[ Martin Pitt ]
* Make "init" not essential any more and lower priority from "required" to
"important", so that we can drop it from minimal chroots and docker
containers at some point. Explicitly mark init-system-helpers as essential
now (before it was only transitively essential due to init depending on
it). (Closes: #756023)

[ Dan Nicholson ]
* deb-systemd-helper, dh_systemd_start: Use split rather than
Text::ParseWords::shellwords since the latter will strip valid \
escapes from unit names. The values then need to have leading and
trailing quotes stripped. (Closes: #820359)
* dh_systemd_enable: Drop unused Text::ParseWords use.

-- Martin Pitt <mpitt@debian.org> Thu, 19 May 2016 18:05:15 +0200

init-system-helpers (1.33) unstable; urgency=medium


+ 10
- 4
script/deb-systemd-helper View File

@@ -85,7 +85,6 @@ use warnings;
use File::Path qw(make_path); # in core since Perl 5.001
use File::Basename; # in core since Perl 5
use File::Temp qw(tempfile); # in core since Perl 5.6.1
use Text::ParseWords qw(shellwords); # in core since Perl 5
use Getopt::Long; # in core since Perl 5
# Make Data::Dumper::Dumper available if present (not present on systems that
# only have perl-base, not perl).
@@ -184,13 +183,18 @@ sub get_link_closure {

my $unit_name = basename($service_path);

# The keys parsed from the unit file below can only have unit names
# as values. Since unit names can't have whitespace in systemd,
# simply use split and strip any leading/trailing quotes. See
# systemd-escape(1) for examples of valid unit names.
open my $fh, '<', $service_path or error("unable to read $service_path");
while (my $line = <$fh>) {
chomp($line);
my $service_link;

if ($line =~ /^\s*(WantedBy|RequiredBy)=(.+)$/i) {
for my $value (shellwords($2)) {
for my $value (split(/\s+/, $2)) {
$value =~ s/^(["'])(.*)\g1$/$2/;
my $wants_dir = "/etc/systemd/system/$value";
$wants_dir .= '.wants' if $1 eq 'WantedBy';
$wants_dir .= '.requires' if $1 eq 'RequiredBy';
@@ -199,7 +203,8 @@ sub get_link_closure {
}

if ($line =~ /^\s*Also=(.+)$/i) {
for my $value (shellwords($1)) {
for my $value (split(/\s+/, $1)) {
$value =~ s/^(["'])(.*)\g1$/$2/;
if ($value ne $unit_name) {
push @links, get_link_closure($value, find_unit($value));
}
@@ -207,7 +212,8 @@ sub get_link_closure {
}

if ($line =~ /^\s*Alias=(.+)$/i) {
for my $value (shellwords($1)) {
for my $value (split(/\s+/, $1)) {
$value =~ s/^(["'])(.*)\g1$/$2/;
if ($value ne $unit_name) {
push @links, { dest => $service_path, src => "/etc/systemd/system/$1" };
}


+ 0
- 1
script/dh_systemd_enable View File

@@ -9,7 +9,6 @@ dh_systemd_enable - enable/disable systemd unit files
use strict;
use Debian::Debhelper::Dh_Lib;
use File::Find;
use Text::ParseWords qw(shellwords); # in core since Perl 5

=head1 SYNOPSIS



+ 9
- 2
script/dh_systemd_start View File

@@ -9,7 +9,6 @@ dh_systemd_start - start/stop/restart systemd unit files
use strict;
use Debian::Debhelper::Dh_Lib;
use File::Find;
use Text::ParseWords qw(shellwords); # in core since Perl 5
use Cwd qw(getcwd abs_path);

=head1 SYNOPSIS
@@ -107,8 +106,16 @@ sub extract_key {
while (my $line = <$fh>) {
chomp($line);

# The keys parsed from the unit file below can only have
# unit names as values. Since unit names can't have
# whitespace in systemd, simply use split and strip any
# leading/trailing quotes. See systemd-escape(1) for
# examples of valid unit names.
if ($line =~ /^\s*$key=(.+)$/i) {
@values = (@values, shellwords($1));
for my $value (split(/\s+/, $1)) {
$value =~ s/^(["'])(.*)\g1$/$2/;
push @values, $value;
}
}
}
close($fh);


+ 1
- 2
script/update-rc.d View File

@@ -446,6 +446,5 @@ sub is_initscripts_installed {
# Check if mountkernfs is available. We cannot make inferences
# using the running init system because we may be running in a
# chroot
my @links = glob '/etc/rcS.d/S??mountkernfs.sh';
return @links != 0;
return -f '/etc/init.d/mountkernfs.sh';
}

Loading…
Cancel
Save