diff options
| author | Roy Marples <roy@marples.name> | 2020-05-21 17:03:54 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-05-21 17:03:54 +0100 |
| commit | 79db244442f6d77b3031a277d4fa536d7a84860d (patch) | |
| tree | 088cf9d640228cf353a27fe70cd8dd1b5b1c2671 /src/privsep-inet.c | |
| parent | 22a703a7a3ef6b297371a6b61cffacb5556a33f9 (diff) | |
| download | dhcpcd-79db244442f6d77b3031a277d4fa536d7a84860d.tar.xz | |
privsep: Validate ICMP messages we send as well
Diffstat (limited to 'src/privsep-inet.c')
| -rw-r--r-- | src/privsep-inet.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/src/privsep-inet.c b/src/privsep-inet.c index c5233024..8bf0474c 100644 --- a/src/privsep-inet.c +++ b/src/privsep-inet.c @@ -29,6 +29,9 @@ #include <sys/socket.h> #include <sys/types.h> +#include <netinet/in.h> +#include <netinet/icmp6.h> + #include <assert.h> #include <errno.h> #include <signal.h> @@ -201,7 +204,7 @@ ps_inet_startcb(void *arg) } static bool -ps_inet_udpports(struct msghdr *msg, uint16_t sport, uint16_t dport) +ps_inet_validudp(struct msghdr *msg, uint16_t sport, uint16_t dport) { struct udphdr udp; struct iovec *iov = msg->msg_iov; @@ -219,6 +222,32 @@ ps_inet_udpports(struct msghdr *msg, uint16_t sport, uint16_t dport) return true; } +#ifdef INET6 +static bool +ps_inet_validnd(struct msghdr *msg) +{ + struct icmp6_hdr icmp6; + struct iovec *iov = msg->msg_iov; + + if (msg->msg_iovlen == 0 || iov->iov_len < sizeof(icmp6)) { + errno = EINVAL; + return false; + } + + memcpy(&icmp6, iov->iov_base, sizeof(icmp6)); + switch(icmp6.icmp6_type) { + case ND_ROUTER_SOLICIT: + case ND_NEIGHBOR_ADVERT: + break; + default: + errno = EPERM; + return false; + } + + return true; +} +#endif + static ssize_t ps_inet_sendmsg(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) @@ -235,19 +264,21 @@ ps_inet_sendmsg(struct dhcpcd_ctx *ctx, switch (psm->ps_cmd) { #ifdef INET case PS_BOOTP: - if (!ps_inet_udpports(msg, BOOTPC, BOOTPS)) + if (!ps_inet_validudp(msg, BOOTPC, BOOTPS)) return -1; s = ctx->udp_wfd; break; #endif #if defined(INET6) && !defined(__sun) case PS_ND: + if (!ps_inet_validnd(msg)) + return -1; s = ctx->nd_fd; break; #endif #ifdef DHCP6 case PS_DHCP6: - if (!ps_inet_udpports(msg, DHCP6_CLIENT_PORT,DHCP6_SERVER_PORT)) + if (!ps_inet_validudp(msg, DHCP6_CLIENT_PORT,DHCP6_SERVER_PORT)) return -1; s = ctx->dhcp6_wfd; break; |
