Skip to content

Commit 900998f

Browse files
masc2008anchao
authored andcommitted
netdb/dns: validate nameserver input in dns_add_nameserver
It can't be zero or broadcast addr for a valid dns server. Signed-off-by: shichunma <masc2008@gmail.com>
1 parent 5f6e1e2 commit 900998f

1 file changed

Lines changed: 81 additions & 21 deletions

File tree

libs/libc/netdb/lib_dnsaddserver.c

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,46 @@ static int dns_check_nameserver(FAR void *arg, FAR struct sockaddr *addr,
104104
return OK;
105105
}
106106

107+
#ifdef CONFIG_NETDB_RESOLVCONF
108+
static int dns_is_valid_nameserver(FAR const struct sockaddr *addr)
109+
{
110+
#ifdef CONFIG_NET_IPv4
111+
if (addr->sa_family == AF_INET)
112+
{
113+
FAR const struct sockaddr_in *in4 =
114+
(FAR const struct sockaddr_in *)addr;
115+
116+
if (net_ipv4addr_cmp(in4->sin_addr.s_addr, INADDR_ANY) ||
117+
net_ipv4addr_cmp(in4->sin_addr.s_addr, INADDR_BROADCAST) ||
118+
IN_MULTICAST(NTOHL(in4->sin_addr.s_addr)))
119+
{
120+
return -EINVAL;
121+
}
122+
123+
return OK;
124+
}
125+
#endif
126+
127+
#ifdef CONFIG_NET_IPv6
128+
if (addr->sa_family == AF_INET6)
129+
{
130+
FAR const struct sockaddr_in6 *in6 =
131+
(FAR const struct sockaddr_in6 *)addr;
132+
133+
if (IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr) ||
134+
IN6_IS_ADDR_MULTICAST(&in6->sin6_addr))
135+
{
136+
return -EINVAL;
137+
}
138+
139+
return OK;
140+
}
141+
#endif
142+
143+
return -ENOSYS;
144+
}
145+
#endif
146+
107147
/****************************************************************************
108148
* Public Functions
109149
****************************************************************************/
@@ -119,7 +159,7 @@ static int dns_check_nameserver(FAR void *arg, FAR struct sockaddr *addr,
119159
#ifdef CONFIG_NETDB_RESOLVCONF
120160
int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
121161
{
122-
FAR FILE *stream;
162+
FAR FILE *stream = NULL;
123163
char addrstr[DNS_MAX_ADDRSTR];
124164
union dns_addr_u dns_addr;
125165
FAR uint16_t *pport;
@@ -131,32 +171,30 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
131171
#endif
132172
int ret;
133173

134-
stream = fopen(CONFIG_NETDB_RESOLVCONF_PATH, "a+");
135-
if (stream == NULL)
174+
if (addr == NULL)
136175
{
137-
ret = -get_errno();
138-
nerr("ERROR: Failed to open %s: %d\n",
139-
CONFIG_NETDB_RESOLVCONF_PATH, ret);
140-
DEBUGASSERT(ret < 0);
141-
return ret;
176+
return -EINVAL;
142177
}
143178

144-
dns_lock();
145-
146179
#ifdef CONFIG_NET_IPv4
147180
/* Check for an IPv4 address */
148181

149182
if (addr->sa_family == AF_INET)
150183
{
151184
if (addrlen < sizeof(struct sockaddr_in))
152185
{
153-
ret = -EINVAL;
154-
goto errout;
186+
return -EINVAL;
155187
}
156188
else
157189
{
158190
FAR struct sockaddr_in *in4 = (FAR struct sockaddr_in *)addr;
159191

192+
ret = dns_is_valid_nameserver(addr);
193+
if (ret < 0)
194+
{
195+
return ret;
196+
}
197+
160198
copylen = sizeof(struct sockaddr_in);
161199
pport = &dns_addr.ipv4.sin_port;
162200
if (inet_ntop(AF_INET, &in4->sin_addr, addrstr,
@@ -165,7 +203,7 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
165203
ret = -get_errno();
166204
nerr("ERROR: inet_ntop failed: %d\n", ret);
167205
DEBUGASSERT(ret < 0);
168-
goto errout;
206+
return ret;
169207
}
170208
}
171209
}
@@ -179,13 +217,18 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
179217
{
180218
if (addrlen < sizeof(struct sockaddr_in6))
181219
{
182-
ret = -EINVAL;
183-
goto errout;
220+
return -EINVAL;
184221
}
185222
else
186223
{
187224
FAR struct sockaddr_in6 *in6 = (FAR struct sockaddr_in6 *)addr;
188225

226+
ret = dns_is_valid_nameserver(addr);
227+
if (ret < 0)
228+
{
229+
return ret;
230+
}
231+
189232
copylen = sizeof(struct sockaddr_in6);
190233
pport = &dns_addr.ipv6.sin6_port;
191234
if (inet_ntop(AF_INET6, &in6->sin6_addr, addrstr,
@@ -194,18 +237,29 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
194237
ret = -get_errno();
195238
nerr("ERROR: inet_ntop failed: %d\n", ret);
196239
DEBUGASSERT(ret < 0);
197-
goto errout;
240+
return ret;
198241
}
199242
}
200243
}
201244
else
202245
#endif
203246
{
204247
nerr("ERROR: Unsupported family: %d\n", addr->sa_family);
205-
ret = -ENOSYS;
206-
goto errout;
248+
return -ENOSYS;
249+
}
250+
251+
stream = fopen(CONFIG_NETDB_RESOLVCONF_PATH, "a+");
252+
if (stream == NULL)
253+
{
254+
ret = -get_errno();
255+
nerr("ERROR: Failed to open %s: %d\n",
256+
CONFIG_NETDB_RESOLVCONF_PATH, ret);
257+
DEBUGASSERT(ret < 0);
258+
return ret;
207259
}
208260

261+
dns_lock();
262+
209263
memcpy(&dns_addr.addr, addr, copylen);
210264

211265
/* A port number of zero means to use the default DNS server port number */
@@ -227,9 +281,7 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
227281
ret = OK;
228282
}
229283

230-
dns_unlock();
231-
fclose(stream);
232-
return ret;
284+
goto errout;
233285
}
234286

235287
#if CONFIG_NETDB_DNSSERVER_NAMESERVERS > 1
@@ -246,6 +298,14 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
246298

247299
fclose(stream);
248300
stream = fopen(CONFIG_NETDB_RESOLVCONF_PATH, "w");
301+
if (stream == NULL)
302+
{
303+
ret = -get_errno();
304+
nerr("ERROR: Failed to open %s: %d\n",
305+
CONFIG_NETDB_RESOLVCONF_PATH, ret);
306+
DEBUGASSERT(ret < 0);
307+
goto errout;
308+
}
249309

250310
/* Write the new record to the head of the resolv.conf file. */
251311

0 commit comments

Comments
 (0)