
Google은 무제한 서버로 syzkaller를 돌리지만, local에서 작업하기에는 자원이 제한되어있다. syzkaller dashboard는 현재 퍼징 상태, 결과 그리고 linux subsystem에 대한 적용 범위를 표시한다.
타겟 선정 전략
Coverage 섹션의 Subsystems Heatmap 분석을 확인하면 각 subsystem의 블록 수와 커버리지 비율을 확인할 수 있다.

블록 수가 많으면서 커버리지 비율이 적은 subsystem을 테스트하여 아직 탐색되지 않은 버그를 찾아보기로 했다.
후보 목록
퍼징 타겟으로 괜찮아 보이는 것
| subsystem | 이유 |
| dsa (3%, 3257 블록) | 코드량 많은데 커버리지 매우 낮음 |
| ncsi (5%, 1329 블록) | 적당한 크기, 낮은 커버리지 |
| 6lowpan (3%, 465 블록) | IoT/저전력 네트워킹, 낮은 커버리지 |
최종선택: NFC subsystem을 선택했다.
- 이유: 네트워킹은 소켓으로 데이터 입출력이 쉬워서 퍼징하기 좋음
- 파일시스템은 바이너리 블롭, 마운트/언마운트 등 복잡함
Attack Surface
nfc 커널 코드(/net/nfc) 를 분석하여 퍼징할 진입점을 파악해보자.
linux/net/nfc/
├── af_nfc.c ← AF_NFC 소켓 패밀리 등록
├── core.c ← NFC 코어 기능
├── netlink.c ← Generic Netlink 인터페이스 ⭐
├── rawsock.c ← RAW 소켓 구현
├── llcp_sock.c ← LLCP 소켓 구현 ⭐
├── llcp_core.c ← LLCP 코어
├── llcp_commands.c ← LLCP 명령어 처리
├── nci/ ← NCI (NFC Controller Interface)
├── hci/ ← HCI (Host Controller Interface)
└── digital*.c ← Digital 프로토콜
Generic Netlink 인터페이스 (netlink.c)
유저스페이스에서 Netlink를 통해 NFC 디바이스 제어하는 코드를 확인해보자.
static const struct genl_ops nfc_genl_ops[] = {
{ .cmd = NFC_CMD_GET_DEVICE, .doit = nfc_genl_get_device },
{ .cmd = NFC_CMD_DEV_UP, .doit = nfc_genl_dev_up },
{ .cmd = NFC_CMD_DEV_DOWN, .doit = nfc_genl_dev_down },
{ .cmd = NFC_CMD_START_POLL, .doit = nfc_genl_start_poll },
{ .cmd = NFC_CMD_STOP_POLL, .doit = nfc_genl_stop_poll },
{ .cmd = NFC_CMD_DEP_LINK_UP, .doit = nfc_genl_dep_link_up },
{ .cmd = NFC_CMD_DEP_LINK_DOWN, .doit = nfc_genl_dep_link_down },
{ .cmd = NFC_CMD_GET_TARGET, .dumpit = nfc_genl_dump_targets },
{ .cmd = NFC_CMD_LLC_GET_PARAMS, .doit = nfc_genl_llc_get_params },
{ .cmd = NFC_CMD_LLC_SET_PARAMS, .doit = nfc_genl_llc_set_params },
{ .cmd = NFC_CMD_LLC_SDREQ, .doit = nfc_genl_llc_sdreq },
{ .cmd = NFC_CMD_ENABLE_SE, .doit = nfc_genl_enable_se },
{ .cmd = NFC_CMD_DISABLE_SE, .doit = nfc_genl_disable_se },
{ .cmd = NFC_CMD_FW_DOWNLOAD, .doit = nfc_genl_fw_download },
{ .cmd = NFC_CMD_GET_SE, .dumpit = nfc_genl_dump_ses },
{ .cmd = NFC_CMD_SE_IO, .doit = nfc_genl_se_io },
{ .cmd = NFC_CMD_ACTIVATE_TARGET, .doit = nfc_genl_activate_target },
{ .cmd = NFC_CMD_VENDOR, .doit = nfc_genl_vendor_cmd },
};
흐름도는 다음과 같다.
User space
│
▼
sendmsg(NETLINK_GENERIC)
│
▼
nfc_genl_ops[] → 각 .doit 핸들러 함수
│
▼
nfc_genl_dev_up(), nfc_genl_start_poll(), ...
LLCP 소켓 인터페이스 (llcp_sock.c)
LLCP (Logical Link Control Protocol): NFC 데이터 전송용 프로토콜
static const struct proto_ops llcp_sock_ops = {
.family = PF_NFC,
.owner = THIS_MODULE,
.release = llcp_sock_release,
.bind = llcp_sock_bind, // ⭐ bind()
.connect = llcp_sock_connect, // ⭐ connect()
.socketpair = sock_no_socketpair,
.accept = llcp_sock_accept, // ⭐ accept()
.getname = llcp_sock_getname,
.poll = llcp_sock_poll,
.ioctl = sock_no_ioctl,
.listen = llcp_sock_listen, // ⭐ listen()
.shutdown = sock_no_shutdown,
.setsockopt = llcp_sock_setsockopt, // ⭐ setsockopt()
.getsockopt = llcp_sock_getsockopt, // ⭐ getsockopt()
.sendmsg = llcp_sock_sendmsg, // ⭐ send()
.recvmsg = llcp_sock_recvmsg, // ⭐ recv()
.mmap = sock_no_mmap,
};
RAW 소켓 인터페이스 (rawsock.c)
저수준 NFC 패킷 송수신
static const struct proto_ops rawsock_ops = {
.family = PF_NFC,
.owner = THIS_MODULE,
.release = rawsock_release,
.bind = sock_no_bind,
.connect = rawsock_connect, // ⭐
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = sock_no_getname,
.poll = datagram_poll,
.ioctl = sock_no_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.sendmsg = rawsock_sendmsg, // ⭐
.recvmsg = rawsock_recvmsg, // ⭐
.mmap = sock_no_mmap,
};
setsockopt 옵션들
// include/uapi/linux/nfc.h
#define NFC_LLCP_RW 0 // Receive Window
#define NFC_LLCP_MIUX 1 // Maximum Information Unit Extension
#define NFC_LLCP_REMOTE_MIU 2 // Remote MIU (read only)
#define NFC_LLCP_REMOTE_LTO 3 // Remote Link Timeout (read only)
#define NFC_LLCP_REMOTE_RW 4 // Remote RW (read only)
공격 표면 요약
┌─────────────────────────────────────────────────────────────┐
│ User Space │
├─────────────────────────────────────────────────────────────┤
│ socket(AF_NFC, ...) │ sendmsg(NETLINK_GENERIC, ...) │
│ │ │ │ │
│ ▼ │ ▼ │
│ ┌─────────────────┐ │ ┌──────────────────┐ │
│ │ LLCP Socket │ │ │ Generic Netlink │ │
│ │ (llcp_sock.c) │ │ │ (netlink.c) │ │
│ └────────┬────────┘ │ └────────┬─────────┘ │
├───────────┼──────────────┼──────────────┼───────────────────┤
│ │ │ │ Kernel │
│ ▼ │ ▼ │
│ llcp_sock_ops │ nfc_genl_ops │
│ - bind │ - NFC_CMD_DEV_UP │
│ - connect │ - NFC_CMD_START_POLL │
│ - sendmsg │ - NFC_CMD_ACTIVATE_TARGET │
│ - recvmsg │ - NFC_CMD_SE_IO │
│ - setsockopt │ - NFC_CMD_VENDOR │
│ - getsockopt │ - ... │
└─────────────────────────────────────────────────────────────┘
알려진 취약점 사례 (참고용)
| CVE | 유형 | 위치 |
| CVE-2021-23134 | UAF | llcp_sock_bind/connect |
| CVE-2021-47068 | UAF | llcp_sock_bind/connect (refcount) |
| 기타 | info leak | llcp_sock_recvmsg (uninitialized memory) |
Fuzzing
syzkaller config에 nfc 관련 syscall을 넣어서 테스트 해보자. syscall은 syzkaller 패키지 하위의 다음 파일에서 참고 하였다.
- syzkaller/sys/linux/socket_netlink_generic_nfc.txt
- syzkaller/sys/linux/socket_nfc.txt
"enable_syscalls": [
"socket$nl_generic",
"syz_init_net_socket$nfc_llcp",
"syz_init_net_socket$nfc_raw",
"bind$nfc_llcp",
"connect$nfc_llcp",
"connect$nfc_raw",
"accept$nfc_llcp",
"accept4$nfc_llcp",
"listen$nfc_llcp",
"setsockopt$nfc_llcp_NFC_LLCP_RW",
"setsockopt$nfc_llcp_NFC_LLCP_MIUX",
"getsockopt$nfc_llcp",
"sendmsg$nfc_llcp",
"sendmmsg$nfc_llcp",
"recvmsg$nfc_llcp",
"syz_genetlink_get_family_id$nfc",
"sendmsg$NFC_CMD_GET_DEVICE",
"sendmsg$NFC_CMD_DEV_UP",
"sendmsg$NFC_CMD_DEV_DOWN",
"sendmsg$NFC_CMD_START_POLL",
"sendmsg$NFC_CMD_ACTIVATE_TARGET",
"sendmsg$NFC_CMD_DEACTIVATE_TARGET",
"sendmsg$NFC_CMD_DEP_LINK_UP",
"sendmsg$NFC_CMD_DEP_LINK_DOWN",
"sendmsg$NFC_CMD_GET_TARGET",
"sendmsg$NFC_CMD_LLC_GET_PARAMS",
"sendmsg$NFC_CMD_LLC_SET_PARAMS",
"sendmsg$NFC_CMD_LLC_SDREQ",
"sendmsg$NFC_CMD_ENABLE_SE",
"sendmsg$NFC_CMD_DISABLE_SE",
"sendmsg$NFC_CMD_FW_DOWNLOAD",
"sendmsg$NFC_CMD_GET_SE",
"sendmsg$NFC_CMD_SE_IO",
"sendmsg$NFC_CMD_VENDOR"
]

실행되고 있으니 이제 하루밤 자고 확인해보면 될것같다.
'Security > Fuzzing' 카테고리의 다른 글
| syzbot 버그 패치 리뷰 (2025.12.18) (0) | 2025.12.18 |
|---|---|
| syzbot, qemu, gdb를 사용하여 linux kernel의 버그 수정 (0) | 2025.12.12 |
| syzkaller를 이용한 커널 퍼징 #3 syz-manager 설정 및 syz-executor 실행 (0) | 2025.12.10 |
| syzkaller를 이용한 커널 퍼징 #2 Syzkaller의 동작 구조 (0) | 2025.12.10 |
| syzkaller를 이용한 커널 퍼징 #1 Fuzzing 이란 (1) | 2025.12.10 |