gcc-7 toolchain triggers bug in build system causing non snmp drivers failing to be linked

Bug #1711092 reported by Christian Ehrhardt  on 2017-08-16
This bug affects 1 person
Affects Status Importance Assigned to Milestone
nut (Ubuntu)

Bug Description

It was building a week ago, so likely gcc7 as you expect, taking a look ...

View might first fall on:
al175.c:400:28: warning: ‘%2X’ directive output may be truncated writing between 2 and 4 bytes into a region of size between 3 and 5 [-Wformat-truncation=]

But that is only a warning due to:
-Wformat-truncation being default on -Wall now [1]

But the actual "break" are errors like:
/usr/bin/ld: al175.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC

Actually -fPIC was used on parts of the build pre and post gcc-7 as seen in the buildlogs [2] [3].
The root cause seems in a change that dropped the former:
options and replaced them with

Since no change was made to nut this likely is from the toolchain upgrade.
This is kind of inverse to what I knew - like [4] where it is about enabling pie.
Did we intentionally drop that - I don't think so?

When analyzing the build it seems there are two times hardning options.
- The first one got the no-pie spec
- And the second lost the -fPIE

--- old 2017-08-16 09:14:46.667114832 +0200
+++ new 2017-08-16 09:14:47.275115931 +0200
@@ -1,15 +1,15 @@
 gcc -DHAVE_CONFIG_H -I. -I../include -Wdate-time -D_FORTIFY_SOURCE=2 -I../include -DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -g -O2 -fdebug-prefix-map=/build/net-snmp=.
 -fstack-protector-strong -Wformat -Werror=format-security -DNETSNMP_USE_INLINE -Ulinux -Dlinux=linux -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fwrapv -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/lib/x86_64-linux-gnu/perl/5.2 -Wdate-time -D_FORTIFY_SOURCE=2 -I/usr/include -I/usr/include/neon -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=.
--fstack-protector-strong -Wformat -Werror=format-security -Wall -Wsign-compare -c -o al175.o al175.c
-/bin/bash ../libtool --tag=CC --mode=link gcc -I../include -DNETSNMP_ENABLE_IPV6 -fno-strict-aliasing -g -O2 -fdebug-prefix-map=/build/net-snmp=.

It almost seems to have two hardening entries one behaving one and one the other way.
I've found the source (form nut's POV) of both changes:
1. loosing -fPIE is the actual configure call changing from
CFLAGS="-g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fPIE -fstack-protector-strong [...]
CFLAGS="-g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong [...]
This can be checked when comparing zesty with artful calling:
$ DEB_BUILD_MAINT_OPTIONS=hardening=+all dpkg-buildflags --get CFLAGS
(Lets assume for now it is dropped because it is considered default anyway?)

2. gaining the no-pie spec is from net-snmp by configure
checking for Net-SNMP cflags... [...] -specs=/usr/share/dpkg/no-pie-compile.specs [...]
checking for Net-SNMP libs... [...] -specs=/usr/share/dpkg/no-pie-compile.specs [...]
While in the past this was without pie reference at all.

The options of #2 come later than #1 and so even if #1 would have -fPIE it would be disabled again.
The real source for the change in #2 is actually outside of the nut package.
On its build it wants to build a net-snmp plugin and to do so gets the build options that used.
And a change from zesty [5] to artful [6] is to add the -specs=/usr/share/dpkg/no-pie-compile.specs and the ld equivalent.

The source for that is there since a long time (2013), in d/rules of net-snmp:
  # without -pie build fails during perl module build somehow...
  export DEB_BUILD_MAINT_OPTIONS := hardening=+all,-pie

There is also a "-specs=/usr/share/dpkg/no-pie-link.specs" for the linker.
And in fact that should be used, so in the linking call replacing no-pie-compile.specs with no-pie-link.specs makes the link work (and seems more correct).

Of course that is hidden in auto-generated makefiles, so debug there if a reasonable way to make the (properly detected) net-snmp lib flags appear.

These (correct) flags are used in:
snmp-ups$(EXEEXT): $(snmp_ups_OBJECTS) $(snmp_ups_DEPENDENCIES) $(EXTRA_snmp_ups_DEPENDENCIES)
        @rm -f snmp-ups$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(snmp_ups_OBJECTS) $(snmp_ups_LDADD) $(LIBS)

But they are missing on the failing object which has:
        @rm -f al175$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(al175_OBJECTS) $(al175_LDADD) $(LIBS)

The reason is that there is a mis-assumption in the makefile:
# Avoid per-target CFLAGS, because this will prevent re-use of object
# files. In any case, CFLAGS are only -I options, so there is no harm,
# but only add them if we really use the target.
AM_CFLAGS = -I$(top_srcdir)/include $(am__append_1) $(am__append_2) \
        $(am__append_3) $(am__append_4) $(am__append_5)

In am__append_2 are the cflags which carry "no-pie-compile.specs" but on the link stage they only propagate to the target that matters (snmp_ups).

That mismatch causes the breakage as CFLAGS are not "In any case, CFLAGS are only -I options, so there is no harm".

Launchpad Janitor (janitor) wrote :

This bug was fixed in the package nut - 2.7.4-5ubuntu4

nut (2.7.4-5ubuntu4) artful; urgency=medium

  * d/p/fix-snmp-driver-compile-options.patch: fix cflags/ldflags
    mismatch (LP: #1711092).
  * d/libnutclient0.symbols: fix symbols in regard to gcc-7 (LP: #1711091).

 -- Christian Ehrhardt <email address hidden> Wed, 16 Aug 2017 12:44:26 +0200

Changed in nut (Ubuntu):
status: New → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers