Моя точка доступа TP-Link EAP770 v1 портачит загрузки по Wi-Fi, а производитель прекратил обслуживание этой модели ещё до того, как я вообще достал её из коробки. Решение проблемы — прописать два нуля в sysfs. Вот только командная оболочка TP-Link не даёт этого сделать, и мне пришлось писать эксплойт для своего же @#$%&! устройства.

Постоянный обрыв длительных загрузок

В августе 2023 года я прикупил новёхонькую точку доступа стандарта Wi-Fi 7 — TP-Link EAP770. Подключение через неё слегка глючило, видео периодически подтупливало, но меня это не особо беспокоило.

Тогда я основное время работал за машиной, подключенной по Ethernet. Если же мне нужно было куда-то отлучиться, то я по Wi-Fi синхронизировал свой домашний каталог (~) с ноутбуком через rsync и брал ноут с собой. Вот как раз при этой передаче и начали возникать косяки с файлами больше нескольких ГБ. SSH ругался на ошибки целостности (MAC), поэтому я какое-то время искал проблемы в rsync и SSH. В остальном всё работало, а смена параметров rsync ситуацию то улучшала, то ухудшала. Wireshark показывал ноль битых контрольных сумм и ноль повторных передач, а одиночный UDP-поток из случайных байтов доходил абсолютно чистым. Я верил, что TCP непременно доставит правильные байты — ведь он, чёрт возьми, для этого и создавался. Собственно, потому я был уверен, что косяк где-то в rsync или SSH. В итоге я написал для rsync обёртку, чтобы автоматически повторять передачи, и забил.

Позже я наладил трафик внутри домашней сети через Tailscale, и повторные попытки стали не нужны. WireGuard просто дропает пакет, если его аутентификация проваливается — TCP внутри туннеля видит потерю пакета и повторяет отправку. Поскольку передача заработала исправно, я снова успокоился.

Отсутствие обновлений прошивки

Как я уже писал, у меня точка доступа EAP770(EU) v1.0. Это модель на базе процессора Qualcomm IPQ9574 под управлением Linux 5.4.164 и с прошивкой 1.0.0 Build 20230605 Rel. 71641. С этой прошивкой устройство шло с завода, и, похоже, с того момента в TP-Link о нём напрочь забыли :)

Я эту штуку купил в августе 2023 года, а стандарт Wi-Fi 7 окончательно утвердили только в сентябре 2024-го. У неё нет сертификации Wi-Fi Alliance, и её покупка была явно глупым решением.

НИКОГДА НЕ ПОКУПАЙТЕ ТЕХНИКУ, ПОКА СТАНДАРТЫ НЕ БУДУТ УТВЕРЖДЕНЫ, А САМИ УСТРОЙСТВА НЕ ПРОЙДУТ СЕРТИФИКАЦИЮ.

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

Поддержка модели EAP770 Version 1 завершена. Это устройство ещё может быть в наличии у некоторых ритейлеров, но обновлений прошивки для него больше не выпускается.

КЛАСС.

Поиск причины повреждения данных

В 2026 году я решил перейти на NixOS и обнаружил, что при скачивании файла на 128 МБ из бинарного кэша Nix через Fastly по протоколу HTTP/2 постоянно возникала ошибка. При этом тот же файл спокойно скачивался по протоколу HTTP/1.1. Мне до сих пор невдомёк, чем помогал HTTP/1.1. Могу лишь предположить, что по HTTP/2 данные просто передавались быстрее. Команда git clone тоже выдавала ошибку, а HTTPS-соединения разрывались с сообщением bad record mac. Плюс в марте попытка скачать ISO-образ NixOS через wget завершилась ошибкой TLS:

2026-03-05 12:37:18 (31.6 MB/s) - Read error at byte 2722477636/3683778560 (error:0A000119:SSL routines::decryption failed or bad record mac; error:0A000139:SSL routines::record layer failure). Retrying.

Я вручную переключился на HTTP/1.1 и снова забил.

В сентябре я превратил свою рабочую станцию в сборочную ферму, а сам пересел за ноутбук, который подключается к сети по Wi-Fi. При этом каждый день где-то в районе 11:00 Wi-Fi стабильно отваливался — аккурат перед дежурным созвоном. Пронаблюдав эту ситуацию несколько дней подряд, я решил снова вскрыть этот ящик Пандоры и засел за поиск причины, позвав на помощь Opus 5.5.

