Page MenuHome GnuPG

[PATCH] qt libraries should be linked with -fPIC instead of -fpic
Closed, WontfixPublic

Description

Hello, this is an example of failure during configure step

configure:19582: checking whether a simple qt program can be built
configure:19593: g++ -o conftest -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/i386-gnu/qt5/QtCore -I/usr/include/i386-gnu/qt5 -fpic -specs=/usr/share/dpkg/pie-link.specs -Wl,-z,relro -Wl,-z,now conftest.cpp -lQt5Core >&5
In file included from /usr/include/i386-gnu/qt5/QtCore/qcoreapplication.h:43:0,
                 from /usr/include/i386-gnu/qt5/QtCore/QCoreApplication:1,
                 from conftest.cpp:32:
/usr/include/i386-gnu/qt5/QtCore/qglobal.h:1113:4: error: #error "You must build your code with position independent code if Qt was built with -reduce-relocations. " "Compile your code with -fPIC (-fPIE is not enough)."
 #  error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\

and this is a trivial patch that fixes the problem in Debian and Ubuntu, where pie is default

Description: Use -fPIC instead of -fpic.
Author: Adam Conrad <adconrad@ubuntu.com>
Last-Update: 2017-05-12

Index: gpgme1.0-1.8.0/m4/qt.m4
===================================================================
--- gpgme1.0-1.8.0.orig/m4/qt.m4
+++ gpgme1.0-1.8.0/m4/qt.m4
@@ -24,8 +24,9 @@ AC_DEFUN([FIND_QT],
                     [have_qt5test_libs="no"])
 
   if ! test "$have_w32_system" = yes; then
+    GPGME_QT_CFLAGS="$GPGME_QT_CFLAGS -shared"
     if "$PKG_CONFIG" --variable qt_config Qt5Core | grep -q "reduce_relocations"; then
-      GPGME_QT_CFLAGS="$GPGME_QT_CFLAGS -fpic"
+      GPGME_QT_CFLAGS="$GPGME_QT_CFLAGS -fPIC"
     fi
   fi
   if test "$have_qt5_libs" = "yes"; then

please have a look at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=870383 for more information and background!

thanks!

Gianfranco

Event Timeline

werner renamed this task from [PATCH] qt libraries should be linked with -fPIC instead of -fPIC to [PATCH] qt libraries should be linked with -fPIC instead of -fpic.Jun 29 2020, 7:53 PM
gniibe added a project: Info Needed.
gniibe added a subscriber: gniibe.

Thanks for your report.

However, I don't think it is a bug of upstream (gpgme). IIUC, it was (around the days of https://wiki.debian.org/Hardening/PIEByDefaultTransition on hurd-i386) caused by some mis-configuration of PIE which was/is forced by dpkg's -specs=/usr/share/dpkg/pie-compile.specs.
IIUC, the problem has gone (on hurd-i386 as well), as far as I can see the build log.

Now, PIE is not enabled when -fpic or -fPIC is used.

And... I don't think the patch is right.

Perhaps, changing -fpic to -fPIC indeed might "fix" the problem on the machine at that time, but, it was because of buggy configuration, I believe.

Please see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=879014, too.

gniibe triaged this task as Normal priority.Jun 30 2020, 4:35 AM

I think that it is the problem of dpkg to override the compiler flag by the spec file. When compiler default is -fPIE, it works well. If not (for the case of x32), it fails.
In the past, hurd-i386 had same issue, but compiler default seems to be now -fPIE, thus no problem.

There's nothing we (upstream) can do here.

So, if no problem, I'd like to close this bug report as invalid.

This comment was removed by gniibe.
dkg added a subscriber: dkg.

I'm still not understanding what specifically should be fixed here. Sorry to be dense about it, but the range of options and configuration details that are different are pretty puzzling.

Can you help me understand what the issue is? Should we be asking gcc maintainers to change the defaults? dpkg to ship a different spec file? dpkg to use the spec file in a different way? overriding standard build processes in debian specifically for gpgme? changing how Qt itself is built in debian?

I'm fine with closing this bug report as invalid, but i'd appreciate any help in figuring out what the right resolution actually is.

Here is my understanding. My point is it's not problem of gpgme. To fix it correctly, I think that dpkg should be fixed and it would be needed to fix Qt too.

(0-1) First of all, I don't think the patch (replacing -fpic by -fPIC) is relevant. Please see GCC manual about -fpic and -fPIC.
(0-2) Second of all, I think that Qt's error message is confusing. If the header file condition is correct, it should say "Compile your code with -fPIC and not with -fPIE". The part in question is:

#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && \
    (!defined(__PIC__) || (defined(__PIE__) && defined(Q_CC_GNU) && Q_CC_GNU >= 500))
#  error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
         "Compile your code with -fPIC (-fPIE is not enough)."
#endif

I mean, it fails when -fPIE is provided even if -fpic (or -fPIC) is provided.
(1) For hardening, when pie is enabled, dpkg pushes spec file to enable PIE, using /usr/share/dpkg/pie-compiler.specs and /usr/share/dpkg/pie-link.specs. This works sometimes, yes, most of cases, but for x32 (or hurd-i386 in the past) which gcc default is not PIE enabled, it fails gpgme build at configure.
(2) In the part of gpgme configure script, gpgme build process just tests Qt application can be build or not.
(3) gpgme process adds -fpic when it detects Qt is build with reduce-relocation. This is how Qt application should be built.

Quoting the log, it is:

configure:19755: g++ -o conftest -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/x86_64-linux-gnux32/qt5/QtCore -I/usr/include/x86_64-linux-gnux32/qt5 -fpic -specs=/usr/share/dpkg/pie-link.specs -Wl,-z,relro -Wl,-z,now conftest.cpp -lQt5Core >&5
In file included from /usr/include/x86_64-linux-gnux32/qt5/QtCore/qcoreapplication.h:43:0,
                 from /usr/include/x86_64-linux-gnux32/qt5/QtCore/QCoreApplication:1,
                 from conftest.cpp:32:
/usr/include/x86_64-linux-gnux32/qt5/QtCore/qglobal.h:1135:4: error: #error "You must build your code with position independent code if Qt was built with -reduce-relocations. " "Compile your code with -fPIC (-fPIE is not enough)."
 #  error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
    ^~~~~
configure:19755: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "gpgme"
| #define PACKAGE_TARNAME "gpgme"
| #define PACKAGE_VERSION "1.9.0"
| #define PACKAGE_STRING "gpgme 1.9.0"
| #define PACKAGE_BUGREPORT "http://bugs.gnupg.org"
| #define PACKAGE_URL ""
| #define PACKAGE "gpgme"
| #define VERSION "1.9.0"
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define __EXTENSIONS__ 1
| #define _ALL_SOURCE 1
| #define _GNU_SOURCE 1
| #define _POSIX_PTHREAD_SEMANTICS 1
| #define _TANDEM_SOURCE 1
| #define PACKAGE "gpgme"
| #define VERSION "1.9.0"
| #define HAVE_DLFCN_H 1
| #define LT_OBJDIR ".libs/"
| #define HAVE_CXX11 1
| /* end confdefs.h.  */
| 
|     #include <QCoreApplication>
|     int main (int argc, char **argv) {
|     QCoreApplication app(argc, argv);
|     app.exec();
|     }

To reproduce it, using

, we can check like:

FAILURE:

$ g++ -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 -specs=/usr/share/dpkg/pie-link.specs -Wl,-z,relro -Wl,-z,now conftest.c -fpic -E -dM | grep -E -i -e  '(pic|pie)'

NO PROBLEM:

$ g++ -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 -Wl,-z,relro -Wl,-z,now conftest.c -fpic -E -dM | grep -E -i -e  '(pic|pie)'

NO PROBLEM:

$ g++ -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 -specs=/usr/share/dpkg/pie-link.specs -Wl,-z,relro -Wl,-z,now conftest.c -fpic -no-pie -E -dM | grep -E -i -e  '(pic|pie)'

My interpretation of those three tests above is:

  • dpkg doesn't support use case of building an executable by single invocation of gcc(g++) (compile and link at once).
  • Build by two steps works:
$ g++ -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 conftest.c -fpic -c
$ g++ -fstack-protector-strong -Wformat -Werror=format-security --specs=/usr/share/dpkg/pie-link.specs -Wl,-z,relro -Wl,-z,now conftest.o -fpic -o a.out -lQt5Core

on #debian-dpkg on IRC, Guillem Jover suggested that we might want to fix dpkg specfiles to use +self_spec: instead of *self_spec:.

To test this, i put conftest.c (from above) in a test directory on an amd64 (x86_64) machine, and supplemented it with:

mkdir from-dpkg
cp /usr/share/dpkg/pie-{compile,link}.specs ./from-dpkg/

I get a failure when i try to use gniibe's test command:

$ g++ -specs=./from-dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 -specs=./from-dpkg/pie-link.specs -Wl,-z,relro -Wl,-z,now ./conftest.c -fpic -E -dM | grep -E -i -e  '(pic|pie)'
In file included from /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h:43,
                 from /usr/include/x86_64-linux-gnu/qt5/QtCore/QCoreApplication:1,
                 from Downloads/conftest.c:32:
/usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h:1187:4: error: #error "You must build your code with position independent code if Qt was built with -reduce-relocations. " "Compile your code with -fPIC (-fPIE is not enough)."
 1187 | #  error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
      |    ^~~~~
#define __PIC__ 2
#define __pie__ 2
#define __pic__ 2
#define __PIE__ 2
$

Then following Guillem's suggestion, i tried modifying *self_spec: to +self_spec: in the two specfiles and recompiled pointing at those updated files:

$ mkdir fixed
$ for x in compile link; do sed 's/^\*self_spec:$/+self_spec:/' < from-dpkg/pie-$x.specs > fixed/pie-$x.specs; done
$ g++ -specs=./fixed/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 -specs=./fixed/pie-link.specs -Wl,-z,relro -Wl,-z,now ./conftest.c -fpic -E -dM | grep -E -i -e  '(pic|pie)'
#define __PIC__ 1
#define __pic__ 1
$ 

Does this look like the fix we need? I can formally report it to dpkg if that's the case.

Yes, it will fix the problem on x32, I suppose.
If it's difficult for dpkg, for some reason for now, workaround for gpgme packaging is disabling pie hardening for x32 until pie will be its compiler default.
For gpgme, it is only test binaries which matter (pie or not), so, the impact (for x32) is minimum.

To summarize:

  • Qt has peculiar requirement for building application with -fpic/-fPIC (and no -fPIE) when Qt is built with the option reduce_relocations; Since -fpic/-fPIC requests position independent code generation for shared object, having -fpic/-fPIC for executable is considered a kind of out of ELF spec. But anyway, it's Qt's (current) way.
  • gpgme checks Qt application can be build or not with -fpic (for reduce_relocations).
  • When compiler default is not pie, dpkg hardening pushes its own spec, it mostly works, but it doesn't work well in the corner case of the build process of gpgme.

BTW, I wonder if it would be better to have Qt5Core.pc to have -fpic for cflags.

werner added a subscriber: werner.

We can't do anything about it except for corner cases which we won't do right now. In case there will be an easy solution to help Debian please re-open this bug.