Reddit

Spent three years blaming rsync and SSH. It was a DMA cache bug in Qualcomm's Wi-Fi driver corrupting 64 bytes at a time

3년 동안 rsync와 SSH를 의심했습니다. Qualcomm Wi-Fi 드라이버의 DMA 캐시 버그가 한 번에 64바이트씩 데이터를 망가뜨렸습니다

TP-Link EAP770의 Qualcomm 드라이버가 재사용한 패킷 버퍼에서 캐시 동기화를 빠뜨려 TCP 데이터 일부를 손상시켰습니다. 작성자는 커널 취약점을 이용해 AP 설정을 바꾸고 오프로드를 끈 뒤, 8% 속도 저하와 맞바꿔 장시간 테스트에서 손상이 사라지는 것을 확인했습니다.

에디터 노트

오프로드를 끈 뒤 같은 방향의 장시간 전송에서 손상 블록이 사라졌다는 결과는 원인 추정에 가장 직접적인 근거입니다. 반면 손상 과정 자체를 장치에서 재현하거나 드라이버를 수정해 검증한 결과는 아니며, 작성자도 PPE 내부의 정확한 순서는 확인할 수 없다고 밝혔습니다. 속도 저하와 함께 개선된 실험은 드라이버 경로를 강하게 가리키지만, 원인 설명과 검증된 수정은 구분해야 합니다. Reddit에서는 작성자가 비슷한 코드 패턴을 다른 드라이버에서도 봤다고 했지만 하드웨어 테스트는 하지 않았다고 선을 그었습니다. 댓글 하나는 AI가 잘못된 원인 분석을 유도했을 가능성을 제기했으나 근거를 덧붙이지 않았습니다. 현재 자료가 뒷받침하는 범위는 EAP770에서 오프로드를 끄자 손상이 관측되지 않았다는 결과와 qca-nss-dp 코드에서 확인한 캐시 처리 경로까지입니다. 다른 드라이버의 유사 문제와 노트북 무선 끊김의 원인은 미확인 상태입니다.

AI 요약

대용량 파일 전송이 자주 실패하자 작성자는 처음에 rsync와 SSH를 의심했습니다. Tailscale을 쓰고 전송 오류가 사라진 뒤에는 조사를 멈췄지만, 몇 년 뒤 NixOS 파일 다운로드와 Git 복제에서도 TLS의 bad record mac 오류를 만났습니다. 패킷 캡처에는 TCP 체크섬이 유효한데도 1440바이트 세그먼트 안의 64바이트가 잘못된 사례가 잡혔습니다. TCP는 데이터를 받아들였고 TLS가 손상을 발견했습니다.

손상 경로 추적

유선 장비에서 Wi-Fi 노트북으로 여러 TCP 스트림을 보내자 8192 MiB 중 64바이트 블록 세 곳이 손상됐습니다. 반대 방향 전송과 유선 장비 사이의 전송은 깨끗했습니다. 노트북의 무선 카드와 케이블을 바꿔도 현상이 남았고, 무선 프레임의 CCMP MIC도 정상이었습니다. 작성자는 손상 위치가 AP 내부의 Ethernet-Wi-Fi 브리지에 있다고 좁혔습니다. 64바이트가 IPQ9574 CPU의 캐시 라인 크기라는 점과 Qualcomm SFE/PPE 오프로드가 브리지 트래픽을 가속하면서 체크섬을 다시 계산한다는 점을 근거로 캐시 또는 DMA 경로를 조사했습니다.

원인으로 지목한 드라이버 동작

작성자가 확인한 Qualcomm qca-nss-dp 경로에서는 송신 뒤 패킷 버퍼를 재활용 목록에 돌려보냅니다. 이때 fast_recycled 표시를 남기고, 다음 수신에서 버퍼 전체를 무효화하는 캐시 작업을 건너뜁니다. 하지만 송신 때 캐시를 정리한 범위는 이후 수신 영역 전체와 맞지 않습니다. 작성자의 설명에 따르면 NIC가 새 패킷을 DRAM에 기록한 뒤 이전 데이터의 더티 캐시 라인이 기록되면 새 패킷 일부를 덮어쓸 수 있습니다. 그 뒤 SFE/PPE가 손상된 데이터로 체크섬을 계산해 TCP가 잘못된 내용을 정상 패킷으로 받아들이고 TLS나 SSH의 무결성 검사가 오류를 냅니다.

AP 설정을 바꾸기까지