Спойлер: причиной отвалов оказался другой баг.

Я обвешал BPF-зондами Qualcomm-драйвер на ноутбуке и запустил утилиту apstats на точке доступа с правами root. Баг таился в закрытой прошивке самой Wi-Fi карты ноутбука; подробности читайте в апдейте в самом низу.

Я пробовал включать и отключать Wi-Fi 7, отключал GRO на клиенте и даже заменил Wi-Fi адаптер MediaTek в моём Framework 16 на модель от Qualcomm. Новый адаптер и отключение GRO вроде как слегка улучшили ситуацию, но в корне проблему не решили.

С помощью tcpdump я перехватил провалившуюся операцию скачивания и нашёл TCP-сегмент из 1440 байт, в котором было повреждено 64 байта подряд, но контрольная сумма при этом оставалась верной. Показатель TcpInCsumErrors держался на нуле. Протокол TCP принял этот сегмент как правильный и передал его на уровень TLS, который отклонил запись с ошибкой bad record mac.

Повреждённая запись не расшифровывалась, поэтому сравнить испорченные байты с ожидаемой полезной нагрузкой я не мог. Тогда я решил потестить передачу сырых данных по TCP между ПК с проводным подключением и ноутбуком с Wi-Fi. Выяснилось, что порча происходила только при одновременной работе нескольких TCP-потоков и только в направлении LAN -> Wi-Fi. Тест выявил три повреждённых блока по 64 байта в 8192 МиБ переданных данных, и каждый из этих блоков начинался с нулей.

Правильная контрольная сумма в повреждённом сегменте означала, что после повреждения её кто-то вычислил повторно. Значит, теперь нужно было понять, что именно на этом маршруте перезаписывает заголовки TCP. После замены платы MediaTek на Qualcomm проблема осталась, то есть дело не в ноутбуке. На проводных клиентах всё было чисто, а код целостности CCMP MIC на «битых» пакетах оставался корректным — значит, дело было не в кабеле и не в помехах радиоэфира. Оставался только мост между Ethernet и Wi-Fi внутри самой точки доступа. 64 байта — это как раз размер строки кэша в ядрах процессора IPQ9574, что явно указывало на баг кэша или DMA, а не на перевёрнутый бит. Единственный же компонент на этом пути, который одновременно и ускоряет трафик моста, и пересчитывает контрольные суммы — это подсистема аппаратной разгрузки Qualcomm SFE/PPE offload.

Две команды записи, требующие root

Изучив исходники драйвера, я предположил, что SFE/PPE можно отключить с помощью двух следующих настроек:

echo 0 > /sys/sfe/l2_feature
echo 0 > /sys/sfe/ppe_rfs_feature

В оба этих файла sysfs разрешена запись только из-под root, но SSH-оболочка в TP-Link запускается как uid 1 вообще без системных прав. В GUI для этого тоже настройки нет.

Официального образа прошивки для первой версии, который можно было бы пропатчить и накатить, в свободном доступе тоже не существовало, а прошивка от v2 предназначена для совсем другого железа. Я попытался залить EAP773(EU)_V1_1.0.14 от родственной модели EAP773, но устройство её отклонило. А более новые релизы прошивок для v2 вообще зашифрованы. Если рассматривать прямую прошивку чипа, то потребуется специальная прищепка (flash clip) для программатора. Но мне не хотелось заморачиваться её поиском, как и превратить эту чёртову точку доступа в кирпич.

Тратить лишние 200 баксов на замену девайса только потому, что в TP-Link не стали заморачиваться его поддержкой после продажи, я тоже не собирался. Устройство работает у меня дома, я точно знаю, какую настройку нужно подкрутить, но софт этого не позволяет.

Но стоит отдать должное TP-Link: систему они укрепили хорошо. Я не нашёл ни одного вектора уязвимости в их бинарниках: они повсюду используют белые списки и загружают для ядра только необходимые модули. Так что халявы в духе ; echo 0 > /sys/sfe/ppe_rfs_feature мне не светило. Единственным путём внутрь оставалось само ядро.

