PunchNAF flew 6,100 hours, consumed 10m litres fuel — SpokesmanThe Jerusalem PostOver 50,000 killed in Europe over summer due to worst heat wave on recordRai NewsSci, Soelden, gigante maschile: Braathen domina prima manche, Borsotti è il migliore degli azzurriInquirer15 passengers, driver hurt as jeepney overturns in QuezonESPNIt's time for El Clásico! All you need to know about Barça vs. Madrid, the biggest match in club soccerDaily MaverickSMOOTH OPERATOR: Gayton Mckenzie’s gift of the gab is both his blessing and his curse한겨레“죽도록 일 더 해서 돈 더 벌어라? 정부가 할 소리냐”…이 대통령 발언에 비판 확산ZDF heuteEntdecken Sie das ZDF-NachrichtenstudioBBC News BrasilAs pesquisas para presidente na véspera do 2º turno — o que diziam em 2018, 2022 e o que mostram agoraIl Fatto Quotidiano“Per cantare Aeroplano con gli 883 ho preso un milione di lire. Un giorno Cecchetto mi ha detto ‘non siamo le persone giuste per te, meglio chiudere il contratto'”: parla Caterina RappoccioSportstarTamil Nadu head coach Yo Mahesh hopes for an encore at home despite rain threatThe South AfricanCarte Blanche coming up: Warning bells
The Daily Newsstand · Free, Always
Sunday, October 25, 2026

[Перевод] Хотел просто скачать ISO, в итоге написал эксплойт для ядра

Translate

Моя точка доступа 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.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.