TL;DR Можно уместить полноценный Linux Live дистрибутив в один файл, если вкомпилировать в ядро initramfs с корневой файловой системой. Компьютеры с UEFI умеют загружать такой файл напрямую, без помощи загрузчика типа GRUB. У меня получилось уместить дистрибутив с программами aircrack-ng, reaver и драйверами для карт Wi-Fi в файл размером 12 мегабайт (наверняка можно еще меньше).

Основные преимущества


  • Работает на любых компьютерах с UEFI — один и тот же файл будет работать на PC и Mac.
  • Не требует установки — достаточно скопировать один файл на EFI-раздел диска и указать в переменных NVRAM путь к этому файлу.
  • Не нужно устанавливать загрузчики GRUB, rEFInd — ядро Linux собранное с поддержкой EFI Stub можно грузить напрямую без промежуточного загрузчика.
  • Не нужны USB-флешки — скопированный на раздел EFI дистрибутив остается там навсегда, и его можно будет загрузить в любой момент. Он не занимает места на разделе основной системы, так как раздел EFI не используется в ОС.
  • Не изменяет процесс загрузки — систему можно загрузить один раз, без изменения порядка загрузки в настройках UEFI. Следующая перезагрузка компьютера загрузит обычную операционную систему. Никаких следов Linux в очередности загрузки не останется.
  • Совместимо с шифрованием диска FileVault и т.д. — файл копируется на EFI System Partition, специальный зарезервированный раздел диска. В компьютерах Mac его размер около 200 мегабайт. Он выделен под Boot Camp и обычно не используется

Зачем это нужно?


Для всех случаев, когда нужен нативный Linux без виртуальной машины.
Чтобы использовать PCIe-устройства в Linux, когда их нельзя прокинуть в виртуальную машину. Например, встроенную Wi-Fi-карту для инъекции пакетов. Когда лень устанавливать виртуальную машину и качать большой ISO файл с дистрибутивом. Когда не хочется возиться с USB флешками.
Единожды скопированный файл позволит всегда иметь под рукой дистрибутив Linux, который переживет даже переустановку системы.

Инструкция по установке на Mac


Все команды нужно выполнять из macOS.

Конфигурация загрузки не имеет значения, способ не нарушает работу BootCamp, rEFInd и любых других нестандартных конфигураций. Поддерживаются компьютеры Mac не старше 2009 года (работоспособность на более старых не проверялась, но может и заработать).

  1. Скачать файл OneFileLinux.efi (20 мегабайт)
  2. Смонтировать EFI-раздел в систему.

    diskutil mount disk_номер_раздела 
    

    Узнать номер раздела EFI можно командой diskutil list.


    В моем случае команда будет выглядеть так:
    diskutil mount disk0s1 
    

  3. Скопировать OneFileLinux.efi в раздел EFI

    cp ~/Downloads/OneFileLinux.efi /Volumes/EFI/

  4. Добавить вариант загрузки в NVRAM

    sudo bless --mount /Volumes/EFI --setBoot --nextonly --file /Volumes/EFI/OneFileLinux.efi
    

    Опция nextonly означает, что данный вариант загрузки будет выполнен один раз. Следующая перезагрузка восстановит прежние настройки. Поэтому, чтобы вернуться из Linux в macOS, достаточно перезагрузиться еще раз.

В последних версиях macOS, начиная с El Capitan, используется технология System Integrity Protection (SIP), так называемый «без root-вый режим». Эта технология запрещает модификацию системных файлов и переменных даже суперпользователю. SIP включен по умолчанию, поэтому последняя команда bless вернет ошибку. Ее можно выполнить из Recovery Mode. Для это нужно зажать cmd+R при включении компьютера и открыть консоль
Utilities —> Terminal. В консоли выполнить шаги 2 и 4
Теперь каждый раз, когда вам потребуется загрузить OneFileLinux.efi, достаточно выполнить шаги 2 и 4 в консоли Recovery, или из основной системы, если SIP выключен.
Наверное, можно выполнить bless без монтирования раздела, но я не нашел, как это сделать. Тогда было бы достаточно одной команды.

Инструкция для PC


