summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2022-09-30 17:51:55 +0200
committerPhil Sutter <phil@nwl.cc>2022-10-01 13:44:10 +0200
commitfca04aa7a53252464c289997e71de10189971da6 (patch)
tree9b0c503b13a67aea723736db0b310b760863a8e4
parenteafe731a50058ed59305ee4ab1ea2d63d6c4e86e (diff)
extensions: among: Fix for use with ebtables-restore
When restoring multiple rules which use among match, new size may be smaller than the old one which caused invalid writes by the memcpy() call. Expect this and realloc the match only if it needs to grow. Also use realloc instead of freeing and allocating from scratch. Fixes: 26753888720d8 ("nft: bridge: Rudimental among extension support") Signed-off-by: Phil Sutter <phil@nwl.cc>
-rw-r--r--extensions/libebt_among.c14
1 files changed, 6 insertions, 8 deletions
diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c
index c607a775..1eab2019 100644
--- a/extensions/libebt_among.c
+++ b/extensions/libebt_among.c
@@ -119,7 +119,6 @@ static int bramong_parse(int c, char **argv, int invert,
struct xt_entry_match **match)
{
struct nft_among_data *data = (struct nft_among_data *)(*match)->data;
- struct xt_entry_match *new_match;
bool have_ip, dst = false;
size_t new_size, cnt;
struct stat stats;
@@ -170,18 +169,17 @@ static int bramong_parse(int c, char **argv, int invert,
new_size *= sizeof(struct nft_among_pair);
new_size += XT_ALIGN(sizeof(struct xt_entry_match)) +
sizeof(struct nft_among_data);
- new_match = xtables_calloc(1, new_size);
- memcpy(new_match, *match, (*match)->u.match_size);
- new_match->u.match_size = new_size;
- data = (struct nft_among_data *)new_match->data;
+ if (new_size > (*match)->u.match_size) {
+ *match = xtables_realloc(*match, new_size);
+ (*match)->u.match_size = new_size;
+ data = (struct nft_among_data *)(*match)->data;
+ }
+
have_ip = nft_among_pairs_have_ip(optarg);
poff = nft_among_prepare_data(data, dst, cnt, invert, have_ip);
parse_nft_among_pairs(data->pairs + poff, optarg, cnt, have_ip);
- free(*match);
- *match = new_match;
-
if (c == AMONG_DST_F || c == AMONG_SRC_F) {
munmap(argv, flen);
close(fd);