summaryrefslogtreecommitdiffstats
path: root/src/privsep-inet.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-05-21 16:53:54 +0100
committerRoy Marples <roy@marples.name>2020-05-21 16:53:54 +0100
commit22a703a7a3ef6b297371a6b61cffacb5556a33f9 (patch)
treef93fc01f43d9da6dca16ddfc58701978a0023797 /src/privsep-inet.c
parent4fc992947e26b7662dee02285708a2a5c8514c24 (diff)
downloaddhcpcd-22a703a7a3ef6b297371a6b61cffacb5556a33f9.tar.xz
privsep: Validate UDP ports
Just like we filter the ioctls.
Diffstat (limited to 'src/privsep-inet.c')
-rw-r--r--src/privsep-inet.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/privsep-inet.c b/src/privsep-inet.c
index bc8a3974..c5233024 100644
--- a/src/privsep-inet.c
+++ b/src/privsep-inet.c
@@ -200,6 +200,25 @@ ps_inet_startcb(void *arg)
return ret;
}
+static bool
+ps_inet_udpports(struct msghdr *msg, uint16_t sport, uint16_t dport)
+{
+ struct udphdr udp;
+ struct iovec *iov = msg->msg_iov;
+
+ if (msg->msg_iovlen == 0 || iov->iov_len < sizeof(udp)) {
+ errno = EINVAL;
+ return false;
+ }
+
+ memcpy(&udp, iov->iov_base, sizeof(udp));
+ if (udp.uh_sport != htons(sport) || udp.uh_dport != htons(dport)) {
+ errno = EPERM;
+ return false;
+ }
+ return true;
+}
+
static ssize_t
ps_inet_sendmsg(struct dhcpcd_ctx *ctx,
struct ps_msghdr *psm, struct msghdr *msg)
@@ -216,6 +235,8 @@ ps_inet_sendmsg(struct dhcpcd_ctx *ctx,
switch (psm->ps_cmd) {
#ifdef INET
case PS_BOOTP:
+ if (!ps_inet_udpports(msg, BOOTPC, BOOTPS))
+ return -1;
s = ctx->udp_wfd;
break;
#endif
@@ -226,6 +247,8 @@ ps_inet_sendmsg(struct dhcpcd_ctx *ctx,
#endif
#ifdef DHCP6
case PS_DHCP6:
+ if (!ps_inet_udpports(msg, DHCP6_CLIENT_PORT,DHCP6_SERVER_PORT))
+ return -1;
s = ctx->dhcp6_wfd;
break;
#endif