ld64 segprot на MacOS Catalina не работает?

Я хочу создать двоичный файл в MacOS Catalina (64 бит) с сегментом данных, который можно сделать исполняемым (см. здесь для подробностей), но с самого начала не исполняется.

Я делаю свой двоичный файл с

gcc -nostdlib -segprot __DATA rwx rw- .... 

Я также создал объектный файл с помощью gcc, а затем напрямую вызвал ld. Версия ld

$ ld -v
@(#)PROGRAM:ld  PROJECT:ld64-530
BUILD 18:57:17 Dec 13 2019
configured to support archs: armv6 armv7 armv7s arm64 arm64e arm64_32 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em
LTO support using: LLVM version 11.0.0, (clang-1100.0.33.17) (static support for 23, runtime is 23)
TAPI support using: Apple TAPI version 11.0.0 (tapi-1100.0.11)

Это должно сделать сегмент данных изначально RW, но позвольте мне использовать mprotect для расширения разрешений в этом сегменте на RWX.

Однако я заметил, что сегмент __DATA является RW для начального и максимального разрешения:

$ otool -l jonesforth
.
.
.
Load command 2
      cmd LC_SEGMENT_64
  cmdsize 312
  segname __DATA
   vmaddr 0x0000000100001000
   vmsize 0x0000000000024000
  fileoff 4096
 filesize 4096
  maxprot 0x00000003
 initprot 0x00000003
   nsects 3
    flags 0x0
Section
.
.
.

Что-то мне не хватает? Документация darwin здесь говорит:

-segprot name max init (32-bit only)

              Specifies the maximum and initial virtual memory  protection  of
              the  named segment, name, to be max and init ,respectively.  The
              values for max and init are any combination  of  the  characters
              `r'  (for  read), `w' (for write), `x' (for execute) and '-' (no
              access).  The default is `rwx' for the  maximum  protection  for
              all segments for PowerPC architecures and `rw` for the all Intel
              architecures.  The default for the initial  protection  for  all
              segments  is  `rw'  unless  the segment contains a section which
              contains some machine instructions, in which  case  the  default
              for  the initial protection is `rwx' (and for Intel architecures
              it also sets the maximum protection to `rwx' in this case).  The
              default for the initial protection for the ``__TEXT'' segment is
              `rx' (not writable).

Конечно, это документация Дарвина (только 32-битная), но это единственное, что я нашел. Я подозреваю, что либо gcc «неправильно» поддерживает синтаксис защиты darwin, либо он сломан, либо что-то в darwin изменилось с x86 на x64.

Любые указатели были бы замечательными, заранее спасибо.


person Klapaucius Klapaucius    schedule 28.05.2020    source источник
comment
Примечание. Я попытался использовать gcc для компиляции и явно вызвал компоновщик apple clang (ld) с теми же результатами. Возможно ли, что компоновщик x64 изменил поведение segprot?   -  person Klapaucius Klapaucius    schedule 28.05.2020
comment
О боже, ты прав - я неправильно прочитал этот код. Есть ли у вас какое-нибудь представление о том, сделано ли это изменение намеренно? Возможно, это было непреднамеренно, учитывая, что на странице руководства все еще четко указано, что ld может принимать maxprot и initprot.   -  person Klapaucius Klapaucius    schedule 29.05.2020
comment
Я считаю, что это часть постоянных усилий Apple по усилению безопасности macOS, но у меня нет источника. Apple также использует только внутреннюю систему ошибок, поэтому я не могу определить, выразили ли они какое-либо мнение по этому поводу.   -  person Elliott Darfink    schedule 29.05.2020
comment
Если вам интересно, я написал сценарий Python, который заменяет ld. Он обертывает ld и применяет max_prot к любому segprot аргументу после связывания: gist.github.com/darfinkbbeef2d3/darfink/a756ee а>   -  person Elliott Darfink    schedule 29.05.2020
comment
Очень круто, я могу подтвердить, что у меня это хорошо работает. Что касается Apple ужесточения безопасности, я на самом деле не покупаю это, потому что это просто более или менее заставляет меня сделать весь сегмент данных rwx (что ld64 может сделать, по крайней мере, на данный момент), а не только четвертые определения. OTOH, на самом деле это не добавляет безопасности для снятия защиты только части сегмента данных, потому что четвертый компилятор может просто выполнить необходимые вызовы mprotect, чтобы снять защиту всего сегмента __DATA для maxprot. Если вы не возражаете, я завершу это ответом и процитирую ваш скрипт python.   -  person Klapaucius Klapaucius    schedule 29.05.2020
comment
Да, согласен, в вашем случае это снижение безопасности. Но когда дело доходит до сегмента __TEXT, вы не можете установить его в rwx (Каталина отказывается выполнять файлы с доступным для записи сегментом __TEXT). Следовательно, это изменение предотвращает использование обходных путей / перехвата кода (например, изменение активного кода в __TEXT), что, возможно, усиливает безопасность. Звучит неплохо! Надеюсь, Apple представит нам лучшее решение.   -  person Elliott Darfink    schedule 29.05.2020
comment
Эллиот, для этого и предназначено право com.apple.security.cs.disable-executable-page-protection?   -  person Klapaucius Klapaucius    schedule 29.05.2020


Ответы (1)