diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-09-30 18:12:34 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-09-30 18:12:34 +0200 |
commit | 9470040d53ca7136b54f32507fe3d31d12736d22 (patch) | |
tree | be20563d91f26648255dfb09b2c7d9afd44f8169 /iptables/nft.c | |
parent | 1f932f08a17c55f1689a432433f9f2a0cf6f014f (diff) |
iptables-compat: fix use after free in the batch send path
Release the batch pages once they have been sent via sendmsg().
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'iptables/nft.c')
-rw-r--r-- | iptables/nft.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/iptables/nft.c b/iptables/nft.c index 8c91e998..a4cea224 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -142,6 +142,18 @@ static void mnl_nft_set_sndbuffer(const struct mnl_socket *nl) nlbuffsiz = newbuffsiz; } +static void mnl_nft_batch_reset(void) +{ + struct batch_page *batch_page, *next; + + list_for_each_entry_safe(batch_page, next, &batch_page_list, head) { + list_del(&batch_page->head); + free(batch_page->batch); + free(batch_page); + batch_num_pages--; + } +} + static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl) { static const struct sockaddr_nl snl = { @@ -154,12 +166,12 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl) .msg_iov = iov, .msg_iovlen = batch_num_pages, }; - struct batch_page *batch_page, *next; - int i = 0; + struct batch_page *batch_page; + int i = 0, ret; mnl_nft_set_sndbuffer(nl); - list_for_each_entry_safe(batch_page, next, &batch_page_list, head) { + list_for_each_entry(batch_page, &batch_page_list, head) { iov[i].iov_base = mnl_nlmsg_batch_head(batch_page->batch); iov[i].iov_len = mnl_nlmsg_batch_size(batch_page->batch); i++; @@ -169,13 +181,12 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl) mnl_nlmsg_batch_size(batch_page->batch), sizeof(struct nfgenmsg)); #endif - list_del(&batch_page->head); - free(batch_page->batch); - free(batch_page); - batch_num_pages--; } - return sendmsg(mnl_socket_get_fd(nl), &msg, 0); + ret = sendmsg(mnl_socket_get_fd(nl), &msg, 0); + mnl_nft_batch_reset(); + + return ret; } static int cb_err(const struct nlmsghdr *nlh, void *data) |