summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Oester <kernel@linuxace.com>2013-08-15 10:19:11 -0700
committerPablo Neira Ayuso <pablo@netfilter.org>2013-08-17 11:47:56 +0200
commit5075879c3370f7d070b40c2f1c8e8039a187d046 (patch)
treee39378d115e0b377fb305582f4451e1755fe7db5
parentd0218ea4573837d775c3e605913a45021f1526b9 (diff)
datatype: validate port number in inet_service_type_parse
At present, nft accepts out of range port values such as in this example: nft add rule ip filter input tcp dport 123456 accept Attached patch adds checks for both integer overflow and 16 bit overflow, and avoids getaddrinfo call in the (common) case of digit input. Example above now produces this output: <cmdline>:1:36-41: Error: Service out of range add rule ip filter input tcp dport 123456 accept ^^^^^^ Signed-off-by: Phil Oester <kernel@linuxace.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/datatype.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/src/datatype.c b/src/datatype.c
index 55368eed..be328518 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
+#include <errno.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <linux/types.h>
@@ -500,18 +501,30 @@ static struct error_record *inet_service_type_parse(const struct expr *sym,
{
struct addrinfo *ai;
uint16_t port;
+ uintmax_t i;
int err;
+ char *end;
+
+ errno = 0;
+ i = strtoumax(sym->identifier, &end, 0);
+ if (sym->identifier != end && *end == '\0') {
+ if (errno == ERANGE || i > UINT16_MAX)
+ return error(&sym->location, "Service out of range");
+
+ port = i;
+ } else {
+ err = getaddrinfo(NULL, sym->identifier, NULL, &ai);
+ if (err != 0)
+ return error(&sym->location, "Could not resolve service: %s",
+ gai_strerror(err));
+
+ port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
+ freeaddrinfo(ai);
+ }
- err = getaddrinfo(NULL, sym->identifier, NULL, &ai);
- if (err != 0)
- return error(&sym->location, "Could not resolve service: %s",
- gai_strerror(err));
-
- port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
*res = constant_expr_alloc(&sym->location, &inet_service_type,
BYTEORDER_BIG_ENDIAN,
sizeof(port) * BITS_PER_BYTE, &port);
- freeaddrinfo(ai);
return NULL;
}