Skip to content

Commit d0872de

Browse files
kzall0cparanlee
authored andcommitted
sys/linux, executor: Add KSMBD subsystem support
Introduces a new pseudo-syscall `syz_ksmbd_send_req` to fuzzing of the KSMBD module. The added functionality enables sending custom SMB2/3 requests to the KSMBD server on 127.0.0.1:445. Cc: linux-cifs@vger.kernel.org Cc: notselwyn@pwning.tech Cc: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Yunseong Kim <yskelg@gmail.com>
1 parent 68da6d9 commit d0872de

File tree

3 files changed

+230
-0
lines changed

3 files changed

+230
-0
lines changed

executor/common_linux.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5833,3 +5833,64 @@ static long syz_pidfd_open(volatile long pid, volatile long flags)
58335833
}
58345834

58355835
#endif
5836+
5837+
#if SYZ_EXECUTOR || __NR_syz_ksmbd_send_req
5838+
#include <netinet/in.h>
5839+
#include <stdio.h>
5840+
#include <string.h>
5841+
#include <sys/socket.h>
5842+
#include <sys/types.h>
5843+
5844+
#define KSMBD_BUF_SIZE 16000
5845+
5846+
static long syz_ksmbd_send_req(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
5847+
{
5848+
int sockfd;
5849+
int packet_reqlen;
5850+
int errno;
5851+
struct sockaddr_in serv_addr;
5852+
char packet_req[KSMBD_BUF_SIZE]; // max frame size
5853+
5854+
debug("[*]{syz_ksmbd_send_req} entered ksmbd send...\n");
5855+
5856+
if (a0 == 0 || a1 == 0) {
5857+
debug("[!]{syz_ksmbd_send_req} param empty\n");
5858+
return -7;
5859+
}
5860+
5861+
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
5862+
if (sockfd < 0) {
5863+
debug("[!]{syz_ksmbd_send_req} failed to create socket\n");
5864+
return -1;
5865+
}
5866+
5867+
memset(&serv_addr, '\0', sizeof(serv_addr));
5868+
serv_addr.sin_family = AF_INET;
5869+
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
5870+
serv_addr.sin_port = htons(445);
5871+
5872+
errno = connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
5873+
if (errno < 0) {
5874+
debug("[!]{syz_ksmbd_send_req} failed to connect (err: %d)\n", errno);
5875+
return errno ^ 0xff80000;
5876+
}
5877+
5878+
// prepend kcov handle to packet
5879+
packet_reqlen = a1 + 8 > KSMBD_BUF_SIZE ? KSMBD_BUF_SIZE - 8 : a1;
5880+
*(unsigned long*)packet_req = procid + 1;
5881+
memcpy(packet_req + 8, (char*)a0, packet_reqlen);
5882+
5883+
if (write(sockfd, (char*)packet_req, packet_reqlen + 8) < 0)
5884+
return -4;
5885+
5886+
if (read(sockfd, (char*)a2, a3) < 0)
5887+
return -5;
5888+
5889+
if (close(sockfd) < 0)
5890+
return -6;
5891+
5892+
debug("[+]{syz_ksmbd_send_req} successfully returned\n");
5893+
5894+
return 0;
5895+
}
5896+
#endif

pkg/vminfo/linux_syscalls.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ var linuxSyscallChecks = map[string]func(*checkContext, *prog.Syscall) string{
103103
"syz_socket_connect_nvme_tcp": linuxSyzSocketConnectNvmeTCPSupported,
104104
"syz_pidfd_open": alwaysSupported,
105105
"syz_create_resource": alwaysSupported,
106+
"syz_ksmbd_send_req": alwaysSupported,
106107
}
107108

108109
func linuxSyzOpenDevSupported(ctx *checkContext, call *prog.Syscall) string {

sys/linux/ksmbd.txt

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
include <linux/ip.h>
2+
include <linux/ipv6.h>
3+
include <linux/route.h>
4+
include <uapi/linux/if_arp.h>
5+
include <uapi/linux/netfilter_ipv6/ip6_tables.h>
6+
include <uapi/linux/wireless.h>
7+
include <uapi/linux/in.h>
8+
9+
sync_id {
10+
ProcessId int32
11+
TreeId int32
12+
} [packed]
13+
14+
_union_smb_req_id [
15+
sync_id sync_id
16+
async_id int64
17+
]
18+
19+
negotiate_message {
20+
Signature array[int8, 8]
21+
# NtLmNegotiate = 1
22+
MessageType int32
23+
NegotiateFlags int32
24+
# MBZ unless SMB3.02 or later
25+
DomainName_Length len[DomainString, int16]
26+
DomainName_MaximumLength len[DomainString, int16]
27+
DomainName_Offset offsetof[DomainString, int32]
28+
# RFC 1001 and ASCII
29+
WorkstationName_Length len[Workstationname_Buffer, int16]
30+
WorkstationName_MaximumLength len[Workstationname_Buffer, int16]
31+
WorkstationName_Offset offsetof[Workstationname_Buffer, int32]
32+
33+
# struct security_buffer for version info not present since we
34+
# do not set the version is present flag
35+
DomainString string
36+
37+
# followed by WorkstationString
38+
Workstationname_Buffer string
39+
} [packed]
40+
41+
_smb2_hdr_pre {
42+
ProtocolId const[0xfe534d42, int32be]
43+
StructureSize const[0x40, int16]
44+
CreditCharge int16
45+
Status int32
46+
} [packed]
47+
48+
_smb2_hdr_post {
49+
CreditRequest int16
50+
Flags int32
51+
NextCommand int32
52+
MessageId int64
53+
Id _union_smb_req_id
54+
SessionId int64
55+
Signature array[int8, 16]
56+
} [packed]
57+
58+
#_smb3_hdr_pre {
59+
# ProtocolId const[0xfe534d42, int32be]
60+
# StructureSize const[0x40, int16]
61+
# CreditCharge int16
62+
# ChannelSequence int16
63+
# Reserved int16
64+
#} [packed]
65+
66+
#_smb3_hdr_post {
67+
# CreditRequest int16
68+
# Flags int32
69+
# NextCommand int32
70+
# MessageId int64
71+
# Id _union_smb_req_id
72+
# SessionId int64
73+
# Signature array[int8, 16]
74+
#} [packed]
75+
76+
smb2_negotiate_req {
77+
_hdr_pre _smb2_hdr_pre
78+
Command const[0x0, int16]
79+
_hdr_post _smb2_hdr_post
80+
StructureSize const[36, int16]
81+
DialectCount len[Dialects, int16]
82+
SecurityMode int16
83+
Reserved int16
84+
Capabilities int32
85+
ClientGUID array[int8, 16]
86+
87+
# In SMB3.02 and earlier next three were MBZ le64 ClientStartTime
88+
NegotiateContextOffset int32
89+
NegotiateContextCount int16
90+
Reserved2 int16
91+
Dialects buffer[in]
92+
} [packed]
93+
94+
smb2_sess_setup_req {
95+
_hdr_pre _smb2_hdr_pre
96+
Command const[0x1, int16]
97+
_hdr_post _smb2_hdr_post
98+
StructureSize const[25, int16]
99+
Flags int8
100+
SecurityMode int8
101+
Capabilities int32
102+
Channel int32
103+
SecurityBufferOffset offsetof[Buffer, int16]
104+
SecurityBufferLength len[Buffer, int16]
105+
PreviousSessionId int64
106+
107+
# variable length GSS security buffer
108+
Buffer negotiate_message
109+
} [packed]
110+
111+
smb2_echo_req {
112+
_hdr_pre _smb2_hdr_pre
113+
Command const[0xd, int16]
114+
_hdr_post _smb2_hdr_post
115+
StructureSize2 const[4, int16]
116+
Reserved int16
117+
} [packed]
118+
119+
smbd_buffer_descriptor_v1 {
120+
offset int64
121+
token int32
122+
length int32
123+
# followed by Smbd_Buffer
124+
smb2_read_req_buffer string
125+
} [packed]
126+
127+
smb2_read_req {
128+
_hdr_pre _smb2_hdr_pre
129+
Command const[0x8, int16]
130+
_hdr_post _smb2_hdr_post
131+
# Must be 49
132+
StructureSize const[49, int16]
133+
# offset from start of SMB2 header to place read
134+
Padding int8
135+
# MBZ unless SMB3.02 or later
136+
Flags int8
137+
Length int32
138+
Offset int64
139+
PersistentFileId int64
140+
VolatileFileId int64
141+
MinimumCount int32
142+
# MBZ except for SMB3 or later
143+
Channel int32
144+
RemainingBytes int32
145+
ReadChannelInfoOffset offsetof[Buffer, int16]
146+
ReadChannelInfoLength len[Buffer, int16]
147+
Buffer smbd_buffer_descriptor_v1
148+
} [packed]
149+
150+
_union_smb2_req [
151+
smb2_negotiate_req smb2_negotiate_req
152+
smb2_sess_setup_req smb2_sess_setup_req
153+
smb2_echo_req smb2_echo_req
154+
smb2_read_req smb2_read_req
155+
] [varlen]
156+
157+
smb2_req {
158+
req_base _union_smb2_req
159+
req_andx1 optional[_union_smb2_req]
160+
req_andx2 optional[_union_smb2_req]
161+
} [packed]
162+
163+
smb2_req_pdu {
164+
_pdu_size len[req, int32be]
165+
req smb2_req
166+
} [packed]
167+
168+
syz_ksmbd_send_req(req_packet ptr[in, smb2_req_pdu], req_len len[req_packet], res_packet buffer[out], res_len len[res_packet])

0 commit comments

Comments
 (0)