Призвав на помощь Opus 4.8, я связал в цепочку уязвимость CVE-2022-0185 и манипуляцию с буфером пайпа. CVE-2022-0185 заключается в целочисленном переполнении вниз в функции legacy_parse_param(), доступной из непривилегированного пространства имён пользователей. Эта уязвимость позволяет при записи переполнить 4-килобайтный slab-объект. А манипуляции с буфером пайпа, в свою очередь, превращают это переполнение в возможность произвольной записи в память. В открытом доступе уже были подробные разборы и примеры эксплуатации (PoC) этих уязвимостей.

При этом эксплойт должен был оставить точку доступа в рабочем режиме, так как после перезагрузки сломанный offload включается обратно. Переполнение оставляет 4-килобайтный slab в таком состоянии, когда вторая попытка уводит ядро в панику, так что на одну загрузку роутера попытка тоже одна. Я дал Opus описание базовых примитивов и поручил дорабатывать эксплойт до тех пор, пока он не заработает стабильно.

Описание эксплойта

Поскольку исходников GPL для версии v1 производитель не выложил, я взял ближайший опубликованный код от модели EAP783. Конфигурация её ядра отличалась от конфигурации в /proc/config.gz моей точки доступа чисто косметически тремя строками. В итоге я собрал с этим конфигом тестовый стенд в QEMU, наладил работу цепочки уязвимостей сначала на нём и только потом перешёл к реальному устройству.

В ядре отсутствует механизм KASLR, поэтому адреса в памяти между перезагрузками не меняются. Но вот таблицу символов kallsyms производитель обнулил, так что мне всё равно пришлось вычислять адреса во время работы системы. В сборке для QEMU ядро загружалось по физическому адресу 0x40080000, но на самом устройстве оно разворачивалось по адресу 0x42080000, из-за чего все расчёты смещались на 0x2000000. Правильный базовый адрес я в итоге нашёл в переменной конфигурации сборки в исходниках EAP783. И даже после его исправления выяснилось, что секции ядра .text, .rodata и .data на устройстве сместились каждая на свою величину относительно сборки QEMU. Так что нельзя было просто прибавить одно общее смещение ко всем адресам.

Механизм работы:

  1. Через unshare изолировать процесс в отдельное пространство имён, чтобы получить доступ к функции fsopen и вызвать переполнение вниз.

  2. Дефрагментировать 4-килобайтный slab с помощью пары сотен аллокаций одного размера, после чего выстроить созданные объекты в памяти так, чтобы источник переполнения, целевой ключ, сообщение SysV и кольцевые буферы пайпа оказались вплотную друг к другу.

  3. Вызвать переполнение, выходящее в область метаданных ключа, и увеличить значение поля его длины. Теперь чтение этого ключа будет приводить к утечке данных соседних объектов, включая поле buf[0].ops пайпа, где содержится адрес anon_pipe_buf_ops.

  4. Перенаправить буфер одного пайпа на страницу кольцевого буфера другого, а затем подделать в этом втором кольце запись, используя утёкший ранее указатель ops. Функция pipe_buf_can_merge() проверяет совпадение этих указателей, поэтому операция совмещённой записи через поддельную запись позволяет добраться до любой физической страницы, включая область образа ядра.

  5. Просканировать секцию .data в поиске modprobe_path. Обычно при чтении страниц образа ядра через пайп в момент очистки буфера для зарезервированной страницы вызывается put_page(), что приводит к ошибке Bad page map и панике ядра. Однако функция pipe_read вызывает только методы ->confirm и ->release, не проверяя подлинность таблицы ops. Поддельная pipe_buf_operations, где оба метода указывают на generic_pipe_buf_confirm (которая просто возвращает ноль и больше ничего не делает), даёт возможность сканировать и читать страницы без их освобождения. Это позволит эксплойту кусками сканировать секцию .data, пока не найдётся нужная строка.

  6. Перезаписать modprobe_path и запустить через execve файл с «магическими байтами», которые не соответствуют ни одному бинарному формату. Ядро вызовет request_module(), которая запустит программу по подменному пути с глобальными правами uid 0.

  7. Оставить дочерний процесс активным, чтобы он удерживал поддельный пайп. Если позволить ему завершиться, пайп будет уничтожен, и из-за попытки освобождения зарезервированной страницы возникнет паника ядра.