Вариантов загрузки на PC множество. Если ваша материнская плата имеет встроенный UEFI Shell, достаточно в нем указать путь к файлу OneFileLinux.efi, чтобы единожды загрузиться в Linux. Я опишу процесс настройки на моем Thinkpad X220.

  1. Скачать OneFileLinux.efi и положить его на EFI-раздел
  2. Добавить опцию загрузки в NVRAM

    
    efibootmgr --disk /dev/sda --part 2 --create --label "One File Linux" --loader /OneFileLinux.efi
  3. Во время загрузки нажать F12 и выбрать нужный вариант



Инструкция по сборке из исходников


Исходники проекта github.com/zhovner/OneFileLinux
Дистрибутив собран на чистом ядре 4.16-rc1 с kernel.org и Alpine Linux Mini Root filesystem.
Его можно легко собрать самостоятельно.

Подготовка initramfs


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

Я использовал корневую файловую систему от Alpine Linux. Это минималистичный дистрибутив для встраиваемых систем и контейнеров. У него существует вариант поставки без ядра и предустановленных программ, только корневая файловая система на базе busybox и пакетный менеджер apk.

chroot-имся в alpine linux:

chroot ./alpine-minirootfs /bin/ash

Находясь внутри окружения, можно внести нужные изменения. Добавить пакеты через «apk add», модифицировать сервисы используя openrc.

Вся необходимая информацию есть в wiki.

Сборка


Запустить скрипт сборки. Он соберет модули ядра, поместит их в initramfs, и соберет ядро.

./build.sh


Помогите!!111



На данный момент дистрибутив достаточно кривой. Если вы умеете линуксы, я буду очень признателен за любую помощь. Будет круто, если получится допилить этот проект до приемлемого уровня.

Известные проблемы:

  • Отключена загрузка модулей ядра — все драйвера вкомпиливаются в ядро.
    Наверное, правильно сделать их отдельными модулями и положить в initramfs
  • Шрифты на HiDPI-дисплеях — из-за огромного разрешения HiDPI-экранов,
    стандартные шрифты 8x16 выглядят очень мелко. Я вкомпилил шрифт 16x32, который выглядит нормально при большой плотности пикселей, но слишком большой для обычных экранов. По-хорошему, шрифт должен выбираться в зависимости от разрешения экрана.
  • Только один драйвер карты WiFi — сейчас вкомпилен один драйвер для встроенного в макбуки адаптера Broadcom 43602. По-хорошему, нужно собрать все популярные драйвера в виде модулей ядра, а также firmware к ним.
  • Сломан udev/mdev? — я не знаю, как он работает. Как правильно загружать модули в зависимости от конфигурации железа?
  • Мусор в ядре — в конфигурации ядра много лишних функций, которые можно выбросить. Это уменьшит размер итогового файла.

Приглашаю всех коммитить и создавать issues о проблемах github.com/zhovner/OneFileLinux.

Update


Изменения в новой версии:
  • Размер файла уменьшен до 12 MB
  • Добавлена поддержка mdev(udev) и модулей ядра
  • Добавлен SSH клиент/сервер
  • Удобный скрипт для сборки


Известные проблемы:
  • Не работает клавиатура на macbook 2015-2017. Необходимо собрать модуль github.com/cb22/macbook12-spi-driver
  • По-прежнему только один шрифт

