Няшная / Говнокод #27541 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
/* https://fstarlang.github.io/lowstar/html/Introduction.html#the-essence-of-low

Consider the following very simple program:

module Intro

module P = LowStar.Printf
module C = LowStar.Comment
module B = LowStar.Buffer

open FStar.HyperStack.ST
open LowStar.BufferOps

let main (): St Int32.t =
  push_frame ();
  let b: B.buffer UInt32.t = B.alloca 0ul 8ul in
  b.(0ul) <- 255ul;
  C.comment "Calls to printf are desugared via meta-programming";
  let s = "from Low*!" in
  P.(printf "Hello from %s\nbuffer contents: %xul\n"
    s 8ul b done);
  pop_frame ();
  0l

....

Once compiled by the KreMLin compiler, we obtain the following C code:
*/

int32_t main()
{
  uint32_t b[8U] = { 0U };
  b[0U] = (uint32_t)255U;
  /* Calls to printf are desugared via meta-programming */
  Prims_string s = "from Low*!";
  LowStar_Printf_print_string("Hello from ");
  LowStar_Printf_print_string(s);
  LowStar_Printf_print_string("\nbuffer contents: ");
  LowStar_Printf_print_lmbuffer_u32((uint32_t)8U, (uint32_t *)b);
  LowStar_Printf_print_string("\n");
  return (int32_t)0;
}

Какая-то компилируемая в сишку хренотень с завтипами, разрабатываемая в Microsoft Research

Запостил: j123123 j123123, (Updated )