Чтобы довести эту схему до рабочего состояния, потребовалось около семнадцати часов игры в «рулетку» с Opus 4.8 за токены. За это время я успел изучить бинарники устройства в radare2, проверить включённые механизмы защиты и разобраться со всеми вылетами системы. В итоге точка доступа осталась в рабочем состоянии, а отключение аппаратной разгрузки привело к прекращению порчи данных.

Баг когерентности DMA-кэша

Драйвер qca-nss-dp от Qualcomm повторно использует пакетные буферы, забывая синхронизировать процессорный кэш для всего буфера приёма перед его возвращением в распоряжение сетевой карты (NIC). На этом железе контроллер DMA пишет напрямую в DRAM, минуя синхронизацию кэшей процессора. Из-за этого «грязная» строка кэша, оставшаяся в буфере от предыдущего использования, может быть сброшена в память уже после того, как сетевая карта приняла новый пакет, затерев часть этого пакета.

Затем подсистема SFE/PPE пересчитывает контрольные суммы для уже повреждённых данных, и клиент получает свежую контрольную сумму TCP, валидную для этого мусора. Протокол TCP принимает пакет, а вот механизмы проверки подлинности сообщений (MAC) в TLS и SSH обнаруживают искажение, выдавая ошибки bad record mac и corrupted MAC.

На архитектуре x86 оборудование само следит за согласованностью DMA с кэшами процессора, поэтому там такое упущение никак бы не навредило. Изучая исходники ядра, я обнаружил похожие проблемы с обслуживанием кэша при DMA и в других драйверах. Только пока не знаю, как протестировать их на реальном железе и кому о них сообщить.

Описание драйвера

Это внешний код NSS от Qualcomm, доступный в репозитории openwrt/qca-nss-dp. При работе по быстрому пути передачи движок SFE сбрасывает кэш для данных skb->data в объёме skb_headlen(skb) байт, что в точности составляет линейную часть исходящего пакета.

edma_tx.c#L483-L490:

buff_addr = (dma_addr_t)virt_to_phys(skb->data);
                EDMA_TXDESC_BUFFER_ADDR_SET(txd, buff_addr);

#ifdef EDMA_40BIT_SUPPORT
                EDMA_TXDESC_BUFFER_ADDR_HI_SET(txd, buff_addr);
#endif

                dmac_clean_range_no_dsb((void )skb->data, (void )(skb->data + buf_len));

Затем он выставляет флаг skb->fast_recycled = 1, а буфер возвращает в закреплённый за процессором список повторного использования без очистки содержимого.

edma_tx.c#L735-L743:

   /*
    * Если пакет пошёл по быстрому пути SFE, устанавливается 
    * флаг fast_recycled, чтобы любой драйвер Rx DMA, который
    * позднее будет выделять буфер под этот пакет, мог избежать
    * аннулирования кэша.
    */
    if (likely(skb->fast_xmit) && likely(skb->is_from_recycler)) {
        skb->fast_recycled = 1;
    }

Механизм повторного использования обнуляет структуру sk_buff вплоть до поля tail, восстанавливает флаг fast_recycled и сбрасывает указатель skb_data на значение skb->head + NET_SKB_PAD.

Когда этот буфер переиспользуется для приёма, код пути наполнения видит установленный флаг и пропускает операцию аннулирования кэша.

edma_rx.c#L477-L491:

/*
 * Аннулирование кэша для skb->data.
 * Операция сброса на ядрах A73 также влечёт за собой аннулирование.
 * Если пакет передаётся по быстрому пути, а значит, выделенный
 * под него буфер возвращается в пул по быстрому циклу, можно быть
 * уверенными, что аннулирование кэша было выполнено при прошлой передаче.
 */
 if (unlikely(!skb->fast_recycled)) {
     dmac_inv_range_no_dsb((void *)skb->data,
                   (void *)(skb->data + rx_alloc_size -
                   EDMA_RX_SKB_HEADROOM -
                   NET_IP_ALIGN));

 }
 skb->fast_recycled = 0;

Область приёма составляет 1856 байт, или 29 строк кэша, начиная со смещения head + 192. При предыдущей передаче произошёл сброс всего двух или трёх строк, причём по другому смещению.