Комментарии (42)


  1. ValdikSS
    23.02.2018 19:02

    Разве адаптер Broadcom 43602 поддерживает инъекции пакетов и режим мониторинга? Насколько я знаю, драйвер brcmfmac не поддерживает ни то, ни другое.


    1. zhovner Автор
      23.02.2018 19:09

      К сожалению да, не умеет. Инъекции и мониторинг поддерживали карты в старых макбуках 2009-2010 года, которые 802.11n. Примечательно, что виноват драйвер brcmfmac, потому что сама карта поддерживает мониторный режим, он работает в macOS через встроенную утилиту Wireless Diagnostics.app.


    1. Vespertilio
      24.02.2018 14:15

      Как минимум мониторинг поддерживается даже из самой МакОси стандартными утилитами, в этот момент значок вайфай меняется на глаз. Вроде бы из под линя можно и инъекции производить.


      1. zhovner Автор
        24.02.2018 14:19

        Я об этом и написал выше. Сама карта действительно поддерживает мониторинг, но единственный драйвер для нее, работающий в Linux, не поддерживает ни мониторинг, ни инъекции.
        wikidevi.com/wiki/Brcmfmac

        unix.stackexchange.com/questions/238461/monitor-mode-on-macbook-2015-hardware-in-kali-linux


  1. Sultansoy
    23.02.2018 19:23

    Подписался на репо, будем следить


  1. ohm
    23.02.2018 19:45

    На моем macbook 2012 года шрифт огромный. Читать затруднительно.


    1. zhovner Автор
      23.02.2018 20:38

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


      1. Ne01eX
        24.02.2018 13:54

        По-хорошему, — если не можете автоматизировать какой-то процесс, то дайте возможность сделать выбор пользователю.

        Вшивание шрифта в ядро собственно и сделано для того, чтобы ничего не выбирать. Ни автоматически, ни в ручную. Но если уж сильно приспичит, то это можно сделать через передачу параметров ядру. Обычно это делается на этапе выбора ядра в любимом загрузчике.


        1. zhovner Автор
          24.02.2018 14:14

          Обычно это делается на этапе выбора ядра в любимом загрузчике

          Смысл моего подхода в том, что загрузчик не используется. Параметры ядра можно передать через UEFI переменную.

          если не можете автоматизировать какой-то процесс, то дайте возможность сделать выбор пользователю


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


          1. Ne01eX
            24.02.2018 14:36

            Нет, шрифт можно задать в /linuxrc, о чём я уже писал. Равно как и раскладку клавиатуры, кодовую страницу и т.п. А уже по окончанию всего этого безобразия передать управление /sbin/init. у себя в RTK GNU/Linux я так и делал, чтобы писать сообщения процесса инициализации на языке, отличном от английского, пока ядро там свои дела проворачивает. Но это было 10 лет назад.

            В общем, в BOOTDISK-HOWTO всё написано.


    1. marataziat
      23.02.2018 20:42

      Зачем прогибаться под SIP, если его можно отключить так:csrutil disable в Recovery mode?


      1. zhovner Автор
        23.02.2018 20:43
        +1

        Да, так можно сделать, но я считаю, что это полезная функция. У нормального пользователя нет никаких причин отключать ее.


      1. creker
        23.02.2018 21:22

        Потому что потом ваш мак прогнут под себя другие. После отключения SIP он становится существенно более уязвимым.


  1. ovoshnayalavka
    23.02.2018 22:08

    Очень удобно


  1. luckybet100
    23.02.2018 22:08

    Всем добрый вечер, возникает ошибка:
    mount_msdos: /dev/disk0s1: not a directory
    при вводе sudo mount -t msdos /tmp/efi /dev/disk0s1

    Вывод diskutil:
    /dev/disk0 (internal):
    #: TYPE NAME SIZE IDENTIFIER
    0: GUID_partition_scheme 251.0 GB disk0
    1: EFI EFI 314.6 MB disk0s1
    2: Apple_CoreStorage Macintosh HD 250.0 GB disk0s2
    3: Apple_Boot Recovery HD 650.0 MB disk0s3

    /dev/disk1 (internal, virtual):
    #: TYPE NAME SIZE IDENTIFIER
    0: Apple_HFS Macintosh HD +249.7 GB disk1
    Logical Volume on disk0s2
    E84C5091-EE4E-4EC6-8497-AE8799151BB7
    Unlocked Encrypted


    1. zhovner Автор
      23.02.2018 22:10

      Прошу прощения, перепутал местами параметры.

      Правильно так:

      sudo mount -t msdos /dev/disk0s1 /tmp/efi
      


      1. babylon
        24.02.2018 06:37

        zhovner, с планшетами не дружит?


        1. ValdikSS
          24.02.2018 07:31

          Если у вас на планшете 32-битный UEFI, то, вероятно, придется использовать 32-битное ядро.
          Если у вас включен Secure Boot, то выключите его.


          1. babylon
            24.02.2018 08:01

            Cube iWork 8 TC


      1. dizzzaster
        24.02.2018 11:10
        +1

        Все проще — mkdir и sudo не нужны:

        diskutil mount disk0s1
        


        1. zhovner Автор
          24.02.2018 11:11

          О, класс, спасибо. Может вы знаете как bless без монтирования выполнить?


          1. dizzzaster
            24.02.2018 17:59

            Попробовать поиграть с

            bless --device


  1. lalabuy9948
    24.02.2018 11:11

    Добрый вечер, вылетает вот такая ошибка на последнем шаге:

    ~ » sudo bless --mount /tmp/efi --setBoot --nextonly --file /tmp/OneFileLinux.efi
    Can't statfs /tmp/OneFileLinux.efi


    1. zhovner Автор
      24.02.2018 11:20
      +1

      У вас неправильный путь. Посмотрите как вы монтировали EFI раздел. Файл должен быть в /tmp/efi/OneFileLinux.efi


  1. 13werwolf13
    24.02.2018 11:12
    +1

    ты сделал то что я планировал начать делать целый год)))
    огромное спасибо, может для кого-то это и «нинужно» а вот у меня есть несколько реальных применений такому проекту…


  1. Ne01eX
    24.02.2018 11:12

    linuxrc вам в корень.


  1. alexoron
    24.02.2018 12:10
    -1

    "Работает на любых компьютерах с UEFI — один и тот же файл будет работать на PC и Mac.
    Не нужно устанавливать загрузчики GRUB, rEFInd — ядро Linux собранное с поддержкой EFI Stub можно грузить напрямую без промежуточного загрузчика.
    Не нужны USB-флешки — скопированный на раздел EFI дистрибутив остается там навсегда, и его можно будет загрузить в любой момент. Он не занимает места на разделе основной системы, так как раздел EFI не используется в ОС."

    Исходя только из этого — это отличная новость для вирусописателей.
    Теперь ждем новые волны «неубиваемых» вирусов!
    Более того печальней всех маководам, которые раньше смеялись над виндузятниками.
    Дохихикались.


    1. zhovner Автор
      24.02.2018 12:27

      Для решения это проблемы как раз придуман secure boot, который уже есть и в Mac, правда пока только в iMac pro. Впрочем, Mac долгое время был подвержен уязвимости Thunderstrike, позволяющий прошить вредонос в саму прошивку на материнской плате, так что даже файлов на диске не было бы.

      Сценарий который вы описали крайне маловероятен. Если у вас включен SIP (проверить можно командой csrutil status) то никакая программа, даже вы сами, не сможете модифицировать nvram для загрузки вредоносного файла из операционной системы.

      Если предположить, что атакующий имеет физический доступ к компьютеру, тогда достаточно установить пароль на EFI, который будет запрашивать при любой попытке изменить очередность загрузки. То есть при попытке зайди в recover mode нажатием cmd+r.

      Рекомендую всем установить пароль на прошивку:

      1. При загрузке зажать cmd+R.

      2. Зайти в меню Утилиты --> пароль прошивки


  1. Tihon_V
    24.02.2018 12:45

    Может стоит использовать какое-нибудь LTS-ядро (4.14/4.4)?
    Под >4.15 — нет стабильно работающего 8814au.

    P. S.: Могу потестировать билд с драйверами для iwlwifi, ath9k, ath9k_htc, rt2800usb и упомянутого 8814au.


    1. zhovner Автор
      24.02.2018 13:04

      Вероятно, вы правы. Я не раздумывал долго и взял последнее в списке на kernel.org.
      Я вот только не знаю как перенести .config с одной версии ядра на другое. Там ведь отличаются опции и их названия.

      Сейчас решаю проблему с неработающей SPI клавиатурой на новых макбуках 2015-2017 года github.com/cb22/macbook12-spi-driver


      1. Ne01eX
        24.02.2018 14:03

        Да ладно. А я-то дурак один и тот же конфиг годами использую…

        Нормально всё будет, я сто раз так делал. При downgrade, те опции, которых нет в 4.14.x будут проигнорированы.


      1. matshch
        25.02.2018 10:59
        +1

        Для переноса .config достаточно его скопировать и выполнить make oldconfig. Всё возможное перенесётся, про разницу будут заданы вопросы.


  1. Hile
    24.02.2018 13:51

    Виртуалка с Kali + внешний адаптер на деле оказывается более удобным.


    1. zhovner Автор
      24.02.2018 13:56

      Да, согласен. Но в нужный момент этого адаптера не оказывается под рукой. Образ kali весит 2GB, еще нужно украсть Vmware Fusion, потому что Virtualbox имеет проблемы с пробрасыванием USB устройств. Я как раз пытался найти более элегантное решение. Жаль только, что встроенная wifi карта в macbook 2015 не умеет ни мониторинг под линуксом, ни инъекции.


      1. Hile
        24.02.2018 14:22

        Parallels еще можно «купить» как вариант ) а еще, есть HyperKit от Apple (возможно там проброс будет ок )


        1. zhovner Автор
          24.02.2018 14:24

          HyperKit от Apple

          Ухты, никогда об этом не слышал. Спасибо.


          1. Hile
            24.02.2018 14:28

            соврал похоже, не от эпл, но там нативный для osx виртуализации движок юзается как я понял.


  1. PapiRUS90
    24.02.2018 14:19

    Приветствую. На команду «sudo bless --mount /Volumes/EFI --setBoot --nextonly --file /Volumes/EFI/OneFileLinux.efi» терминал ругался. Без sudo всё прошло успешно.
    Но у меня крайне дилетантский вопрос. Крузится Alpha и спрашивает «onefilelinux login». Я погуглил. Ввёл root. А дальше вроде как нужно вводить setup-alpha. Но команда не работает. Что не так делаю?
    Заранее благодарю за ответ.


    1. zhovner Автор
      24.02.2018 14:22

      Без sudo всё прошло успешно.

      Речь про recovery режим? Тогда все правильно, там не нужно вводить sudo, потому что она и так запущена от пользователя root.

      спрашивает «onefilelinux login». Я погуглил. Ввёл root. А дальше вроде как нужно вводить setup-alpha.

      После того как вы ввели root, вас пускает в консоль. Это конец. Дальше вы либо делаете что вам нужно, либо вводите reboot и перезагружаетесь обратно в macOS.

      Графического интерфейса нет. Возможно, мы добавим его позже, но я не уверен.


  1. dizzzaster
    24.02.2018 17:55

    Скрипт запилил для macOS, пользуйтесь, оптимизируйте:
    gist.github.com/aquigni/5097f40413f53da5a75bc29309cc0059

    #!/bin/sh
    cd ~/Downloads/
    
    ### Checking if Homebrew is installed:
    command -v brew >/dev/null 2>&1 || {
    	echo >&2 "Installing Homebrew:"
    	/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    }
    
    ### Getting wget:
    brew install wget
    
    ### Getting latest OneFileLinux.efi release via GitHub API:
    curl -s https://api.github.com/repos/zhovner/OneFileLinux/releases/latest |
    	grep "browser_download_url.*efi" |
    	cut -d : -f 2,3 |
    	tr -d \" |
    	wget -i -
    
    ### Find first macOS disk (containing Recovery HD by default) and mounting its EFI partition:
    diskutil mount $(diskutil info "Recovery HD" |
    	grep "Part of Whole" |
    	grep -Eo '.{5}$')s1
    
    ### Or just mount default EFI partition:
    # diskutil mount disk0s1
    
    ### Check if SIP is enabled:
    if csrutil status | grep "NVRAM Protections: disabled"; then
    	echo "NVRAM isn't protected, continuing:"
    	mkdir -p /Volumes/EFI/EFI/OneFileLinux
    	cp -v OneFileLinux.efi /Volumes/EFI/EFI/OneFileLinux/boot.efi
    	sudo bless --mount /Volumes/EFI/EFI/OneFileLinux --setBoot --nextonly --file /Volumes/EFI/EFI/OneFileLinux/boot.efi --verbose
    else
    	echo "System Integrity Protection is enabled, disabling only available in Recovery OS." >&2
    	exit 1
    fi
    
    


  1. JEAN17RUS
    24.02.2018 19:28

    Интересно, получится ли запилить полноценный Linux-дистро таким образом? :)


    1. dizzzaster
      25.02.2018 09:59

      Скорее да, при условии, что влезет в ~200 Мб EFI раздела.