LINUX.ORG.RU

По какой причине clang собирает pie executable вместо shared object ?

 ,


3

4

Вот мой код:

$ cat library.h 
#ifndef __LIBRARY_H__
#define __LIBRARY_H__

int hello_world();

#endif // __LIBRARY_H__

$ cat library.c 
#include "library.h"

int hello_world()
{
	return 42;
}

$ cat main.c 
#include 
#include "library.h"

int main(int argc, char** argv)
{
	int res = hello_world();
	printf ("%d\n", res);
	return 0;
}

Собираю командами:

$ cat build.sh 
#!/bin/bash

clang -shared -nostdlib library.c -o library.so
clang -L ./ library.so main.c

Запускаю
LD_LIBRARY_PATH=. ./a.out

проблема в том, что
$ file library.so
library.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, not stripped

а должен быть не pie executable

проблема в том, что

Ты всецело доверяешь результату, который выдаёт file, вместо того, чтобы попытаться осознать, если ли вообще проблема.

GCC, кстати, аналогичный результат выдаст, так что дело тут вовсе не в Clang.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)
Ответ на: комментарий от i-rinat

GCC, кстати, аналогичный результат выдаст, так что дело тут вовсе не в Clang.

потому что

[viper@viper-manjaro ~]$ gcc -v | grep  -enable-default-pie
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp --enable-cet=auto
Thread model: posix
gcc version 8.2.1 20180831 (GCC) 

отключается через -no-pie. в шланге видимо аналогичная опция.

vvviperrr ★★★★★
()
Ответ на: комментарий от Deleted

Вот я тоже заметил. Прям интересно оп как-то собирает

deadplace
()
Ответ на: комментарий от Einstok_Fair

что ты на это скажешь

Скажу, что знаю, как сделать так, чтобы компилятор сгенерил so-шку, про которую file скажет, что это shared object. Но тебе, Indaril, я телефон не скажу. :-D

i-rinat ★★★★★
()
Ответ на: комментарий от Deleted

Это в википедии написано, на странице
https://en.wikipedia.org/wiki/Position-independent_code

цитирую:

Gentoo's new profiles now support PIE by default.

Я пробовал собирать командами
clang -shared -fPIC library.c -o library.so
clang -shared -fPIC -nostdlib -fno-pie library.c -o library.so
clang -shared -fPIC -Wl,-PIC library.c -o library.so
clang -shared -fPIC -nostdlib -Wl,-PIC library.c -o library.so
clang -shared -fPIC -Wl,-shared -Wl,-fPIC library.c -o library.so
clang -shared -fPIC -Wl,-shared -Wl,-fPIC -nostdlib library.c -o library.so

ничего не меняется.

Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 3)
Ответ на: комментарий от anonymous

-nostdlib ломает динамическую либу.

я пробовал и без этого ключа.
Файл только больше по размеру становится, а пользы никакой.

pie от shared library сложно отличить.

значит надо в library что-нибудь добавить, чтобы отличить стало можно. Но я пока не понимаю - что именно.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от pon4ik

а должен быть не pie executable

Обоснуй.

Обосновываю:
1) существуют такие .so файлы, для которых команда file выдаёт «shared object»
2) я хочу получить такой же
3) это становится моим требованием к программе
4) возникает вопрос, как этого добиться
5) я создаю топик с таким вопросом
6) набигают какие-то люди, которые не понимают вопроса, делают неправильные выводы, замусоривают топик
7) вопрос остаётся неотвеченным

Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 1)
Ответ на: комментарий от i-rinat

если ли вообще проблема.

да, проблема в том, что я не понимаю, что сделать, чтобы результат, который выдаёт file, был другим.

Это проблема. Она есть.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от pon4ik

ты туда __start влинковываешь, ха.

нет:

$ ld library.so
ld: warning: cannot find entry symbol _start; not setting start address

Einstok_Fair ★★☆
() автор топика
$ file lib.so 
lib.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, stripped

$ chmod -x lib.so
$ file lib.so 
lib.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped
KennyMinigun ★★★★★
()
Ответ на: комментарий от Einstok_Fair
executable => pe => elf

По идее, современные линковщики в условиях включенного под дефолту aslr не должны по дефолту выдавать не pie бинари.

Про то, что main в main.c не увидал, да.

pon4ik ★★★★★
()
Ответ на: комментарий от Einstok_Fair

Хз. Никогда меня ни разу не парило, что сошку что-то там считает выполняемым файлом, грань так тонка... Тем более, в терминах ld это и не совсем so, а именно pie:

LC_ALL=C man ld | grep '\-pie' -A 10
pon4ik ★★★★★
()
Ответ на: комментарий от Deleted