«Грязные» строки, оставшиеся вне этой очищенной области, могут сбрасываться в DRAM уже после того, как сетевая карта выполнит DMA-передачу, затирая принятый пакет порциями по 64 байта. Причиной такого сброса может стать обычное вытеснение строк из кэша. На arm64 к этому также приводит аннулирование невыровненной области памяти. Функция __dma_inv_area использует инструкцию dc civac (очистка и аннулирование) для частично заполненных пограничных строк кэша. После того, как «грязные» данные затёрли часть пакета в DRAM, восстановить полученные байты с помощью аннулирования кэша уже не получится.

Сетевая карта проверяет контрольную сумму исходного пакета ещё до его повреждения, а код приёма на точке доступа видит аппаратные флаги состояния и помечает пакет как CHECKSUM_UNNECESSARY. Точная последовательность операций внутри PPE скрыта в проприетарном коде драйвера и железа, но анализ сетевых пакетов показывает, что контрольная сумма вычислялась уже после повреждения данных.

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

Через проводной тракт приёма точки доступа проходит только трафик, скачиваемый Wi-Fi клиентами; загружаемый ими трафик через него не идёт, а обмен данными между проводными клиентами происходит исключительно через коммутатор.

Opus 5.5 нашёл баг, а потом отказался его обсуждать

Когда я перешёл от диагностики проблемы к её исправлению, Opus 5.5 начал обрывать сессии примерно на каждом втором сообщении. Причём достаточно было просто упомянуть что-то вроде «локального повышения привилегий». И хотя у меня на аккаунте включена опция Cyber Verification Program, это никак не помогло. К слову, Opus 4.8 помог реализовать эксплойт без подобных проблем.

Из-за своих защитных механизмов Opus 5.5 также обрывал сессию, когда я просил его вычитать эту статью. А вот GPT-6 Astra вычитывает и правит её без какой-либо кибер-верификации.

До отключения offload и после

Я протестировал передачу сырого TCP-трафика между теми же двумя компьютерами с включённой аппаратной разгрузкой и выключенной.

Offload

Направление

Данные

Скорость

Повреждённые блоки по 64 байта

Включен

LAN -> Wi-Fi

8192 МиБ

103,4 МиБ/с

3

Отключен

LAN -> Wi-Fi

Тест в течение ночи

95,4 МиБ/с

0

В этом тесте из-за её отключения скорость скачивания упала примерно на 8%. Приходится жертвовать производительностью только потому, что TP-Link не даёт мне нормально починить собственное устройство.

При включённой же разгрузке невозможно скачать большой файл по Wi-Fi одним потоком, проходят только обрубки. Когда же я её отключил, за всю ночь тестирования не побился ни один фрагмент, и с тех пор крупные файлы передаются без проблем. Ну а выгрузка с Wi-Fi клиента в LAN и без того работала исправно.

После отключения разгрузки начинает расти счётчик NOT_SUPPORT_BRIDGE в файле /sys/sfe/exceptions, так как трафик в режиме моста теперь идёт не по ускоренному сетевому тракту, а по обычному.

После перезагрузки роутера настройки сбрасываются, поэтому скрипт-наблюдатель на моём NAS периодически опрашивает устройство и перезапускает эксплойт, если разгрузка снова включилась. Если же у него это не получается, он перезагружает точку через API управления TP-Link и повторяет попытку. При этом на количество таких перезагрузок установлен жёсткий лимит.

А ведь в Qualcomm могут при желании починить свой драйвер или хотя бы выложить его в более открытом виде. В чистом OpenWrt этого бага нет, а TP-Link всё равно не выпустит новую прошивку для моего девайса. Хотя похожие баги с DMA, которые я нашёл в самом ядре Linux, заслуживают более внимательного изучения. Вернусь к ним на выходных.

Апдейт: отслеживание обрывов

Плата Qualcomm, которую я установил в свой Framework 16, именуется WCN785x, и каждые несколько часов она внезапно прекращала отправлять данные на период от 1 до 4 минут. Поскольку у меня уже был рут-доступ к точке, я запустил на EAP770 утилиту apstats параллельно с BPF-зондами на ноутбуке и зафиксировал три обрыва связи, попутно собрав логи с обеих сторон.

Всё, что точка доступа отправляла на ноутбук, до него доходило и подтверждалось сообщением ACK. Значит, радиомодуль ноутбука исправно передаёт сигналы, и приёмник точки их ловит. Вот только кадры данных с ноута почему-то не уходят.

