Linux в одном файле для Macbook +74





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
    /#10684294

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

    • zhovner
      /#10684298

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

    • Vespertilio
      /#10684910

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

  2. Sultansoy
    /#10684304

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

  3. ohm
    /#10684316

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

    • zhovner
      /#10684378

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

      • Ne01eX
        /#10684900

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

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

        • zhovner
          /#10684908

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

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

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


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

          • Ne01eX
            /#10684936

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

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

    • marataziat
      /#10684382

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

      • zhovner
        /#10684384 / +1

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

      • creker
        /#10684412

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

  4. ovoshnayalavka
    /#10684440

    Очень удобно

  5. luckybet100
    /#10684442

    Всем добрый вечер, возникает ошибка:
    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

    • zhovner
      /#10684448

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

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

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

      • babylon
        /#10684690

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

        • ValdikSS
          /#10684708

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

      • dizzzaster
        /#10684802 / +1

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

        diskutil mount disk0s1
        

        • zhovner
          /#10684804

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

          • dizzzaster
            /#10685112

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

            bless --device

  6. lalabuy9948
    /#10684806

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

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

    • zhovner
      /#10684812 / +1

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

  7. 13werwolf13
    /#10684808 / +1

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

  8. Ne01eX
    /#10684810

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

  9. alexoron
    /#10684836 / -1

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

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

    • zhovner
      /#10684842

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

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

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

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

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

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

  10. Tihon_V
    /#10684858

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

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

    • zhovner
      /#10684870

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

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

      • Ne01eX
        /#10684904

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

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

      • matshch
        /#10685550 / +1

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

  11. Hile
    /#10684898

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

    • zhovner
      /#10684902

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

      • Hile
        /#10684924

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

        • zhovner
          /#10684926

          HyperKit от Apple

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

          • Hile
            /#10684928

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

  12. PapiRUS90
    /#10684918

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

    • zhovner
      /#10684922

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

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

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

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

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

  13. dizzzaster
    /#10685110

    Скрипт запилил для 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
    
    

  14. JEAN17RUS
    /#10685192

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

    • dizzzaster
      /#10685530

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