С тех пор, как самому сопливому мамкиному какеру стали доступны metasploit и прочий sploit database.

Даже в 6ой центоси вроде по дефолту включены ганарейки и aslr.

pon4ik ★★★★★
()
Ответ на: комментарий от Einstok_Fair
-f.* - флаги генерации кода

А флаги линковки идут без префикса 'f'. Чет я в своём man ld не нашёл no-pie... Может огорожено от любителей шерета?

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

моя текущая версия:
clang -v -shared -fPIC -fno-PIE -Wl,-PIC,-no-PIE -nostdlib library.c -o library.so

при сборке ругается на библиотеку «library-b41bb1.o»
/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../../../x86_64-pc-linux-gnu/bin/ld: /tmp/library-b41bb1.o: relocation R_X86_64_32S against symbol `global_variable' can not be used when making a shared object; recompile with -fPIC

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

Ну правильно ругается, нельзя влинковать архив в шарную либу если код в нём не pic.

Pic - код который не зависит от своего местоположения.

Pie - бинарник, который не зависит от местоположения своих секций.

Вот тут, тип упражняется по всякому.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от pon4ik

Я задаю PIC и задаю no-PIE для компилятора, и потом для линкера.
Мне кажется, что нельзя сказать, что у меня объектник без pic.

Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 1)
Ответ на: комментарий от Einstok_Fair

Даже интересно стало, хм, а если так:

clang -v -shared -fPIC -Wl,-no-PIE library.c -o library.so

Это первый момент.

А второй момент - каков выхлоп readelf?

LC_ALL=C readelf -h library.so
pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik
$ clang -v -shared -fPIC -Wl,-no-PIE library.c -o library.so
clang version 7.0.0 (tags/RELEASE_700/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm/7/bin
Selected GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
 "/usr/lib64/llvm/7/bin/clang-7" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name library.c -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -v -resource-dir /usr/lib64/llvm/7/bin/../../../../lib/clang/7.0.0 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/llvm/7/bin/../../../../lib/clang/7.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /home/user/test1 -ferror-limit 19 -fmessage-length 154 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -o /tmp/library-383a72.o -x c library.c -faddrsig
clang -cc1 version 7.0.0 based upon LLVM 7.0.0 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib64/llvm/7/bin/../../../../lib/clang/7.0.0/include
 /usr/include
End of search list.
 "/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../../../x86_64-pc-linux-gnu/bin/ld" --eh-frame-hdr -m elf_x86_64 -shared -o library.so /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../../../lib64 -L/usr/lib64/llvm/7/bin/../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../.. -L/lib -L/usr/lib -no-PIE /tmp/library-383a72.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../../../lib64/crtn.o
/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.0/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
clang-7: error: linker command failed with exit code 1 (use -v to see invocation)

если добавить -nostdlib, то создаётся файл с именем
-PIE

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

Забавно, а если всё тоже самое провернуть gcc?

При сборке с pie - будет ли file ругать соху executable? И не будет ли без?

Коли так, дальше видимо надо смотреть как file их различает.

pon4ik ★★★★★
()
Ответ на: комментарий от Einstok_Fair

смотри

$ file libsample.so 
libsample.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=96360930c904ed7577626dd47f0fa8995cd821e7, stripped
$ chmod a+x libsample.so 
$ file libsample.so 
libsample.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=96360930c904ed7577626dd47f0fa8995cd821e7, stripped
$ 

Круто, да?

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

ну ты-то такое решение не нашел. Ты сейчас всё что угодно можешь говорить, но доказать что ты его знал уже невозможно, после того, как ты это тут прочёл.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от i-rinat

Кстати, дело не в флаге +x.

Обнаружил либы, которые выполняемые,
но при этом команда file показывает на них «shared object»

$ ls -l libKF5UnitConversion.so.5.51.0
-rwxr-xr-x 1 root root 399328 окт 20 23:05 libKF5UnitConversion.so.5.51.0

$ file libKF5UnitConversion.so.5.51.0 
libKF5UnitConversion.so.5.51.0: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, stripped
Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 1)
Ответ на: комментарий от Einstok_Fair

ну ты-то такое решение не нашел. Ты сейчас всё что угодно можешь говорить, но доказать что ты его знал уже невозможно, после того, как ты это тут прочёл.

А надо было, что ли? Я думал, мы тут над твоей ленью глумимся.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Я думал, что для того, чтобы file начала понимать, там должна быть таблица, и если её нет - это вырожденный случай.

Сделал ещё одну функцию, теперь таблица есть:

$ readelf --relocs library.so 

Relocation section '.rela.plt' at offset 0x298 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000201018  000400000007 R_X86_64_JUMP_SLO 00000000000002d0 internal_function + 0

но это не помогло.

Einstok_Fair ★★☆
() автор топика

https://bugs.launchpad.net/ubuntu/+source/file/+bug/1747711

Если кратко, то в утилите file починили одно и сломали другое.

Насколько я знаю, с точки зрения формата ELF, чёткой границы между executable и shared library просто нет.

проблема в том, что

никакой проблемы нет.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

никакой проблемы нет.

У тебя нет.
А у меня есть - проблема понимания (или непонимания).

Для решения моей проблемы я задаю вопросы. Спасибо.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

А у меня есть - проблема понимания (или непонимания).

Почитай что написано по ссылке. Проблема не в том, что ты неправильно что-то собираешь, а в утилите file.

Deleted
()
Ответ на: комментарий от Deleted

хорошо. Пусть проблема в утилите file. Пусть есть рекомендация и настройка по умолчанию для того, чтобы выполняемые файлы были PIE.

Правильно ли я понимаю, что для того, чтобы собрать не PIE файл .so мне нужно взять старый или специально собранный gcc?

Т.е. как собрать не PIE-файл?

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

PIE == position-independent EXECUTABLE. Ты уже собираешь не executable, так что у тебя 100% не PIE. file просто врёт тебе.

Deleted
()
Ответ на: комментарий от Deleted

clang ещё ставит флаг +x. Значит он солидарен с file в том, что всё-таки не библиотеку он собирает.

Это напрягает, и просто кричит о том, что что-то не так.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от anonymous

он сам приполз.

gcc-config -l
 [1] x86_64-pc-linux-gnu-4.9.3
 [2] x86_64-pc-linux-gnu-4.9.3-hardenednopie
 [3] x86_64-pc-linux-gnu-4.9.3-hardenednopiessp
 [4] x86_64-pc-linux-gnu-4.9.3-hardenednossp
 [5] x86_64-pc-linux-gnu-4.9.3-vanilla
 [6] x86_64-pc-linux-gnu-5.4.0
 [7] x86_64-pc-linux-gnu-5.4.0-hardenednopie
 [8] x86_64-pc-linux-gnu-5.4.0-hardenednopiessp
 [9] x86_64-pc-linux-gnu-5.4.0-hardenednossp
 [10] x86_64-pc-linux-gnu-5.4.0-vanilla
 [11] x86_64-pc-linux-gnu-6.4.0 *
Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 1)
Ответ на: комментарий от Einstok_Fair

капец, а зачем тебе 11 штук gcc?)

Тебе не програмированием нужно заняться, а поудалять барахло с диска.

anonymous
()
Ответ на: комментарий от anonymous

зачем тебе 11 штук gcc?)

Я исповедую принцип «не сломалось - не чини», сколько сообщество решило иметь целесообразным, столько у меня и стоит.
И удалять я ничего не буду, а то вдруг что-нибудь сломается...

сделай emerge -avc --with-bdeps=y

Зачем/с какой целью? У меня основной пакетный менеджер equo

и eclean-dist -d

У меня нет проблем с местом на диске, и мне безразлично, что лежит в /usr/portage/distfiles

А вот проблема со сборкой библиотеки - реальная проблема. Классно, конечно, что умеешь ты пересказывать, но сейчас вышло не к месту.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Deleted

Давно уже все бинари собирают как pie из-за секурити мартышек.

anonymous
()
Ответ на: комментарий от Einstok_Fair

clang ещё ставит флаг +x. Значит он солидарен с file в том, что всё-таки не библиотеку он собирает.

Это напрягает, и просто кричит о том, что что-то не так.

Мне стало интересно.

Как минимум на моей системе, clang использует ld из gnu binutils для получения конечных бинарников. И именно ld делает chmod("...", 0777). Я потыкал в него отладчиком и посмотрел в исходники. Вот эта функция из $BINUTILS_SRC/bfd/opncls.c:

static inline void
_maybe_make_executable (bfd * abfd)
{
  /* If the file was open for writing and is now executable,
     make it so.  */
  if (abfd->direction == write_direction
      && (abfd->flags & (EXEC_P | DYNAMIC)) != 0)
    {
      struct stat buf;

      if (stat (abfd->filename, &buf) == 0
          /* Do not attempt to change non-regular files.  This is
             here especially for configure scripts and kernel builds
             which run tests with "ld [...] -o /dev/null".  */
          && S_ISREG(buf.st_mode))
        {
          unsigned int mask = umask (0);

          umask (mask);
          chmod (abfd->filename,
                 (0777
                  & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
        }
    }
}
Не смотря на комменты вида «If the created file is executable, then <<chmod>> is called to mark it as such.», она вызывается всегда, если не произошла ошибка. Ну либо я слепой и не вижу других путей.

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.