문제를 멈추려면 /sys/sfe/l2_feature와 /sys/sfe/ppe_rfs_feature를 0으로 설정해야 했지만, TP-Link의 SSH 셸은 root 권한이 없었고 관리 화면에도 설정이 없었습니다. EAP770 v1은 지원 종료 상태였으며 새 펌웨어도 제공되지 않았습니다. 작성자는 CVE-2022-0185와 pipe-buffer 조작을 결합한 권한 상승 익스플로잇을 구성해 AP에서 설정을 바꿨습니다. QEMU에서 체인을 만든 뒤 실제 장치의 주소 차이와 커널 메모리 배치를 조정했고, 익스플로잇은 재부팅 뒤 다시 실행해야 했습니다. 오프로드 설정은 재부팅 때 복구되므로 NAS에서 감시해 필요하면 다시 실행하도록 했습니다.

오프로드를 켠 상태에서는 LAN에서 Wi-Fi로 8192 MiB를 보낼 때 103.4 MiB/s 속도에서 손상된 블록 세 곳이 나왔습니다. 끈 상태에서는 95.4 MiB/s로 속도가 약 8% 떨어졌지만, 밤새 실행한 테스트에서 손상 블록은 없었습니다. 작성자는 이후 대용량 다운로드도 매번 정상 동작했다고 밝혔습니다. Wi-Fi에서 LAN으로 보내는 업로드는 수정 전에도 깨끗했습니다.

별도로 남은 무선 끊김

작성자는 노트북의 Qualcomm WCN785x 카드가 몇 시간마다 1~4분 동안 송신을 멈추는 현상도 추적했습니다. AP에는 프레임이 도착하지 않았고 노트북 드라이버에는 전송 대기열이 쌓였습니다. 무선 펌웨어가 일부 프레임만 확인한 뒤 나머지를 드라이버에 돌려줬고, 이후 카드가 대기열을 한꺼번에 전송했습니다. 작성자는 이 현상이 앞서 추적한 데이터 손상과 별개의 버그라고 구분했습니다. 원인은 확인하지 못했으며, AP를 Wi-Fi 6 모드로 바꾼 뒤 24시간 관찰해 Wi-Fi 7 모드와 관련 있는지 확인하려 했습니다.

Reddit 반응

  • @u/adminvasheypomoiki — 작성자입니다. 글 대부분은 AP 루팅 이야기이고, 커널 문제는 DMA 캐시 일관성 버그 부분입니다. 드라이버가 재사용한 수신 버퍼의 캐시 무효화를 건너뛰어 이전 패킷의 더티 라인이 DMA 뒤에 새 패킷을 덮어쓰고, 오프로드 엔진이 손상된 데이터로 체크섬을 다시 계산한다고 봅니다. 다른 드라이버에서도 비슷한 패턴을 코드로만 봤고 테스트하지는 않았습니다. qca-nss-dp 패치를 어디에 보내야 할지 모르겠습니다. GitHub 저장소는 미러입니다. 캐시 일관성 문제를 어디서 논의할지도 모르겠습니다.
    • @u/WildCard65 — 커널과 내장 모듈 패치는 메일링 리스트로 보낸다는 것만 압니다.
    • @u/sunny0_0 — 버그 신고가 접수된 곳이 있나요?
  • @u/R3V0LU710N_05 — 하하. 그래도 결국 알아내셨네요.
  • @u/SPEZ_IS_A_JABRONI — rsync를 탓했다니 놀랍네요.
    • @u/adminvasheypomoiki — 글을 읽어보세요. rsync는 MAC 검사 오류 같은 이상한 메시지로 실패했고, 직접 SSH를 쓰면 동작했으며 TCP 체크섬은 정상이었습니다.
    • @u/xeoron — TP-Link를 위험 신호로 보지 않은 것도 놀랍네요.
  • @u/ipsirc — 나중에 집 안 트래픽에 Tailscale을 쓰자 재시도가 필요 없어졌다는 대목이 늘 이렇습니다. 저는 WireGuard나 OpenVPN 없이 rsync를 실행한 적이 없습니다.
    • @u/autogyrophilia — 임질을 치료할 필요가 없다고 말하면서 늘 콘돔을 쓴다는 것과 같습니다.
    • @u/Gold-Supermarket-342 — 마음에 드네요.
    • @u/adminvasheypomoiki — VLAN도 있는 로컬 네트워크인데 왜 그런가요?
  • @u/AminoOxi — Qualcomm이라니, 제발요.
  • @u/RayneYoruka — 이런. 읽어볼 만하네요.
  • @u/mrtruthiness — 제 생각에는 형편없는 글입니다. 요약하면 작성자는 액세스 포인트 문제를 겪었고 의심스러운 이유로 여러 대상을 탓했습니다. 결국 Opus 5.5의 환각에 오도돼 마지막 원인을 믿는 것일 수도 있습니다. 누가 알겠어요.

원문: 개인 블로그 / 번역·요약: Trawling