ошибка при сжатии файлов в rpm с помощью rpmbuild

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

На самом деле, на большинстве платформ он просто завершается с ошибкой, но это зависит от аппаратной архитектуры. Определенно нет никакой гарантии, что это безвредно, если только вы не запустите команду от имени непривилегированного пользователя. Для непривилегированного пользователя эта команда совершенно безвредна, потому что вы не можете открыть /dev/mem.

Когда вы запускаете команду от имени пользователя root, вы должны знать, что делаете. Ядро будет иногда мешать вам делать что-то опасное, но не всегда. /dev/mem— это одна из тех потенциально опасных вещей, когда вы действительно должны знать, что делаете.

Я расскажу, как запись в /dev/memработает в Linux. Общий принцип был бы таким же на других Unices, но такие вещи, как параметры ядра, совершенно другие.

Что происходит, когда процесс читает или записывает файл устройства, зависит от ядра. Доступ к файлу устройства запускает некоторый код в драйвере, который обрабатывает этот файл устройства. Например, запись в /dev/memвызывает функциюwrite_memв drivers/char/mem.c. Эта функция принимает 4 аргумента :структуру данных, представляющую открытый файл, указатель на данные для записи,количество байтов для записи и текущая позиция в файле.

Обратите внимание, что вы дойдете до этого только в том случае, если вызывающая сторона изначально имела разрешение на открытие файла. Файлы устройств обычно подчиняются разрешениям на доступ к файлам. Обычные разрешения /dev/memпринадлежат crw-r-----root:kmem, поэтому, если вы попытаетесь открыть его для записи, не будучи root, вы просто получите «отказано в доступе» (EACCESS ). Но если вы являетесь пользователем root (или если root изменил права доступа к этому файлу ), открытие происходит, и вы можете попытаться выполнить запись.

Код в функции write_memвыполняет некоторые проверки работоспособности, но этих проверок недостаточно для защиты от всего плохого. Первое, что он делает, это преобразует текущую позицию файла *pposв физический адрес. Если это не удается (на практике, потому что вы работаете на платформе с 32 -битными физическими адресами, но с 64 -битными смещениями файлов, а смещение файла больше 2^32 ), запись завершается ошибкой с EFBIG (слишком большой файл ). Следующая проверка заключается в том, допустим ли диапазон физических адресов для записи в этой конкретной архитектуре процессора, и там ошибка приводит к EFAULT (bad address ).

Далее, на Sparc и m68k любая часть записи на самой первой физической странице автоматически пропускается.

Теперь мы достигли основного цикла , который перебирает данные в блоках, которые могут уместиться на одной MMU странице. /dev/memобращается к физической памяти, а не к виртуальной памяти, но инструкции процессора для загрузки и сохранения данных в памяти используют виртуальные адреса, поэтому код должен организовать сопоставление физической памяти с некоторым виртуальным адресом. В Linux, в зависимости от архитектуры процессора и конфигурации ядра, это сопоставление либо существует постоянно, либо должно выполняться на лету; это работаxlate_dev_mem_ptrunxlate_dev_mem_ptrотменяет все, что xlate_dev_mem_ptrделает ).Затем функция copy_from_userчитает из буфера, который был передан системному вызову write, и просто записывает в виртуальный адрес, на который в данный момент отображается физическая память. Код выдает обычные инструкции по сохранению в памяти, и что это означает, зависит от аппаратного обеспечения.

Прежде чем я расскажу, что делает запись в физический адрес, я расскажу о проверке, которая происходит перед этой записью. Внутри цикла функция page_is_allowedблокирует доступ к определенным адресам, если опция конфигурации ядраCONFIG_STRICT_DEVMEMвключена (, что имеет место по умолчанию ):только адреса, разрешенные devmem_is_allowed, могут быть достигнуты через /dev/mem, для других запись завершается ошибкой с EPERM (операция не разрешена ). В описании этой опции указано:

If this option is switched on, and IO_STRICT_DEVMEM=n, the /dev/mem file only allows userspace access to PCI space and the BIOS code and data regions. This is sufficient for dosemu and X and all common users of /dev/mem.

Это очень ориентированное на x86 -описание. На самом деле, в более общем смысле, CONFIG_STRICT_DEVMEMблокирует доступ к адресам физической памяти, которые отображаются в ОЗУ, но разрешает доступ к адресам, которые не отображаются в ОЗУ. Детали того, какие диапазоны физических адресов разрешены, зависят от архитектуры процессора, но все они исключают ОЗУ, где хранятся данные ядра и пользовательских процессов. Дополнительная опция CONFIG_IO_STRICT_DEVMEM(, отключенная в Ubuntu 18.04 ), блокирует доступ к физическим адресам, заявленным драйвером.