На самом ноутбуке пакеты продолжали поступать в драйвер ath12k, и в очереди скопилось аж несколько тысяч кадров. Прошивка подтверждала обработку лишь по нескольку кадров за раз, а оставшиеся в конечном итоге вернула с сообщением CMD_REMOVE_AGED_FRAMES — так в результате этого обрыва было потеряно 10630 кадров из 26388. В остальном драйвер вёл себя исправно.  

На стороне точки доступа счётчик rx_data в течение большинства тактов оставался на нуле (+0), за исключением редких всплесков. При этом ошибок приёма (RX errors) и повторных попыток зафиксировано не было — то есть кадры не покидали сетевую плату ноутбука. Затем плату внезапно «отпускало», и она выплёвывала всю накопившуюся очередь за две секунды: точка доступа зафиксировала скачки rx_data+3273, а затем +12498, в то время как ноутбук зарегистрировал сразу 7751 подтверждённых кадров.

Проблема явно была не на стороне ОС или эфира: уровень сигнала оставался от -31 до -42 дБм, фоновое сканирование не выполнялось, да и IP-стек на ноутбуке работал абсолютно нормально. Плюс я уже использую последнюю официальную прошивку — WLAN.HMT.1.1.c7-00108 UPSTREAM-3. Драйвер ath12k получает обратно только статусы завершения операций, а всё, что связано с отправкой кадра в эфир, определяется внутри закрытого бинарника amss.bin от Qualcomm. Так что дело в самой прошивке.

Я до сих пор не знаю, почему пропадает передача. Всплески трафика, который прорывался во время обрыва, похожи на работу планировщика отправки данных в стандартах 802.11ax/be — передачу на основе триггеров или механизм MU EDCA. Но таких настроек я на устройстве не нашёл, так что проверить эти предположения не получилось.

Пока что я переключил радиомодуль 5 Ггц с Wi-Fi 7 на Wi-Fi 6 (802.11ax) и оставил скрипт наблюдать за ним на 24 часа. Если обрывы прекратятся, значит, это проблема Wi-Fi 7 — тогда я останусь на Wi-Fi 6 и отправлю баг-репорт разработчикам ath12k. Если нет, то прошивка косячит в любом режиме, и мне останется либо писать баг-репорт, либо просто купить сетевую карту от Intel.

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


  1. CitizenOfDreams
    25.10.2026 09:35

    Мне в последний раз попадалось сетевое устройство, молча портящее данные, где-то в 2000 году. Это была сетевая карточка то ли PCI, то ли еще ISA, которая конфликтовала с кем-то по прерываниям. Время тогда было такое - джамперы с карточек уже убрали, а надежно раздавать им ресурсы еще не научились.


  1. m0xf
    25.10.2026 09:35

    Ещё раз убеждаюсь, что точки доступа с чипами Qualcomm лучше обходить стороной. Mediatek не зажимает драйверы, и можно поставить OpenWrt когда потребуется.


  1. checkpoint
    25.10.2026 09:35

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


    1. Harisgod
      25.10.2026 09:35

      Забавно, что если бы автор сделал как ты описываешь, то не было бы смысла в твоём комменте. И меня интересует: а есть ли тогда вообще хоть какой-то толк в этом вопросе?


      1. checkpoint
        25.10.2026 09:35

        Для тех, у кого радиостанция на танке, а не на транзисторах: то был комплимент автору.


  1. Revertis
    25.10.2026 09:35

    Эксплоит пишется через И!


    1. VADemon
      25.10.2026 09:35

      А пишет его ЙиЙи!



    1. Frankenstine
      25.10.2026 09:35

      Эксплоит это глагол, а эксплойт - существительное)


    1. garwall
      25.10.2026 09:35

      А город пишется как Детроит, да?


      1. Revertis
        25.10.2026 09:35

        Тупой вопрос.


        1. garwall
          25.10.2026 09:35

          просто везде одинаковый дифтонг [ɔɪ]


          1. Revertis
            25.10.2026 09:35

            Который произносят по-разному.


      1. rombell
        25.10.2026 09:35

        Мисс Хадсон и река Гудзон прекрасно сосуществуют в русском языке.

        И да, как носителю языка с довольно большим стажем и начитанностью, мне кажется правильным воин, Таиланд, эксплоит.