From 649b8ce38fc8d90127e8c3d5d62a494a86fb1a01 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 18 Jul 2022 16:18:33 +0200 Subject: [PATCH] cache: validate handle string length Maximum supported string length for handle is NFT_NAME_MAXLEN, report an error if user is exceeding this limit. By validating from the cache evaluation phase, input is validated for the native and json parsers. Conflict: add struct list_head *msgs; Reference: https://git.netfilter.org/nftables/commit?id=649b8ce38fc8d90127e8c3d5d62a494a86fb1a01 Signed-off-by: Pablo Neira Ayuso --- src/cache.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/src/cache.c b/src/cache.c index c1f0972..828e4cc 100644 --- a/src/cache.c +++ b/src/cache.c @@ -16,6 +16,7 @@ #include #include #include +#include static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags) { @@ -58,6 +59,109 @@ static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags) return flags; } +static int nft_handle_validate(const struct cmd *cmd, struct list_head *msgs) +{ + const struct handle *h = &cmd->handle; + const struct location *loc; + + switch (cmd->obj) { + case CMD_OBJ_TABLE: + if (h->table.name && + strlen(h->table.name) > NFT_NAME_MAXLEN) { + loc = &h->table.location; + goto err_name_too_long; + } + break; + case CMD_OBJ_RULE: + case CMD_OBJ_CHAIN: + case CMD_OBJ_CHAINS: + if (h->table.name && + strlen(h->table.name) > NFT_NAME_MAXLEN) { + loc = &h->table.location; + goto err_name_too_long; + } + if (h->chain.name && + strlen(h->chain.name) > NFT_NAME_MAXLEN) { + loc = &h->chain.location; + goto err_name_too_long; + } + break; + case CMD_OBJ_ELEMENTS: + case CMD_OBJ_SET: + case CMD_OBJ_SETS: + case CMD_OBJ_MAP: + case CMD_OBJ_MAPS: + case CMD_OBJ_METER: + case CMD_OBJ_METERS: + if (h->table.name && + strlen(h->table.name) > NFT_NAME_MAXLEN) { + loc = &h->table.location; + goto err_name_too_long; + } + if (h->set.name && + strlen(h->set.name) > NFT_NAME_MAXLEN) { + loc = &h->set.location; + goto err_name_too_long; + } + break; + case CMD_OBJ_FLOWTABLE: + case CMD_OBJ_FLOWTABLES: + if (h->table.name && + strlen(h->table.name) > NFT_NAME_MAXLEN) { + loc = &h->table.location; + goto err_name_too_long; + } + if (h->flowtable.name && + strlen(h->flowtable.name) > NFT_NAME_MAXLEN) { + loc = &h->flowtable.location; + goto err_name_too_long; + } + break; + case CMD_OBJ_INVALID: + case CMD_OBJ_EXPR: + case CMD_OBJ_RULESET: + case CMD_OBJ_MARKUP: + case CMD_OBJ_MONITOR: + case CMD_OBJ_SETELEMS: + case CMD_OBJ_HOOKS: + break; + case CMD_OBJ_COUNTER: + case CMD_OBJ_COUNTERS: + case CMD_OBJ_QUOTA: + case CMD_OBJ_QUOTAS: + case CMD_OBJ_LIMIT: + case CMD_OBJ_LIMITS: + case CMD_OBJ_SECMARK: + case CMD_OBJ_SECMARKS: + case CMD_OBJ_SYNPROXY: + case CMD_OBJ_SYNPROXYS: + case CMD_OBJ_CT_HELPER: + case CMD_OBJ_CT_HELPERS: + case CMD_OBJ_CT_TIMEOUT: + case CMD_OBJ_CT_EXPECT: + if (h->table.name && + strlen(h->table.name) > NFT_NAME_MAXLEN) { + loc = &h->table.location; + goto err_name_too_long; + } + if (h->obj.name && + strlen(h->obj.name) > NFT_NAME_MAXLEN) { + loc = &h->obj.location; + goto err_name_too_long; + } + break; + } + + return 0; + +err_name_too_long: + erec_queue(error(loc, "name too long, %d characters maximum allowed", + NFT_NAME_MAXLEN), + msgs); + return -1; +} + + static unsigned int evaluate_cache_del(struct cmd *cmd, unsigned int flags) { switch (cmd->obj) { @@ -121,8 +225,12 @@ unsigned int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds) { unsigned int flags = NFT_CACHE_EMPTY; struct cmd *cmd; + struct list_head *msgs; list_for_each_entry(cmd, cmds, list) { + if (nft_handle_validate(cmd, msgs) < 0) + return -1; + switch (cmd->op) { case CMD_ADD: case CMD_INSERT: -- 2.33.0