Адреса физической памяти, соответствующие ОЗУ . Итак, существуют адреса физической памяти, которые не сопоставляются с оперативной памятью? да. Это обсуждение, которое я обещал выше, о том, что значит писать по адресу.

Команда сохранения в памяти не обязательно производит запись в ОЗУ. Процессор разбивает адрес и решает, на какое периферийное устройство отправить хранилище. (Когда я говорю «процессор», я имею в виду периферийные контроллеры, которые могут поставляться разными производителями. )ОЗУ — это только одно из этих периферийных устройств. То, как выполняется диспетчеризация, очень зависит от архитектуры процессора, но основные принципы более или менее одинаковы для всех архитектур.Процессор в основном разлагает старшие биты адреса и ищет их в некоторых таблицах, которые заполняются на основе жестко закодированной -информации, информации, полученной путем проверки некоторых шин, и информации, настроенной программным обеспечением. Может потребоваться много кэширования и буферизации, но в двух словах, после этой декомпозиции процессор записывает что-то (, кодирующее как целевой адрес, так и данные, которые хранятся )на какой-то шине и тогда дело за периферийным устройством. (Или результатом поиска в таблице может быть то, что по этому адресу нет периферийных устройств, и в этом случае процессор входит в состояние ловушки , где он выполняет некоторый код в ядре, который обычно приводит к SIGBUS для вызывающего процесса.)

Сохранение по адресу, который сопоставляется с ОЗУ, не «делает» ничего, кроме перезаписи значения, ранее сохраненного по этому адресу, с обещанием, что последующая загрузка по тому же адресу вернет последнее сохраненное значение.. Но даже в оперативной памяти есть несколько адресов, которые не ведут себя таким образом :, в ней есть несколько регистров , которые могут управлять такими вещами, как частота обновления и напряжение.

В общем, чтение или запись в аппаратный регистр делает то, на что запрограммировано аппаратное обеспечение. Большинство обращений к оборудованию работает таким образом :программное обеспечение (обычно код ядра )обращается к определенному физическому адресу, он достигает шины, которая соединяет процессор с периферийным устройством, и периферийное устройство делает свое дело. Некоторые процессоры (, в частности x86 ), также имеют отдельные инструкции ЦП, которые вызывают чтение/запись в периферийные устройства, которые отличаются от загрузки и сохранения памяти, но даже на x86 многие периферийные устройства доступны через загрузку/сохранение.

Команда dd if=/dev/urandom of=/dev/memзаписывает случайные данные в любое периферийное устройство, отображаемое по адресу 0 (и последующим адресам, до тех пор, пока запись выполняется успешно ).На практике я ожидаю, что во многих архитектурах физический адрес 0 не имеет сопоставленных с ним периферийных устройств или имеет ОЗУ, и поэтому самая первая попытка записи завершается неудачно. Но если есть периферийное устройство, сопоставленное с адресом 0, или если вы измените команду на запись по другому адресу, вы вызовете что-то непредсказуемое в периферийном устройстве. Со случайными данными по возрастающим адресам вряд ли получится что-то интересное, но в принципе мог бы выключить компьютер (там наверное адрес, который делает это на самом деле ), затирает какую-то настройку биоса, что делает невозможной загрузку, или даже ударить какое-нибудь неисправное периферийное устройство таким образом, что оно повредится.

alias Russian_roulette='dd if=/dev/urandom of=/dev/mem seek=$((4096*RANDOM+4096*32768*RANDOM))'

0
22.08.2021, 22:39
1 ответ

Вы компилируете новый пакет с rpmbuild, не сжимая его.

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

Вы должны использовать diffдля создания патча, который включает ваши изменения в исходный код, и применить его после того, как все другие патчи в файле спецификаций (включат его, добавив еще одну строку Patch ###в файл спецификации. и строку %patch к %prep ). Конечным результатом будут единственные файлы, которые вы изменяете, это файл спецификации и добавление файла.patch в исходный каталог. См. Руководство по упаковке RPM для правильного создания патча.

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

Что касается фальшивых дат, RPM начал проверять правильность дня недели для даты, и все эти даты неверны. Я полагаю, вам нужно исправить это, если вы хотите собрать пакет. Вероятно, это было исправлено в RHEL.

1
22.08.2021, 23:19

Теги

Похожие вопросы