summaryrefslogtreecommitdiffstats
path: root/lib/Lintian/Check/Libraries/Shared
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lintian/Check/Libraries/Shared')
-rw-r--r--lib/Lintian/Check/Libraries/Shared/Exit.pm72
-rw-r--r--lib/Lintian/Check/Libraries/Shared/FilePermissions.pm72
-rw-r--r--lib/Lintian/Check/Libraries/Shared/Links.pm167
-rw-r--r--lib/Lintian/Check/Libraries/Shared/MultiArch.pm79
-rw-r--r--lib/Lintian/Check/Libraries/Shared/Obsolete.pm56
-rw-r--r--lib/Lintian/Check/Libraries/Shared/Relocation.pm58
-rw-r--r--lib/Lintian/Check/Libraries/Shared/Soname.pm123
-rw-r--r--lib/Lintian/Check/Libraries/Shared/Soname/Missing.pm73
-rw-r--r--lib/Lintian/Check/Libraries/Shared/Stack.pm69
-rw-r--r--lib/Lintian/Check/Libraries/Shared/Trigger/Ldconfig.pm131
10 files changed, 900 insertions, 0 deletions
diff --git a/lib/Lintian/Check/Libraries/Shared/Exit.pm b/lib/Lintian/Check/Libraries/Shared/Exit.pm
new file mode 100644
index 0000000..5788808
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/Exit.pm
@@ -0,0 +1,72 @@
+# libraries/shared/exit -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz
+# Copyright (C) 2018-2019 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::Libraries::Shared::Exit;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use List::SomeUtils qw(any none);
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+# not presently used
+#my $UNKNOWN_SHARED_LIBRARY_EXCEPTIONS
+# = $self->data->load('shared-libs/unknown-shared-library-exceptions');
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ # shared library
+ return
+ unless @{$item->elf->{SONAME} // [] };
+
+ my @symbols = grep { $_->section eq '.text' || $_->section eq 'UND' }
+ @{$item->elf->{SYMBOLS} // []};
+
+ my @symbol_names = map { $_->name } @symbols;
+
+ # If it has an INTERP section it might be an application with
+ # a SONAME (hi openjdk-6, see #614305). Also see the comment
+ # for "shared-library-is-executable" below.
+ $self->pointed_hint('exit-in-shared-library', $item->pointer)
+ if (any { m/^_?exit$/ } @symbol_names)
+ && (none { $_ eq 'fork' } @symbol_names)
+ && !length $item->elf->{INTERP};
+
+ 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/Libraries/Shared/FilePermissions.pm b/lib/Lintian/Check/Libraries/Shared/FilePermissions.pm
new file mode 100644
index 0000000..663205e
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/FilePermissions.pm
@@ -0,0 +1,72 @@
+# libraries/shared/file-permissions -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz
+# Copyright (C) 2018-2019 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::Libraries::Shared::FilePermissions;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+const my $WIDELY_READABLE => oct(644);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ # shared library
+ return
+ unless @{$item->elf->{SONAME} // [] };
+
+ # Yes. But if the library has an INTERP section, it's
+ # designed to do something useful when executed, so don't
+ # report an error. Also give ld.so a pass, since it's
+ # special.
+ $self->pointed_hint('shared-library-is-executable',
+ $item->pointer, $item->octal_permissions)
+ if $item->is_executable
+ && !$item->elf->{INTERP}
+ && $item->name !~ m{^lib.*/ld-[\d.]+\.so$};
+
+ $self->pointed_hint('odd-permissions-on-shared-library',
+ $item->pointer, $item->octal_permissions)
+ if !$item->is_executable
+ && $item->operm != $WIDELY_READABLE;
+
+ 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/Libraries/Shared/Links.pm b/lib/Lintian/Check/Libraries/Shared/Links.pm
new file mode 100644
index 0000000..e25d3fd
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/Links.pm
@@ -0,0 +1,167 @@
+# libraries/shared/links -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz
+# Copyright (C) 2018-2019 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::Libraries::Shared::Links;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+use List::SomeUtils qw(none);
+
+const my $ARROW => q{->};
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has development_packages => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my @development_packages;
+
+ for my $installable ($self->group->get_installables) {
+
+ push(@development_packages, $installable)
+ if $installable->name =~ /-dev$/
+ && $installable->relation('strong')
+ ->satisfies($self->processable->name);
+ }
+
+ return \@development_packages;
+ }
+);
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ # shared library
+ return
+ unless @{$item->elf->{SONAME} // [] };
+
+ my $soname = $item->elf->{SONAME}[0];
+
+ my @ldconfig_folders = @{$self->data->architectures->ldconfig_folders};
+ return
+ if none { $item->dirname eq $_ } @ldconfig_folders;
+
+ my $installed = $self->processable->installed;
+
+ my $versioned_name = $item->dirname . $soname;
+ my $versioned_item = $installed->lookup($versioned_name);
+
+ my $unversioned_name = $versioned_name;
+ # libtool "-release" variant
+ $unversioned_name =~ s/-[\d\.]+\.so$/.so/;
+ # determine shlib link name (w/o version)
+ $unversioned_name =~ s/\.so.+$/.so/;
+
+ $self->pointed_hint('lacks-versioned-link-to-shared-library',
+ $item->pointer, $versioned_name)
+ unless defined $versioned_item;
+
+ $self->pointed_hint(
+ 'ldconfig-symlink-referencing-wrong-file',
+ $versioned_item->pointer,'should point to',
+ $versioned_item->link,'instead of',$item->basename
+ )
+ if $versioned_name ne $item->name
+ && defined $versioned_item
+ && $versioned_item->is_symlink
+ && $versioned_item->link ne $item->basename;
+
+ $self->pointed_hint(
+ 'ldconfig-symlink-is-not-a-symlink',
+ $versioned_item->pointer,'should point to',
+ $item->name
+ )
+ if $versioned_name ne $item->name
+ && defined $versioned_item
+ && !$versioned_item->is_symlink;
+
+ # shlib symlink may not exist.
+ # if shlib doesn't _have_ a version, then $unversioned_name and
+ # $item->name will be equal, and it's not a development link,
+ # so don't complain.
+ $self->pointed_hint(
+ 'link-to-shared-library-in-wrong-package',
+ $installed->lookup($unversioned_name)->pointer,
+ $item->name
+ )
+ if $unversioned_name ne $item->name
+ && defined $installed->lookup($unversioned_name);
+
+ # If the shared library is in /lib, we have to look for
+ # the dev symlink in /usr/lib
+ $unversioned_name = "usr/$unversioned_name"
+ unless $item->name =~ m{^usr/};
+
+ my @dev_links;
+ for my $dev_installable (@{$self->development_packages}) {
+ for my $dev_item (@{$dev_installable->installed->sorted_list}) {
+
+ next
+ unless $dev_item->is_symlink;
+
+ next
+ unless $dev_item->name =~ m{^ usr/lib/ }x;
+
+ # try absolute first
+ my $resolved = $installed->resolve_path($dev_item->link);
+
+ # otherwise relative
+ $resolved
+ = $installed->resolve_path($dev_item->dirname . $dev_item->link)
+ unless defined $resolved;
+
+ next
+ unless defined $resolved;
+
+ push(@dev_links, $dev_item)
+ if $resolved->name eq $item->name;
+ }
+ }
+
+ # found -dev package; library needs a symlink
+ $self->pointed_hint('lacks-unversioned-link-to-shared-library',
+ $item->pointer, "example: $unversioned_name")
+ if @{$self->development_packages}
+ && (none { $_->name =~ m{ [.]so $}x } @dev_links);
+
+ 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/Libraries/Shared/MultiArch.pm b/lib/Lintian/Check/Libraries/Shared/MultiArch.pm
new file mode 100644
index 0000000..52c1bc5
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/MultiArch.pm
@@ -0,0 +1,79 @@
+# libraries/shared/multi-arch -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz
+# Copyright (C) 2018-2019 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::Libraries::Shared::MultiArch;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use List::SomeUtils qw(none uniq);
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has shared_libraries => (is => 'rw', default => sub { [] });
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ return
+ unless $item->is_file;
+
+ return
+ unless $item->file_type =~ m{^ [^,]* \b ELF \b }x;
+
+ return
+ unless $item->file_type
+ =~ m{(?: shared [ ] object | pie [ ] executable )}x;
+
+ my @ldconfig_folders = @{$self->data->architectures->ldconfig_folders};
+ return
+ if none { $item->dirname eq $_ } @ldconfig_folders;
+
+ push(@{$self->shared_libraries}, $item->name);
+
+ return;
+}
+
+sub installable {
+ my ($self) = @_;
+
+ $self->hint(
+ 'shared-library-is-multi-arch-foreign',
+ (sort +uniq @{$self->shared_libraries})
+ )
+ if @{$self->shared_libraries}
+ && $self->processable->fields->value('Multi-Arch') eq '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/Libraries/Shared/Obsolete.pm b/lib/Lintian/Check/Libraries/Shared/Obsolete.pm
new file mode 100644
index 0000000..699b70c
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/Obsolete.pm
@@ -0,0 +1,56 @@
+# libraries/shared/obsolete -- lintian check script -*- perl -*-
+
+# Copyright (C) 2020 Mo Zhou
+#
+# 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::Libraries::Shared::Obsolete;
+
+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 =~ /^[^,]*\bELF\b/;
+
+ my @needed = @{$item->elf->{NEEDED} // []};
+ my @obsolete = grep { /^libcblas\.so\.\d/ } @needed;
+
+ $self->pointed_hint('linked-with-obsolete-library', $item->pointer, $_)
+ for @obsolete;
+
+ 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/Libraries/Shared/Relocation.pm b/lib/Lintian/Check/Libraries/Shared/Relocation.pm
new file mode 100644
index 0000000..8c3dac9
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/Relocation.pm
@@ -0,0 +1,58 @@
+# libraries/shared/relocation -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz
+# Copyright (C) 2018-2019 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::Libraries::Shared::Relocation;
+
+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;
+
+ # shared library
+ return
+ unless @{$item->elf->{SONAME} // [] };
+
+ # Now that we're sure this is really a shared library, report on
+ # non-PIC problems.
+ $self->pointed_hint('specific-address-in-shared-library', $item->pointer)
+ if $item->elf->{TEXTREL};
+
+ 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/Libraries/Shared/Soname.pm b/lib/Lintian/Check/Libraries/Shared/Soname.pm
new file mode 100644
index 0000000..9887e3b
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/Soname.pm
@@ -0,0 +1,123 @@
+# libraries/shared/soname -- 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::Libraries::Shared::Soname;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use Const::Fast;
+use List::SomeUtils qw(any none uniq);
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+const my $SPACE => q{ };
+const my $SLASH => q{/};
+
+has DEB_HOST_MULTIARCH => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ return $self->data->architectures->deb_host_multiarch;
+ }
+);
+
+sub installable {
+ my ($self) = @_;
+
+ return
+ if $self->processable->type eq 'udeb';
+
+ my $architecture = $self->processable->fields->value('Architecture');
+ my $multiarch_component = $self->DEB_HOST_MULTIARCH->{$architecture};
+
+ my @common_folders = qw{lib usr/lib};
+ push(@common_folders, map { "$_/$multiarch_component" } @common_folders)
+ if length $multiarch_component;
+
+ my @duplicated;
+ for my $item (@{$self->processable->installed->sorted_list}) {
+
+ # For the package naming check, filter out SONAMEs where all the
+ # files are at paths other than /lib, /usr/lib and /usr/lib/<MA-DIR>.
+ # This avoids false positives with plugins like Apache modules,
+ # which may have their own SONAMEs but which don't matter for the
+ # purposes of this check.
+ next
+ if none { $item->dirname eq $_ . $SLASH } @common_folders;
+
+ # Also filter out nsswitch modules
+ next
+ if $item->basename =~ m{^ libnss_[^.]+\.so(?:\.\d+) $}x;
+
+ push(@duplicated, @{$item->elf->{SONAME} // []});
+ }
+
+ my @sonames = uniq @duplicated;
+
+ # try to strip transition strings
+ my $shortened_name = $self->processable->name;
+ $shortened_name =~ s/c102\b//;
+ $shortened_name =~ s/c2a?\b//;
+ $shortened_name =~ s/\dg$//;
+ $shortened_name =~ s/gf$//;
+ $shortened_name =~ s/v[5-6]$//; # GCC-5 / libstdc++6 C11 ABI breakage
+ $shortened_name =~ s/-udeb$//;
+ $shortened_name =~ s/^lib64/lib/;
+
+ my $match_found = 0;
+ for my $soname (@sonames) {
+
+ $soname =~ s/ ([0-9]) [.]so[.] /$1-/x;
+ $soname =~ s/ [.]so (?:[.]|\z) //x;
+ $soname =~ s/_/-/g;
+
+ my $lowercase = lc $soname;
+
+ $match_found = any { $lowercase eq $_ }
+ ($self->processable->name, $shortened_name);
+
+ last
+ if $match_found;
+ }
+
+ $self->hint('package-name-doesnt-match-sonames',
+ join($SPACE, sort @sonames))
+ if @sonames && !$match_found;
+
+ 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/Libraries/Shared/Soname/Missing.pm b/lib/Lintian/Check/Libraries/Shared/Soname/Missing.pm
new file mode 100644
index 0000000..a01a878
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/Soname/Missing.pm
@@ -0,0 +1,73 @@
+# libraries/shared/soname/missing -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz
+# Copyright (C) 2018-2019 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::Libraries::Shared::Soname::Missing;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use List::SomeUtils qw(none);
+
+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;
+
+ return
+ unless $item->file_type
+ =~ m{(?: shared [ ] object | pie [ ] executable )}x;
+
+ # does not have SONAME
+ return
+ if @{$item->elf->{SONAME} // [] };
+
+ my @ldconfig_folders = @{$self->data->architectures->ldconfig_folders};
+ return
+ if none { $item->dirname eq $_ } @ldconfig_folders;
+
+ # disregard executables
+ $self->pointed_hint('sharedobject-in-library-directory-missing-soname',
+ $item->pointer)
+ if !$item->is_executable
+ || !defined $item->elf->{DEBUG}
+ || $item->name =~ / [.]so (?: [.] | $ ) /msx;
+
+ 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/Libraries/Shared/Stack.pm b/lib/Lintian/Check/Libraries/Shared/Stack.pm
new file mode 100644
index 0000000..f3e1d03
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/Stack.pm
@@ -0,0 +1,69 @@
+# libraries/shared/stack -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz
+# Copyright (C) 2018-2019 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::Libraries::Shared::Stack;
+
+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;
+
+ # shared library
+ return
+ unless @{$item->elf->{SONAME} // [] };
+
+ $self->pointed_hint('shared-library-lacks-stack-section',$item->pointer)
+ if $self->processable->fields->declares('Architecture')
+ && !exists $item->elf->{PH}{STACK};
+
+ $self->pointed_hint('executable-stack-in-shared-library', $item->pointer)
+ if exists $item->elf->{PH}{STACK}
+ && $item->elf->{PH}{STACK}{flags} ne 'rw-'
+ # Once the following line is removed again, please also remove
+ # the Test-Architectures line in
+ # t/recipes/checks/libraries/shared/stack/shared-libs-exec-stack/eval/desc
+ # and the MIPS-related notes in
+ # tags/e/executable-stack-in-shared-library.tag. See
+ # https://bugs.debian.org/1025436 and
+ # https://bugs.debian.org/1022787 for details
+ && $self->processable->fields->value('Architecture') !~ /mips/;
+
+ 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/Libraries/Shared/Trigger/Ldconfig.pm b/lib/Lintian/Check/Libraries/Shared/Trigger/Ldconfig.pm
new file mode 100644
index 0000000..66f5961
--- /dev/null
+++ b/lib/Lintian/Check/Libraries/Shared/Trigger/Ldconfig.pm
@@ -0,0 +1,131 @@
+# libraries/shared/trigger/ldconfig -- lintian check script -*- perl -*-
+
+# Copyright (C) 1998 Christian Schwarz
+# Copyright (C) 2018-2019 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::Libraries::Shared::Trigger::Ldconfig;
+
+use v5.20;
+use warnings;
+use utf8;
+
+use List::SomeUtils qw(any uniq);
+
+use Moo;
+use namespace::clean;
+
+with 'Lintian::Check';
+
+has soname_by_filename => (
+ is => 'rw',
+ lazy => 1,
+ default => sub {
+ my ($self) = @_;
+
+ my %soname_by_filename;
+ for my $item (@{$self->processable->installed->sorted_list}) {
+
+ $soname_by_filename{$item->name}= $item->elf->{SONAME}[0]
+ if exists $item->elf->{SONAME};
+ }
+
+ return \%soname_by_filename;
+ }
+);
+
+has must_call_ldconfig => (is => 'rw', default => sub { [] });
+
+sub visit_installed_files {
+ my ($self, $item) = @_;
+
+ my $resolved_name = $item->name;
+ $resolved_name = $item->link_normalized
+ if length $item->link;
+
+ # Installed in a directory controlled by the dynamic
+ # linker? We have to strip off directories named for
+ # hardware capabilities.
+ # yes! so postinst must call ldconfig
+ push(@{$self->must_call_ldconfig}, $resolved_name)
+ if exists $self->soname_by_filename->{$resolved_name}
+ && $self->needs_ldconfig($item);
+
+ return;
+}
+
+sub installable {
+ my ($self) = @_;
+
+ # determine if the package had an ldconfig trigger
+ my $triggers = $self->processable->control->resolve_path('triggers');
+
+ my $we_trigger_ldconfig = 0;
+ $we_trigger_ldconfig = 1
+ if defined $triggers
+ && $triggers->decoded_utf8
+ =~ /^ \s* activate-noawait \s+ ldconfig \s* $/mx;
+
+ $self->hint('package-has-unnecessary-activation-of-ldconfig-trigger')
+ if !@{$self->must_call_ldconfig}
+ && $we_trigger_ldconfig
+ && $self->processable->type ne 'udeb';
+
+ $self->hint('lacks-ldconfig-trigger',
+ (sort +uniq @{$self->must_call_ldconfig}))
+ if @{$self->must_call_ldconfig}
+ && !$we_trigger_ldconfig
+ && $self->processable->type ne 'udeb';
+
+ return;
+}
+
+sub needs_ldconfig {
+ my ($self, $item) = @_;
+
+ # Libraries that should only be used in the presence of certain capabilities
+ # may be located in subdirectories of the standard ldconfig search path with
+ # one of the following names.
+ my $HWCAP_DIRS = $self->data->load('shared-libs/hwcap-dirs');
+ my @ldconfig_folders = @{$self->data->architectures->ldconfig_folders};
+
+ my $dirname = $item->dirname;
+ my $encapsulator;
+ do {
+ $dirname =~ s{ ([^/]+) / $}{}x;
+ $encapsulator = $1;
+
+ } while ($encapsulator && $HWCAP_DIRS->recognizes($encapsulator));
+
+ $dirname .= "$encapsulator/" if $encapsulator;
+
+ # yes! so postinst must call ldconfig
+ return 1
+ if any { $dirname eq $_ } @ldconfig_folders;
+
+ return 0;
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et