Комментарии (66) RSS

  • Нахрен кстати им генерить какую-то там сишку, пусть бы сразу в какое-нибудь middle-end представление компилятора набрасывали (в Clang это LLVM-байткод, в GCC это байткод GIMPLE). Заодно пусть все оптимизации и трансформации докажут формально.
    Ответить
    • пусть сначало C# приложения в Native AOT компилировать научатся
      Ответить
      • ngen?

        Да, это не труъ AOT. Но приложухи после него вполне шустро работают.
        Ответить
        • Кстати, а почему он не труъ? Потому что на выходе не нормальный экзешник, а странная питушня из блоков кода, представленных как массив данных?
          Ответить
          • Потому что мутабельная рантайм рефлексия и прочие eval в труъ AOT невозможны?
            Ответить
            • разАОТится обратно если что, это же как с JIT
              Ответить
              • > разАОТится

                Ну вот... т.е. это скорее стартовый снепшот для JIT'а, чем нативный образ.
                Ответить
                • Теперь понял. Это кэш одного из возможных состояний (наиболее вероятного). Если нужно перейти к другому (к эвалам всяким), придётся переключаться обратно к честной интерпретации.

                  Кстати, а как реализована библиотека «Phobos» для языка «D»? Ну там всякие «std.functional», где код передаётся строками? Она в рантайме вызывает модуль для компиляции кода и инжектит сгенерированный код?

                  https://dlang.org/phobos/std_functional.html
                  Ответить
                  • В "D", если я не туплю, в рантайме ничего не генерится, это труъ конпелятор. Просто он умеет выполнять какое-то ограниченное подмножество "D" в компайлтайме и отдавать строки из mixin своему же парсеру.
                    Ответить
                    • Точно. Попробовал template compose, он в компайлтайме нагенерировал функций со страшными именами типа
                      __D3std10functional__T7composeVAyaa7_61202b20302e35SQBxQBw__TQBnVQBia15_746f2128696e7429286129202b2031S_D1b3fooFiZQDfZQDsZ__TQDzTiZQEfFiZd
                      Ответить
                    • Минимальный пример:
                      import std.stdio;
                      import std.functional;
                      
                      int main() {
                      	writeln(unaryFun!("a + 0.5")(1));
                      
                      	return 0;
                      }


                      Дизасм:
                      .text:00000384                 public __Dmain
                      .text:00000384 __Dmain         proc near
                      .text:00000384
                      .text:00000384 var_8           = qword ptr -8
                      .text:00000384
                      .text:00000384                 mov     eax, 1
                      .text:00000389                 call    __D3std10functional__T8unaryFunVAyaa7_61202b20302e35VQva1_61Z__TQBqTiZQBwFNaNbNiNfiZd
                      .text:0000038E                 sub     esp, 8
                      .text:00000391                 fstp    [esp+8+var_8]   ; double
                      .text:00000394                 call    __D3std5stdio__T7writelnTdZQlFNfdZv
                      .text:00000399                 xor     eax, eax
                      .text:0000039B                 retn
                      .text:0000039B __Dmain         endp ; sp-analysis failed
                      .text:0000039B
                      .text:0000039B _text           ends
                      
                                      public __D3std10functional__T8unaryFunVAyaa7_61202b20302e35VQva1_61Z__TQBqTiZQBwFNaNbNiNfiZd
                      .text:000003F8 __D3std10functional__T8unaryFunVAyaa7_61202b20302e35VQva1_61Z__TQBqTiZQBwFNaNbNiNfiZd proc near
                      .text:000003F8                                         ; CODE XREF: __Dmain+5p
                      .text:000003F8
                      .text:000003F8 var_4           = dword ptr -4
                      .text:000003F8
                      .text:000003F8                 enter   4, 0
                      .text:000003FC                 mov     [ebp+var_4], eax
                      .text:000003FF                 fild    [ebp+var_4]
                      .text:00000402                 fadd    ds:_TMP0
                      .text:00000408                 leave
                      .text:00000409                 retn
                      .text:00000409 __D3std10functional__T8unaryFunVAyaa7_61202b20302e35VQva1_61Z__TQBqTiZQBwFNaNbNiNfiZd endp


                      И ещё куча питушни для реализации writeln. Фактически writeln — это крестошаблон.
                      Ответить
            • Надо вернуться к использованию реального режима процессора: там самомодифицирующийся код был нормой.
              Ответить
              • > самомодифицирующийся код был нормой

                Да он и сейчас вполне норма... JIT'ы ведь работают.
                Ответить
                • В принципе, форматы «ELF» и «PE» позволяют создать секцию с атрибутами «rwx» и течь...
                  Ответить
                  • ...но не в самой лучшей в мире ОС

                    точнее создать можно, загрузить нельзя
                    Ответить
                    • В рантайме то потом можно выделить? Или там всякие js'ы на чистой интерпретации лагают?
                      Ответить
                      • JSам можно. Нужен спец ключ в заголовке ELF, чтоб разрешили, и такой файл нужно класть в спец место

                        В base system таких файлов нет
                        Ответить
                        • Сурово.

                          В винде такое только в ядре решились сделать.
                          Ответить
                          • Ну там это тоже не везде работает. В /usr/local можно срать rwx, иначе бы всякая джитня и правда не работала.
                            Ответить
                            • Джитня реализуема через переключения mprotect()-ом из "rw-" в "r-x". Можно и такое переключение запретить, но тогда надо и mmap с PROT_EXECUTE запретить, и dlopen запретить, и еще /proc/self/mem запретить, и execve запретить (ведь можно насрать байтиками в файл с нужными разрешениями и тупо запустить его)
                              Ответить
                              • > dlopen, execve

                                Ну тут достаточно запретить грузить файлы, которые не помечены как исполняемые. А дальше можно на уровне файлухи вырубить "x", а на файлухе с исполняемыми файлами отобрать у юзера "w" и хрен ты насрёшь байтиков в исполняемый файл.
                                Ответить
                                • > Ну тут достаточно запретить грузить файлы, которые не помечены как исполняемые.

                                  Надо еще убедиться в том, что нет таких готовых исполняемых файлов, которые можно было бы перезаписать.

                                  > дальше можно на уровне файлухи вырубить "x", а на файлухе с исполняемыми файлами отобрать у юзера "w"

                                  Их может допустим перезаписать какой-нибудь кривой говноскрипт, у которого будут такие права
                                  Ответить
                                  • > перезаписать какой-нибудь кривой говноскрипт

                                    Ну тут можно пойти дальше и через selinux запретить привилегированным процессам шариться по юзерским каталогам. Вообще. Всем. Ну кроме какой-нибудь бекапилки (но у неё можно отобрать write на систему) и тулов для управления юзерами (им достаточно delete и create, без чтения и записи обойдутся).

                                    В интеловских процах сейчас тоже такая фишка есть, кстати (SMAP и SMEP).
                                    Ответить
                                    • https://rdot.org/forum/showthread.php?p=39356
                                      >SMEP
                                      >Не позволяет процессору, будучи в ring0, выполнять код со страниц, помеченных флагом User.
                                      >Таким образом, столь привычные способы эксплуатации, когда есть возможность перезаписать указатель в какой-нибудь структуре в ядре адресом в юзер-моде, заммапить этот адрес и ждать, что ядро прыгнет на него исполнять наш шелл-код, перестают работать.
                                      >SMAP
                                      >Не позволяет процессору, будучи в ring0, обращаться (например, читать) к страницам, помеченным флагом User.
                                      >Поскольку ядру это необходимо в работе, были введены 2 новые инструкции, которые должны использоваться перед и после обращением к страницам памяти с флагом User: CLAC/STAC.
                                      >Использование SMAP незначительно увеличивает размер ядра и уменьшает скорость работы.

                                      Это вообще не об этом. Запретить что-то читать и писать на жесткий диск этим не выйдет

                                      Тут надо делать поеботину примерно как в KasperskyOS https://youtu.be/zUyllpPYpXY?t=746
                                      Ответить
                                      • > Это вообще не об этом

                                        Ну я про аналогию, что супер-юзер не может лезть к данным обычного юзера и исполнять его код. Суть уязвимостей ведь абсолютно такая же -- кривой привелигированный код без причины взял что-то у юзера и неаккуратно поюзал.
                                        Ответить
                                      • Кашпировский? Да ну нах

                                        > как создать безопасный промышленный шлюз
                                        На авито за 1000 рублей купить
                                        Ответить
                                        • > как создать безопасный промышленный шлюз

                                          На помойке найти
                                          Ответить
                                • У опёнка так примерно и сделано.

                                  Чтобы mmapнуть регион с W&X нужно иметь ключ в заголовке ELF

                                  Но с обычной FS такой бинарь не загрузится: нужно прикрутить FS со спец ключом

                                  Base system и home без такого ключа, так что там физически не может быть W&X

                                  А usr/local с таким ключом, так что в сёрд парти софте можно срать, но на продакшен сервере такого софта лучше не иметь

                                  Потому для SMTP, WWW, Perl, FTP и X11 у них свои сборки без W&X
                                  Ответить
                    • Я не могу запомнить, чем отличаются «Open», «Free» и «Net». Есть шпаргалка с различиями?
                      Ответить
                      • Open: повёрнутость на безопасности, отсутствие свистелок и пирделок (минимализм), много фишек для сети (CARP, качественный файрвол pf), очень хорошая документация в man.

                        Net: максимальная переносимость, RUMP kernel.

                        Free: максимально производительный сервер на x86, драйверов очень много, большое коммунити, хороший handbook.

                        DragonFly: максимальная многопоточность (раньше всех убрали локи в ядре чтобы использовать все ядра), своя файловая система похожая на ZFS

                        На сервере приложений логично иметь free, на роутере или бастионе Open. Остальное скорее академический интерес
                        Ответить
            • Так, походу я гоню и в дотнете нет таких фишек? Только новые классы можно нагенерить и загрузить, что совсем не будет мешать AOT'у?
              Ответить
              • Про какие фишки ты говоришь? Модификация MSIL в рантайме?


                А хотя какая разница, в любом случае дотнет говно, как впрочем и жаба.
                Ответить
                • Да, модификацию существующих классов и методов в рантайме. Новые то я и в крестах могу высрать при желании.
                  Ответить
                  • > Да, модификацию существующих классов и методов в рантайме
                    Ну CLR (он же MSIL) там модифицировать можно
                    https://www.codeproject.com/Articles/463508/NET-CLR-Injection-Modify-IL-Code-during-Run-time
                    И вот еще https://stackoverflow.com/questions/7299097/dynamically-replace-the-contents-of-a-c-sharp-method

                    > Новые то я и в крестах могу высрать при желании.
                    Ты и в крестах можешь mprotect-нуть сегмент с исполняемым кодом и переписать байтики опкодов в какой-то там функции и потом эту патченную хуйню исполнять.
                    Ответить
                    • > Ты и в крестах можешь

                      Хуй там... Откуда я знаю, куда ещё конпелятор заинлайнил и заанроллил код, который я хочу запатчить?

                      А новый класс будет через VMT взаимодействовать, там всё чисто.
                      Ответить
                      • > Хуй там... Откуда я знаю, что куда ещё конпелятор заинлайнил и заанроллил код, который я хочу запатчить?

                        Для этого просто нужен особый компилятор, который будет предсказуемым образом что-то инлайнить и анроллить по какой-то строгой спецификации.
                        Ответить
                        • Ну или хотя бы оставляет какие-то таблички с пометками куда и что он инлайнил.
                          Ответить
                    • > Ну CLR (он же MSIL) там модифицировать можно

                      Ну такое...

                      В одном варианте какие-то кишки рантайма/джита пинают чтобы переджитить заново, в другом варианте нативный jmp (sic!) патчат в джит-переходнике.

                      Может быть я невнимательно читала, но выглядит как ёбаные хаки.
                      Ответить
              • привет, в .net я могу сборку в рантайме загрузить
                Ответить
                • Я в Си тоже могу через dlopen-dlsym загрузить всякую фигню. Только bormand не про это спрашивала.
                  Ответить
                    • > Но это сломает AOT же.

                      Загрузка/генерация новых классов не ломает AOT. Старый скомпилированный код либо их вообще не увидит либо будет к ним обращаться через какие-то уже известные ему интерфейсы.
                      Ответить
                      • АОТ может заинлайнить что-то, думая что снаружи никто это трогать не будет

                        А новый класс потрогает. Да и старый может потрогать через рефлексию, и в этом случае оно разAOTится обратно кмк
                        Ответить
                        • А как это мешает?

                          Чтобы рефлексия работала я вижу джва варианта:

                          - Хранить в метаинфе для рефлексии ссылку на нативный метод. Тогда линкер его не удалит даже если все точки вызова заинлайнились и нам всегда будет что вызвать.
                          - Хранить в метаинфе оригинальный IL метода. Тогда его всегда можно воссоздать на лету и проинтерпретировать/заджитить.
                          Ответить
                          • Я думаю, что у них второй вариант, но это не точно
                            Ответить
                        • Хорошо что у меня в контроллерах нет всей этой хуйни
                          Ответить
                          • Честно говоря, если у меня на сервере или на ноутбуке это и есть, то меня это точно не ебёт.
                            Ответить
  • https://fstarlang.github.io/lowstar/html/Core.html#struct-types
    Struct types

    Flat records are part of the original paper formalization, and are translated as regular C structs.

    type uint128 = {
      low: UInt64.t;
      high: UInt64.t
    }


    typedef struct uint128_s
    {
      uint64_t low;
      uint64_t high;
    }
    uint128;


    In the original paper, structs may be allocated within buffers.

    let uint128_alloc (h l: UInt64.t): St (B.buffer uint128) =
      B.malloc HyperStack.root ({ low = l; high = h }) 1ul


    uint128 *uint128_alloc(uint64_t h, uint64_t l)
    {
      KRML_CHECK_SIZE(sizeof (uint128), (uint32_t)1U);
      uint128 *buf = KRML_HOST_MALLOC(sizeof (uint128));
      buf[0U] = ((uint128){ .low = l, .high = h });
      return buf;
    }


    Still in the original paper, one may access a buffer index, then select a number of fields.

    let uint128_high (x: B.buffer uint128): Stack UInt64.t
      (requires fun h -> B.live h x /\ B.length x = 1)
      (ensures fun h0 _ h1 -> B.live h1 x)
    =
      (x.(0ul)).high


    uint64_t uint128_high(uint128 *x)
    {
      return x->high;
    }
    Ответить
      • Ня порть высокие построения математической мысли своими грязными OOMами. В чистом мире математики лента машины Тьюринга бесконечня! ヽ(o^▽^o)ノ
        Ответить
        • Тогда еще надо чтоб бесконечное адресное пространство, чтоб указатели были бигинтами
          Только зачем тогда что-то выделять в бесконечном адресном пространстве, если всю хуйню можно в бигинте хранить?
          Ответить
          • Из адреса ячейки нельзя читать, его можно только для адресации использовать вроде
            Ответить
      • Нет, т.к. они не нужны. Ты бы ещё спросил, есть ли в «Nim» та питушня из «Rust».
        Ответить
        • Почему не нужны? А если я хочу на этапе компиляции проверять такую хуйню, что мне делать в случае с "Nim"?
          Ответить
  • Там ещё компилятор называется КРЕМЛИН, то есть гологубу бы не понравился такой язык. Да и мне тоже.
    Ответить
  • let b: B.buffer UInt32.t = B.alloca 0ul 8ul in

    Какой понятный синтаксис )))
    Ответить

Добавить комментарий

Семь раз отмерь — один отрежь, guest!

    А не использовать ли нам bbcode?


    8