summaryrefslogtreecommitdiffstats
path: root/lib/Lintian/Check/Binaries
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lintian/Check/Binaries')
-rw-r--r--lib/Lintian/Check/Binaries/Architecture.pm60
-rw-r--r--lib/Lintian/Check/Binaries/Architecture/Other.pm141
-rw-r--r--lib/Lintian/Check/Binaries/Corrupted.pm93
-rw-r--r--lib/Lintian/Check/Binaries/DebugSymbols.pm72
-rw-r--r--lib/Lintian/Check/Binaries/DebugSymbols/Detached.pm86
-rw-r--r--lib/Lintian/Check/Binaries/Hardening.pm183
-rw-r--r--lib/Lintian/Check/Binaries/LargeFileSupport.pm108
-rw-r--r--lib/Lintian/Check/Binaries/Location.pm138
-rw-r--r--lib/Lintian/Check/Binaries/Obsolete/Crypt.pm90
-rw-r--r--lib/Lintian/Check/Binaries/Prerequisites.pm214
-rw-r--r--lib/Lintian/Check/Binaries/Prerequisites/Numpy.pm107
-rw-r--r--lib/Lintian/Check/Binaries/Prerequisites/Perl.pm81
-rw-r--r--lib/Lintian/Check/Binaries/Prerequisites/Php.pm80
-rw-r--r--lib/Lintian/Check/Binaries/Profiling.pm73
-rw-r--r--lib/Lintian/Check/Binaries/Rpath.pm145
-rw-r--r--lib/Lintian/Check/Binaries/Spelling.pm86
-rw-r--r--lib/Lintian/Check/Binaries/Static.pm100
17 files changed, 1857 insertions, 0 deletions
diff --git a/lib/Lintian/Check/Binaries/Architecture.pm b/lib/Lintian/Check/Binaries/Architecture.pm
new file mode 100644
index 0000000..009b1f5
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Architecture.pm
@@ -0,0 +1,60 @@
+# binaries/architecture -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Architecture;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ m{^ [^,]* \b ELF \b }x
+ || $item->file_type =~ m{ \b current [ ] ar [ ] archive \b }x;
+
+ my $architecture = $self->processable->fields->value('Architecture');
+
+ $self->pointed_hint('arch-independent-package-contains-binary-or-object',
+ $item->pointer)
+ if $architecture eq 'all';
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Architecture/Other.pm b/lib/Lintian/Check/Binaries/Architecture/Other.pm
new file mode 100644
index 0000000..b40811f
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Architecture/Other.pm
@@ -0,0 +1,141 @@
+# binaries/architecture/other -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Architecture::Other;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+# Guile object files do not objdump/strip correctly, so exclude them
+# from a number of tests. (#918444)
+const my $GUILE_PATH_REGEX => qr{^usr/lib(?:/[^/]+)+/guile/[^/]+/.+\.go$};
+
+has ARCH_REGEX => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my %arch_regex;
+
+ my $data = $self->data->load('binaries/arch-regex', qr/\s*\~\~/);
+ for my $architecture ($data->all) {
+
+ my $pattern = $data->value($architecture);
+ $arch_regex{$architecture} = qr{$pattern};
+ }
+
+ return \%arch_regex;
+ }
+);
+
+has ARCH_64BIT_EQUIVS => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ return $self->data->load('binaries/arch-64bit-equivs',qr/\s*\=\>\s*/);
+ }
+);
+
+sub from_other_architecture {
+ my ($self, $item) = @_;
+
+ my $architecture = $self->processable->fields->value('Architecture');
+
+ return 0
+ if $architecture eq 'all';
+
+ # If it matches the architecture regex, it is good
+ return 0
+ if exists $self->ARCH_REGEX->{$architecture}
+ && $item->file_type =~ $self->ARCH_REGEX->{$architecture};
+
+ # Special case - "old" multi-arch dirs
+ if ( $item->name =~ m{(?:^|/)lib(x?\d\d)/}
+ || $item->name =~ m{^emul/ia(\d\d)}) {
+
+ my $bus_width = $1;
+
+ return 0
+ if exists $self->ARCH_REGEX->{$bus_width}
+ && $item->file_type =~ $self->ARCH_REGEX->{$bus_width};
+ }
+
+ # Detached debug symbols could be for a biarch library.
+ return 0
+ if $item->name =~ m{^usr/lib/debug/\.build-id/};
+
+ # Guile binaries do not objdump/strip (etc.) correctly.
+ return 0
+ if $item->name =~ $GUILE_PATH_REGEX;
+
+ # Allow amd64 kernel modules to be installed on i386.
+ if ( $item->name =~ m{^lib/modules/}
+ && $self->ARCH_64BIT_EQUIVS->recognizes($architecture)) {
+
+ my $equivalent_64 = $self->ARCH_64BIT_EQUIVS->value($architecture);
+
+ return 0
+ if $item->file_type =~ $self->ARCH_REGEX->{$equivalent_64};
+ }
+
+ # Ignore i386 binaries in amd64 packages for right now.
+ return 0
+ if $architecture eq 'amd64'
+ && $item->file_type =~ $self->ARCH_REGEX->{i386};
+
+ return 1;
+}
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x;
+
+ $self->pointed_hint('binary-from-other-architecture', $item->pointer)
+ if $self->from_other_architecture($item);
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Corrupted.pm b/lib/Lintian/Check/Binaries/Corrupted.pm
new file mode 100644
index 0000000..834ed31
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Corrupted.pm
@@ -0,0 +1,93 @@
+# binaries/corrupted -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Corrupted;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use List::SomeUtils qw(uniq);
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+sub visit_patched_files {
+ my ($self, $item) = @_;
+
+ $self->check_elf_issues($item);
+
+ return;
+}
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ $self->check_elf_issues($item);
+
+ return;
+}
+
+sub check_elf_issues {
+ my ($self, $item) = @_;
+
+ return unless $item->is_elf;
+
+ for (uniq @{$item->elf->{ERRORS} // []}) {
+ $self->pointed_hint('elf-error',$item->pointer, $_)
+ unless (
+ m{In program headers: Unable to find program interpreter name}
+ and $item->name =~ m{^usr/lib/debug/});
+ }
+
+ $self->pointed_hint('elf-warning', $item->pointer, $_)
+ for uniq @{$item->elf->{WARNINGS} // []};
+
+ # static library
+ for my $member_name (keys %{$item->elf_by_member}) {
+
+ my $member_elf = $item->elf_by_member->{$member_name};
+
+ $self->pointed_hint('elf-error', $item->pointer, $member_name, $_)
+ for uniq @{$member_elf->{ERRORS} // []};
+
+ $self->pointed_hint('elf-warning', $item->pointer, $member_name, $_)
+ for uniq @{$member_elf->{WARNINGS} // []};
+ }
+
+ $self->pointed_hint('binary-with-bad-dynamic-table', $item->pointer)
+ if $item->elf->{'BAD-DYNAMIC-TABLE'}
+ && $item->name !~ m{^usr/lib/debug/};
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/DebugSymbols.pm b/lib/Lintian/Check/Binaries/DebugSymbols.pm
new file mode 100644
index 0000000..4afe525
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/DebugSymbols.pm
@@ -0,0 +1,72 @@
+# binaries/debug-symbols -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::DebugSymbols;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+# Guile object files do not objdump/strip correctly, so exclude them
+# from a number of tests. (#918444)
+const my $GUILE_PATH_REGEX => qr{^usr/lib(?:/[^/]+)+/guile/[^/]+/.+\.go$};
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x;
+
+ # Is it an object file (which generally cannot be
+ # stripped), a kernel module, debugging symbols, or
+ # perhaps a debugging package?
+ $self->pointed_hint('unstripped-binary-or-object', $item->pointer)
+ if $item->file_type =~ m{ \b not [ ] stripped \b }x
+ && $item->name !~ m{ [.]k?o $}x
+ && $self->processable->name !~ m{ -dbg $}x
+ && $item->name !~ m{^ (?:usr/)? lib/debug/ }x
+ && $item->name !~ $GUILE_PATH_REGEX
+ && $item->name !~ m{ [.]gox $}x
+ && ( $item->file_type !~ m/executable/
+ || $item->strings !~ m{^ Caml1999X0[0-9][0-9] $}mx);
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/DebugSymbols/Detached.pm b/lib/Lintian/Check/Binaries/DebugSymbols/Detached.pm
new file mode 100644
index 0000000..b4f9a4f
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/DebugSymbols/Detached.pm
@@ -0,0 +1,86 @@
+# binaries/debug-symbols/detached -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::DebugSymbols::Detached;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use List::Compare;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x;
+
+ return
+ unless $item->file_type =~ m{ executable | shared [ ] object }x;
+
+ # Detached debugging symbols directly in /usr/lib/debug.
+ $self->pointed_hint('debug-symbols-directly-in-usr-lib-debug',
+ $item->pointer)
+ if $item->dirname eq 'usr/lib/debug/';
+
+ return
+ unless $item->name
+ =~ m{^ usr/lib/debug/ (?:lib\d*|s?bin|usr|opt|dev|emul|\.build-id) / }x;
+
+ $self->pointed_hint('debug-symbols-not-detached', $item->pointer)
+ if exists $item->elf->{NEEDED};
+
+ # Something other than detached debugging symbols in
+ # /usr/lib/debug paths.
+ my @KNOWN_DEBUG_SECTION_NAMES
+ = qw{.debug_line .zdebug_line .debug_str .zdebug_str};
+
+ my @elf_sections = values %{$item->elf->{'SECTION-HEADERS'}};
+ my @have_section_names = map { $_->name } @elf_sections;
+
+ my $lc_name
+ = List::Compare->new(\@have_section_names, \@KNOWN_DEBUG_SECTION_NAMES);
+
+ my @have_debug_sections = $lc_name->get_intersection;
+
+ $self->pointed_hint('debug-file-with-no-debug-symbols', $item->pointer)
+ unless @have_debug_sections;
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Hardening.pm b/lib/Lintian/Check/Binaries/Hardening.pm
new file mode 100644
index 0000000..55e70ac
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Hardening.pm
@@ -0,0 +1,183 @@
+# binaries/hardening -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Hardening;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has HARDENED_FUNCTIONS => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ return $self->data->load('binaries/hardened-functions');
+ }
+);
+
+has recommended_hardening_features => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my %recommended_hardening_features;
+
+ my $hardening_buildflags = $self->data->hardening_buildflags;
+ my $architecture = $self->processable->fields->value('Architecture');
+
+ %recommended_hardening_features
+ = map { $_ => 1 }
+ @{$hardening_buildflags->recommended_features->{$architecture}}
+ if $architecture ne 'all';
+
+ return \%recommended_hardening_features;
+ }
+);
+
+has built_with_golang => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my $built_with_golang = $self->processable->name =~ m/^golang-/;
+
+ my $source = $self->group->source;
+
+ $built_with_golang
+ = $source->relation('Build-Depends-All')
+ ->satisfies('golang-go | golang-any')
+ if defined $source;
+
+ return $built_with_golang;
+ }
+);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ my @elf_hardened;
+ my @elf_unhardened;
+
+ for my $symbol (@{$item->elf->{SYMBOLS}}) {
+
+ next
+ unless $symbol->section eq 'UND';
+
+ if ($symbol->name =~ /^__(\S+)_chk$/) {
+
+ my $vulnerable = $1;
+ push(@elf_hardened, $vulnerable)
+ if $self->HARDENED_FUNCTIONS->recognizes($vulnerable);
+
+ } else {
+
+ push(@elf_unhardened, $symbol->name)
+ if $self->HARDENED_FUNCTIONS->recognizes($symbol->name);
+ }
+ }
+
+ $self->pointed_hint('hardening-no-fortify-functions', $item->pointer)
+ if @elf_unhardened
+ && !@elf_hardened
+ && !$self->built_with_golang
+ && $self->recommended_hardening_features->{fortify};
+
+ for my $member_name (keys %{$item->elf_by_member}) {
+
+ my @member_hardened;
+ my @member_unhardened;
+
+ for my $symbol (@{$item->elf_by_member->{$member_name}{SYMBOLS}}) {
+
+ next
+ unless $symbol->section eq 'UND';
+
+ if ($symbol->name =~ /^__(\S+)_chk$/) {
+
+ my $vulnerable = $1;
+ push(@member_hardened, $vulnerable)
+ if $self->HARDENED_FUNCTIONS->recognizes($vulnerable);
+
+ } else {
+
+ push(@member_unhardened, $symbol->name)
+ if $self->HARDENED_FUNCTIONS->recognizes($symbol->name);
+ }
+ }
+
+ $self->pointed_hint('hardening-no-fortify-functions',
+ $item->pointer, $member_name)
+ if @member_unhardened
+ && !@member_hardened
+ && !$self->built_with_golang
+ && $self->recommended_hardening_features->{fortify};
+ }
+
+ return
+ if $self->processable->type eq 'udeb';
+
+ return
+ unless $item->is_file;
+
+ return
+ if $item->file_type !~ m{^ [^,]* \b ELF \b }x
+ || $item->file_type !~ m{ \b executable | shared [ ] object \b }x;
+
+ # dynamically linked?
+ return
+ unless exists $item->elf->{NEEDED};
+
+ $self->pointed_hint('hardening-no-relro', $item->pointer)
+ if $self->recommended_hardening_features->{relro}
+ && !$self->built_with_golang
+ && !$item->elf->{PH}{RELRO};
+
+ $self->pointed_hint('hardening-no-bindnow', $item->pointer)
+ if $self->recommended_hardening_features->{bindnow}
+ && !$self->built_with_golang
+ && !exists $item->elf->{FLAGS_1}{NOW};
+
+ $self->pointed_hint('hardening-no-pie', $item->pointer)
+ if $self->recommended_hardening_features->{pie}
+ && !$self->built_with_golang
+ && $item->elf->{'ELF-HEADER'}{Type} =~ m{^ EXEC }x;
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/LargeFileSupport.pm b/lib/Lintian/Check/Binaries/LargeFileSupport.pm
new file mode 100644
index 0000000..e64d727
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/LargeFileSupport.pm
@@ -0,0 +1,108 @@
+# binaries/large-file-support -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::LargeFileSupport;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use List::SomeUtils qw(any);
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has ARCH_REGEX => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my %arch_regex;
+
+ my $data = $self->data->load('binaries/arch-regex', qr/\s*\~\~/);
+ for my $architecture ($data->all) {
+
+ my $pattern = $data->value($architecture);
+ $arch_regex{$architecture} = qr{$pattern};
+ }
+
+ return \%arch_regex;
+ }
+);
+
+has LFS_SYMBOLS => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ return $self->data->load('binaries/lfs-symbols');
+ }
+);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ # The LFS check only works reliably for ELF files due to the
+ # architecture regex.
+ return
+ unless $item->is_elf;
+
+ # Only 32bit ELF binaries can lack LFS.
+ return
+ unless $item->file_type =~ $self->ARCH_REGEX->{'32'};
+
+ return
+ if $item->name =~ m{^usr/lib/debug/};
+
+ my @unresolved_symbols;
+ for my $symbol (@{$item->elf->{SYMBOLS} // [] }) {
+
+ # ignore if defined in the binary
+ next
+ unless $symbol->section eq 'UND';
+
+ push(@unresolved_symbols, $symbol->name);
+ }
+
+ # Using a 32bit only interface call, some parts of the
+ # binary are built without LFS
+ $self->pointed_hint('binary-file-built-without-LFS-support',$item->pointer)
+ if any { $self->LFS_SYMBOLS->recognizes($_) } @unresolved_symbols;
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Location.pm b/lib/Lintian/Check/Binaries/Location.pm
new file mode 100644
index 0000000..c207ae0
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Location.pm
@@ -0,0 +1,138 @@
+# binaries/location -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Location;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+const my $EMPTY => q{};
+
+const my %PATH_DIRECTORIES => map { $_ => 1 } qw(
+ bin/ sbin/ usr/bin/ usr/sbin/ usr/games/ );
+
+has DEB_HOST_MULTIARCH => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ return $self->data->architectures->deb_host_multiarch;
+ }
+);
+
+has gnu_triplet_pattern => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my $gnu_triplet_pattern = $EMPTY;
+
+ my $architecture = $self->processable->fields->value('Architecture');
+ my $madir = $self->DEB_HOST_MULTIARCH->{$architecture};
+
+ if (length $madir) {
+ $gnu_triplet_pattern = quotemeta $madir;
+ $gnu_triplet_pattern =~ s{^i386}{i[3-6]86};
+ }
+
+ return $gnu_triplet_pattern;
+ }
+);
+
+has ruby_triplet_pattern => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my $ruby_triplet_pattern = $self->gnu_triplet_pattern;
+ $ruby_triplet_pattern =~ s{linux\\-gnu$}{linux};
+ $ruby_triplet_pattern =~ s{linux\\-gnu}{linux\\-};
+
+ return $ruby_triplet_pattern;
+ }
+);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x
+ || $item->file_type =~ / \b current [ ] ar [ ] archive \b /x;
+
+ $self->pointed_hint('binary-in-etc', $item->pointer)
+ if $item->name =~ m{^etc/};
+
+ $self->pointed_hint('arch-dependent-file-in-usr-share', $item->pointer)
+ if $item->name =~ m{^usr/share/};
+
+ my $fields = $self->processable->fields;
+
+ my $architecture = $fields->value('Architecture');
+ my $multiarch = $fields->value('Multi-Arch') || 'no';
+
+ my $gnu_triplet_pattern = $self->gnu_triplet_pattern;
+ my $ruby_triplet_pattern = $self->ruby_triplet_pattern;
+
+ $self->pointed_hint('arch-dependent-file-not-in-arch-specific-directory',
+ $item->pointer)
+ if $multiarch eq 'same'
+ && length $gnu_triplet_pattern
+ && $item->name !~ m{\b$gnu_triplet_pattern(?:\b|_)}
+ && length $ruby_triplet_pattern
+ && $item->name !~ m{/$ruby_triplet_pattern/}
+ && $item->name !~ m{/java-\d+-openjdk-\Q$architecture\E/}
+ && $item->name !~ m{/[.]build-id/};
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x;
+
+ $self->pointed_hint('development-package-ships-elf-binary-in-path',
+ $item->pointer)
+ if exists $PATH_DIRECTORIES{$item->dirname}
+ && $fields->value('Section') =~ m{ (?:^|/) libdevel $}x
+ && $fields->value('Multi-Arch') ne 'foreign';
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Obsolete/Crypt.pm b/lib/Lintian/Check/Binaries/Obsolete/Crypt.pm
new file mode 100644
index 0000000..8813d8b
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Obsolete/Crypt.pm
@@ -0,0 +1,90 @@
+# binaries/obsolete/crypt -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Obsolete::Crypt;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has OBSOLETE_CRYPT_FUNCTIONS => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ return $self->data->load('binaries/obsolete-crypt-functions',
+ qr/\s*\|\|\s*/);
+ }
+);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ for my $symbol (@{$item->elf->{SYMBOLS} // []}) {
+
+ next
+ unless $symbol->section eq 'UND';
+
+ next
+ unless $self->OBSOLETE_CRYPT_FUNCTIONS->recognizes($symbol->name);
+
+ my $tag = $self->OBSOLETE_CRYPT_FUNCTIONS->value($symbol->name);
+
+ $self->pointed_hint($tag, $item->pointer, $symbol->name);
+ }
+
+ for my $member_name (keys %{$item->elf_by_member}) {
+
+ for
+ my $symbol (@{$item->elf_by_member->{$member_name}{SYMBOLS} // []}) {
+
+ next
+ unless $symbol->section eq 'UND';
+
+ next
+ unless $self->OBSOLETE_CRYPT_FUNCTIONS->recognizes(
+ $symbol->name);
+
+ my $tag = $self->OBSOLETE_CRYPT_FUNCTIONS->value($symbol->name);
+
+ $self->pointed_hint($tag, $item->pointer, "($member_name)",
+ $symbol->name);
+ }
+ }
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Prerequisites.pm b/lib/Lintian/Check/Binaries/Prerequisites.pm
new file mode 100644
index 0000000..cdc5868
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Prerequisites.pm
@@ -0,0 +1,214 @@
+# binaries/prerequisites -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Prerequisites;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+use List::SomeUtils qw(any none uniq);
+
+const my $SPACE => q{ };
+const my $LEFT_PARENTHESIS => q{(};
+const my $RIGHT_PARENTHESIS => q{)};
+
+# Guile object files do not objdump/strip correctly, so exclude them
+# from a number of tests. (#918444)
+const my $GUILE_PATH_REGEX => qr{^usr/lib(?:/[^/]+)+/guile/[^/]+/.+\.go$};
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has built_with_octave => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my $built_with_octave = $self->processable->name =~ m/^octave-/;
+
+ my $source = $self->group->source;
+
+ $built_with_octave
+ = $source->relation('Build-Depends')->satisfies('dh-octave:any')
+ if defined $source;
+
+ return $built_with_octave;
+ }
+);
+
+has files_by_library => (is => 'rw', default => sub { {} });
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ if $self->processable->type eq 'udeb';
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x;
+
+ return
+ unless $item->file_type =~ m{ executable | shared [ ] object }x;
+
+ my $is_shared = $item->file_type =~ m/(shared object|pie executable)/;
+
+ for my $library (@{$item->elf->{NEEDED} // [] }) {
+
+ $self->files_by_library->{$library} //= [];
+ push(@{$self->files_by_library->{$library}}, $item->name);
+ }
+
+ # Some exceptions: kernel modules, syslinux modules, detached
+ # debugging information and the dynamic loader (which itself
+ # has no dependencies).
+ $self->pointed_hint('shared-library-lacks-prerequisites', $item->pointer)
+ if $is_shared
+ && !@{$item->elf->{NEEDED} // []}
+ && $item->name !~ m{^boot/modules/}
+ && $item->name !~ m{^lib/modules/}
+ && $item->name !~ m{^usr/lib/debug/}
+ && $item->name !~ m{\.(?:[ce]32|e64)$}
+ && $item->name !~ m{^usr/lib/jvm/.*\.debuginfo$}
+ && $item->name !~ $GUILE_PATH_REGEX
+ && $item->name !~ m{
+ ^lib(?:|32|x32|64)/
+ (?:[-\w/]+/)?
+ ld-[\d.]+\.so$
+ }xsm;
+
+ my $depends = $self->processable->relation('strong');
+
+ $self->pointed_hint('undeclared-elf-prerequisites', $item->pointer,
+ $LEFT_PARENTHESIS
+ . join($SPACE, sort +uniq @{$item->elf->{NEEDED} // []})
+ . $RIGHT_PARENTHESIS)
+ if @{$item->elf->{NEEDED} // [] }
+ && $depends->is_empty;
+
+ # If there is no libc dependency, then it is most likely a
+ # bug. The major exception is that some C++ libraries,
+ # but these tend to link against libstdc++ instead. (see
+ # #719806)
+ my $linked_with_libc
+ = any { m{^ libc[.]so[.] }x } @{$item->elf->{NEEDED} // []};
+
+ $self->pointed_hint('library-not-linked-against-libc', $item->pointer)
+ if !$linked_with_libc
+ && $is_shared
+ && @{$item->elf->{NEEDED} // [] }
+ && (none { /^libc[.]so[.]/ } @{$item->elf->{NEEDED} // [] })
+ && $item->name !~ m{/libc\b}
+ && (!$self->built_with_octave
+ || $item->name !~ m/\.(?:oct|mex)$/);
+
+ $self->pointed_hint('program-not-linked-against-libc', $item->pointer)
+ if !$linked_with_libc
+ && !$is_shared
+ && @{$item->elf->{NEEDED} // [] }
+ && (none { /^libstdc[+][+][.]so[.]/ }@{$item->elf->{NEEDED} // [] })
+ && !$self->built_with_octave;
+
+ return;
+}
+
+sub installable {
+ my ($self) = @_;
+
+ my $depends = $self->processable->relation('strong');
+ return
+ if $depends->is_empty;
+
+ my %libc_files;
+ for my $library (keys %{$self->files_by_library}) {
+
+ # Match libcXX or libcXX-*, but not libc3p0.
+ next
+ unless $library =~ m{^ libc [.] so [.] (\d+ .*) $}x;
+
+ my $package = "libc$1";
+
+ $libc_files{$package} //= [];
+ push(@{$libc_files{$package}}, @{$self->files_by_library->{$library}});
+ }
+
+ for my $package (keys %libc_files) {
+
+ next
+ if $depends->matches(qr/^\Q$package\E\b/);
+
+ my @sorted = sort +uniq @{$libc_files{$package}};
+
+ my $context = 'needed by ' . $sorted[0];
+ $context .= ' and ' . (scalar @sorted - 1) . ' others'
+ if @sorted > 1;
+
+ $self->hint('missing-dependency-on-libc', $context)
+ unless $self->processable->name =~ m{^ libc [\d.]+ (?:-|\z) }x;
+ }
+
+ my %libcxx_files;
+ for my $library (keys %{$self->files_by_library}) {
+
+ # Match libstdc++XX or libcstdc++XX-*
+ next
+ unless $library =~ m{^ libstdc[+][+] [.] so [.] (\d+) $}xsm;
+
+ my $package = "libstdc++$1";
+
+ $libcxx_files{$package} //= [];
+ push(@{$libcxx_files{$package}},
+ @{$self->files_by_library->{$library}});
+ }
+
+ for my $package (keys %libcxx_files) {
+
+ next
+ if $depends->matches(qr/^\Q$package\E\b/);
+
+ my @sorted = sort +uniq @{$libcxx_files{$package}};
+
+ my $context = 'needed by ' . $sorted[0];
+ $context .= ' and ' . (scalar @sorted - 1) . ' others'
+ if @sorted > 1;
+
+ $self->hint('missing-dependency-on-libstdc++', $context);
+ }
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Prerequisites/Numpy.pm b/lib/Lintian/Check/Binaries/Prerequisites/Numpy.pm
new file mode 100644
index 0000000..c1ecfc3
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Prerequisites/Numpy.pm
@@ -0,0 +1,107 @@
+# binaries/prerequisites/numpy -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Prerequisites::Numpy;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+
+use Lintian::Relation;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+const my $NUMPY_REGEX => qr{
+ \Qmodule compiled against ABI version \E (?:0x)?%x
+ \Q but this version of numpy is \E (?:0x)?%x
+}x;
+
+has uses_numpy_c_abi => (is => 'rw', default => 0);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ if $item->file_type !~ m{^ [^,]* \b ELF \b }x
+ || $item->file_type !~ m{ \b executable | shared [ ] object \b }x;
+
+ # Python extension using Numpy C ABI?
+ if ( $item->name=~ m{^usr/lib/(?:pyshared/)?python2\.\d+/.*(?<!_d)\.so$}
+ || $item->name
+ =~ m{^ usr/lib/python3(?:[.]\d+)? / \S+ [.]cpython- \d+ - \S+ [.]so $}x
+ ){
+ $self->uses_numpy_c_abi(1)
+ if $item->strings =~ / numpy /msx
+ && $item->strings =~ $NUMPY_REGEX;
+ }
+
+ return;
+}
+
+sub installable {
+ my ($self) = @_;
+
+ return
+ if $self->processable->type eq 'udeb';
+
+ my $depends = $self->processable->relation('strong');
+
+ # Check for dependency on python3-numpy-abiN dependency (or strict
+ # versioned dependency on python3-numpy)
+ # We do not allow alternatives as it would mostly likely
+ # defeat the purpose of this relation. Also, we do not allow
+ # versions for -abi as it is a virtual package.
+ $self->hint('missing-dependency-on-numpy-abi')
+ if $self->uses_numpy_c_abi
+ && !$depends->matches(qr/^python3?-numpy-abi\d+$/,
+ Lintian::Relation::VISIT_OR_CLAUSE_FULL)
+ && (
+ !$depends->matches(
+ qr/^python3-numpy \(>[>=][^\|]+$/,
+ Lintian::Relation::VISIT_OR_CLAUSE_FULL
+ )
+ || !$depends->matches(
+ qr/^python3-numpy \(<[<=][^\|]+$/,
+ Lintian::Relation::VISIT_OR_CLAUSE_FULL
+ )
+ )
+ && $self->processable->name !~ m{\A python3?-numpy \Z}xsm;
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Prerequisites/Perl.pm b/lib/Lintian/Check/Binaries/Prerequisites/Perl.pm
new file mode 100644
index 0000000..a105d25
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Prerequisites/Perl.pm
@@ -0,0 +1,81 @@
+# binaries/prerequisites/perl -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Prerequisites::Perl;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Lintian::Relation;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has has_perl_lib => (is => 'rw', default => 0);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ if $item->file_type !~ m{^ [^,]* \b ELF \b }x
+ || $item->file_type !~ m{ \b executable | shared [ ] object \b }x;
+
+ $self->has_perl_lib(1)
+ if $item->name =~ m{^ usr/lib/ (?:[^/]+/)? perl5/ .* [.]so $}x;
+
+ return;
+}
+
+sub installable {
+ my ($self) = @_;
+
+ return
+ if $self->processable->type eq 'udeb';
+
+ my $depends = $self->processable->relation('strong');
+
+ # It is a virtual package, so no version is allowed and
+ # alternatives probably does not make sense here either.
+ $self->hint('missing-dependency-on-perlapi')
+ if $self->has_perl_lib
+ && !$depends->matches(
+ qr/^perlapi-[-\w.]+(?:\s*\[[^\]]+\])?$/,
+ Lintian::Relation::VISIT_OR_CLAUSE_FULL
+ );
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Prerequisites/Php.pm b/lib/Lintian/Check/Binaries/Prerequisites/Php.pm
new file mode 100644
index 0000000..f4f9634
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Prerequisites/Php.pm
@@ -0,0 +1,80 @@
+# binaries/prerequisites/php -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Prerequisites::Php;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Lintian::Relation;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has has_php_ext => (is => 'rw', default => 0);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ if $item->file_type !~ m{^ [^,]* \b ELF \b }x
+ || $item->file_type !~ m{ \b executable | shared [ ] object \b }x;
+
+ # PHP extension?
+ $self->has_php_ext(1)
+ if $item->name =~ m{^usr/lib/php\d/.*\.so(?:\.\d+)*$};
+
+ return;
+}
+
+sub installable {
+ my ($self) = @_;
+
+ return
+ if $self->processable->type eq 'udeb';
+
+ my $depends = $self->processable->relation('strong');
+
+ # It is a virtual package, so no version is allowed and
+ # alternatives probably does not make sense here either.
+ $self->hint('missing-dependency-on-phpapi')
+ if $self->has_php_ext
+ && !$depends->matches(qr/^phpapi-[\d\w+]+$/,
+ Lintian::Relation::VISIT_OR_CLAUSE_FULL);
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Profiling.pm b/lib/Lintian/Check/Binaries/Profiling.pm
new file mode 100644
index 0000000..4b52937
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Profiling.pm
@@ -0,0 +1,73 @@
+# binaries/profiling -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Profiling;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ my $architecture = $self->processable->fields->value('Architecture');
+
+ my $is_profiled = 0;
+
+ for my $symbol (@{$item->elf->{SYMBOLS} // [] }) {
+
+ # According to the binutils documentation[1], the profiling symbol
+ # can be named "mcount", "_mcount" or even "__mcount".
+ # [1] http://sourceware.org/binutils/docs/gprof/Implementation.html
+ $is_profiled = 1
+ if $symbol->version =~ /^GLIBC_.*/
+ && $symbol->name =~ m{\A _?+ _?+ (gnu_)?+mcount(_nc)?+ \Z}xsm
+ && ($symbol->section eq 'UND' || $symbol->section eq '.text');
+
+ # This code was used to detect profiled code in Wheezy and earlier
+ $is_profiled = 1
+ if $symbol->section eq '.text'
+ && $symbol->version eq 'Base'
+ && $symbol->name eq '__gmon_start__'
+ && $architecture ne 'hppa';
+ }
+
+ $self->pointed_hint('binary-compiled-with-profiling-enabled',
+ $item->pointer)
+ if $is_profiled;
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Rpath.pm b/lib/Lintian/Check/Binaries/Rpath.pm
new file mode 100644
index 0000000..a4ecb93
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Rpath.pm
@@ -0,0 +1,145 @@
+# binaries/rpath -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Rpath;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+use File::Spec;
+use List::SomeUtils qw(any);
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+const my $SLASH => q{/};
+
+has DEB_HOST_MULTIARCH => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ return $self->data->architectures->deb_host_multiarch;
+ }
+);
+
+has multiarch_component => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my $architecture = $self->processable->fields->value('Architecture');
+ my $multiarch_component = $self->DEB_HOST_MULTIARCH->{$architecture};
+
+ return $multiarch_component;
+ }
+);
+
+has private_folders => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my @lib_folders = qw{lib};
+
+ push(@lib_folders,
+ map { $_ . $SLASH . $self->multiarch_component } @lib_folders)
+ if length $self->multiarch_component;
+
+ my @usrlib_folders = qw{usr/lib};
+
+ push(@usrlib_folders,
+ map { $_ . $SLASH . $self->multiarch_component } @usrlib_folders)
+ if length $self->multiarch_component;
+
+ my @game_folders = map { "$_/games" } @usrlib_folders;
+
+ my @private_folders
+ = map { $_ . $SLASH . $self->processable->source_name }
+ (@lib_folders, @usrlib_folders, @game_folders);
+
+ return \@private_folders;
+ }
+);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x;
+
+ for my $section (qw{RPATH RUNPATH}) {
+
+ my @rpaths = keys %{$item->elf->{$section} // {}};
+
+ my @no_origin = grep { !m{^ \$ \{? ORIGIN \}? }x } @rpaths;
+
+ my @canonical = map { File::Spec->canonpath($_) } @no_origin;
+
+ my @custom;
+ for my $folder (@canonical) {
+
+ # for shipped folders, would have to disallow system locations
+ next
+ if any { $folder =~ m{^ / \Q$_\E }x } @{$self->private_folders};
+
+ # GHC in Debian uses a scheme for RPATH (#914873)
+ next
+ if $folder =~ m{^ /usr/lib/ghc (?: / | $ ) }x;
+
+ push(@custom, $folder);
+ }
+
+ my @absolute = grep { m{^ / }x } @custom;
+
+ $self->pointed_hint('custom-library-search-path',
+ $item->pointer, $section, $_)
+ for @absolute;
+
+ my @relative = grep { m{^ [^/] }x } @custom;
+
+ $self->pointed_hint('relative-library-search-path',
+ $item->pointer, $section, $_)
+ for @relative;
+ }
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Spelling.pm b/lib/Lintian/Check/Binaries/Spelling.pm
new file mode 100644
index 0000000..38a2529
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Spelling.pm
@@ -0,0 +1,86 @@
+# binaries/spelling -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Spelling;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Lintian::Spelling qw(check_spelling);
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has BINARY_SPELLING_EXCEPTIONS => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ return $self->data->load('binaries/spelling-exceptions',qr/\s+/);
+ }
+);
+
+sub spelling_tag_emitter {
+ my ($self, $tag_name, $item, @orig_args) = @_;
+
+ return sub {
+
+ my $pointer = $item->pointer($.);
+
+ return $self->pointed_hint($tag_name, $pointer, @orig_args, @_);
+ };
+}
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x;
+
+ my @acceptable = (
+ @{ $self->group->spelling_exceptions },
+ $self->BINARY_SPELLING_EXCEPTIONS->all
+ );
+
+ my $tag_emitter
+ = $self->spelling_tag_emitter('spelling-error-in-binary', $item);
+
+ check_spelling($self->data, $item->strings, \@acceptable, $tag_emitter, 0);
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/lib/Lintian/Check/Binaries/Static.pm b/lib/Lintian/Check/Binaries/Static.pm
new file mode 100644
index 0000000..47eafb8
--- /dev/null
+++ b/lib/Lintian/Check/Binaries/Static.pm
@@ -0,0 +1,100 @@
+# binaries/static -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
+# Copyright (C) 2017-2020 Chris Lamb <lamby@debian.org>
+# Copyright (C) 2021 Felix Lechner
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at https://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+package Lintian::Check::Binaries::Static;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has built_with_golang => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my $built_with_golang = $self->processable->name =~ m/^golang-/;
+
+ my $source = $self->group->source;
+
+ $built_with_golang
+ = $source->relation('Build-Depends-All')
+ ->satisfies('golang-go | golang-any')
+ if defined $source;
+
+ return $built_with_golang;
+ }
+);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ if $self->processable->type eq 'udeb';
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ /^ [^,]* \b ELF \b /x;
+
+ return
+ unless $item->file_type =~ m{ executable | shared [ ] object }x;
+
+ my $is_shared = $item->file_type =~ m/(shared object|pie executable)/;
+
+ # Some exceptions: files in /boot, /usr/lib/debug/*,
+ # named *-static or *.static, or *-static as
+ # package-name.
+ # Binaries built by the Go compiler are statically
+ # linked by default.
+ # klibc binaries appear to be static.
+ # Location of debugging symbols.
+ # ldconfig must be static.
+ $self->pointed_hint('statically-linked-binary', $item->pointer)
+ if !$is_shared
+ && !exists $item->elf->{NEEDED}
+ && $item->name !~ m{^boot/}
+ && $item->name !~ /[\.-]static$/
+ && $self->processable->name !~ /-static$/
+ && !$self->built_with_golang
+ && (!exists $item->elf->{INTERP}
+ || $item->elf->{INTERP} !~ m{/lib/klibc-\S+\.so})
+ && $item->name !~ m{^usr/lib/debug/}
+ && $item->name ne 'sbin/ldconfig';
+
+ return;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et