Zero pad private area, otherwise we expose private kernel pointer to userspace. This patch also zero the tail area after the ->matchsize and ->targetsize that results from XT_ALIGN(). Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables") Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- net/netfilter/nft_compat.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 32535eea51b2..32f0b122db21 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c @@ -293,13 +293,28 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr) { const struct xt_target *target = expr->ops->data; + size_t size = XT_ALIGN(target->targetsize); void *info = nft_expr_priv(expr); + struct nlattr *nla; if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) || - nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) || - nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(target->targetsize), info)) + nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision))) goto nla_put_failure; + nla = nla_reserve(skb, NFTA_TARGET_INFO, size); + if (!nla) + goto nla_put_failure; + + if (target->usersize) { + memcpy(nla_data(nla), info, target->usersize); + memset(nla_data(nla) + target->usersize, 0, + size - target->usersize); + } else { + memcpy(nla_data(nla), info, target->targetsize); + memset(nla_data(nla) + target->targetsize, 0, + size - target->targetsize); + } + return 0; nla_put_failure: @@ -529,12 +544,27 @@ static int __nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr, void *info) { struct xt_match *match = expr->ops->data; + size_t size = XT_ALIGN(match->matchsize); + struct nlattr *nla; if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) || - nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) || - nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(match->matchsize), info)) + nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision))) goto nla_put_failure; + nla = nla_reserve(skb, NFTA_MATCH_INFO, size); + if (!nla) + goto nla_put_failure; + + if (match->usersize) { + memcpy(nla_data(nla), info, match->usersize); + memset(nla_data(nla) + match->usersize, 0, + size - match->usersize); + } else { + memcpy(nla_data(nla), info, match->matchsize); + memset(nla_data(nla) + match->matchsize, 0, + size - match->matchsize); + } + return 0; nla_put_failure: -- 2.11.0