Blame SOURCES/0039-json-Fix-seqnum_to_json-functionality.patch

acfc56
From 0dcfa1b0211fa50201d51d0f52869a8e2d93ba76 Mon Sep 17 00:00:00 2001
acfc56
From: Phil Sutter <psutter@redhat.com>
acfc56
Date: Mon, 7 Dec 2020 18:29:15 +0100
acfc56
Subject: [PATCH] json: Fix seqnum_to_json() functionality
acfc56
acfc56
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1900565
acfc56
Upstream Status: nftables commit 299ec575faa6b
acfc56
acfc56
commit 299ec575faa6b070940b483dc517ecd883b9f1a4
acfc56
Author: Phil Sutter <phil@nwl.cc>
acfc56
Date:   Wed Dec 2 23:07:11 2020 +0100
acfc56
acfc56
    json: Fix seqnum_to_json() functionality
acfc56
acfc56
    Introduction of json_cmd_assoc_hash missed that by the time the hash
acfc56
    table insert happens, the struct cmd object's 'seqnum' field which is
acfc56
    used as key is not initialized yet. This doesn't happen until
acfc56
    nft_netlink() prepares the batch object which records the lowest seqnum.
acfc56
    Therefore push all json_cmd_assoc objects into a temporary list until
acfc56
    the first lookup happens. At this time, all referenced cmd objects have
acfc56
    their seqnum set and the list entries can be moved into the hash table
acfc56
    for fast lookups.
acfc56
acfc56
    To expose such problems in the future, make json_events_cb() emit an
acfc56
    error message if the passed message has a handle but no assoc entry is
acfc56
    found for its seqnum.
acfc56
acfc56
    Fixes: 389a0e1edc89a ("json: echo: Speedup seqnum_to_json()")
acfc56
    Cc: Derek Dai <daiderek@gmail.com>
acfc56
    Signed-off-by: Phil Sutter <phil@nwl.cc>
acfc56
---
acfc56
 src/parser_json.c | 27 +++++++++++++++++++++++----
acfc56
 1 file changed, 23 insertions(+), 4 deletions(-)
acfc56
acfc56
diff --git a/src/parser_json.c b/src/parser_json.c
acfc56
index 107dc38..785f0e7 100644
acfc56
--- a/src/parser_json.c
acfc56
+++ b/src/parser_json.c
acfc56
@@ -3646,6 +3646,7 @@ static int json_verify_metainfo(struct json_ctx *ctx, json_t *root)
acfc56
 }
acfc56
 
acfc56
 struct json_cmd_assoc {
acfc56
+	struct json_cmd_assoc *next;
acfc56
 	struct hlist_node hnode;
acfc56
 	const struct cmd *cmd;
acfc56
 	json_t *json;
acfc56
@@ -3653,6 +3654,7 @@ struct json_cmd_assoc {
acfc56
 
acfc56
 #define CMD_ASSOC_HSIZE		512
acfc56
 static struct hlist_head json_cmd_assoc_hash[CMD_ASSOC_HSIZE];
acfc56
+static struct json_cmd_assoc *json_cmd_assoc_list;
acfc56
 
acfc56
 static void json_cmd_assoc_free(void)
acfc56
 {
acfc56
@@ -3660,6 +3662,12 @@ static void json_cmd_assoc_free(void)
acfc56
 	struct hlist_node *pos, *n;
acfc56
 	int i;
acfc56
 
acfc56
+	while (json_cmd_assoc_list) {
acfc56
+		cur = json_cmd_assoc_list->next;
acfc56
+		free(json_cmd_assoc_list);
acfc56
+		json_cmd_assoc_list = cur;
acfc56
+	}
acfc56
+
acfc56
 	for (i = 0; i < CMD_ASSOC_HSIZE; i++) {
acfc56
 		hlist_for_each_entry_safe(cur, pos, n,
acfc56
 					  &json_cmd_assoc_hash[i], hnode)
acfc56
@@ -3670,21 +3678,29 @@ static void json_cmd_assoc_free(void)
acfc56
 static void json_cmd_assoc_add(json_t *json, const struct cmd *cmd)
acfc56
 {
acfc56
 	struct json_cmd_assoc *new = xzalloc(sizeof *new);
acfc56
-	int key = cmd->seqnum % CMD_ASSOC_HSIZE;
acfc56
 
acfc56
 	new->json	= json;
acfc56
 	new->cmd	= cmd;
acfc56
+	new->next	= json_cmd_assoc_list;
acfc56
 
acfc56
-	hlist_add_head(&new->hnode, &json_cmd_assoc_hash[key]);
acfc56
+	json_cmd_assoc_list = new;
acfc56
 }
acfc56
 
acfc56
 static json_t *seqnum_to_json(const uint32_t seqnum)
acfc56
 {
acfc56
-	int key = seqnum % CMD_ASSOC_HSIZE;
acfc56
 	struct json_cmd_assoc *cur;
acfc56
 	struct hlist_node *n;
acfc56
+	int key;
acfc56
 
acfc56
+	while (json_cmd_assoc_list) {
acfc56
+		cur = json_cmd_assoc_list;
acfc56
+		json_cmd_assoc_list = cur->next;
acfc56
 
acfc56
+		key = cur->cmd->seqnum % CMD_ASSOC_HSIZE;
acfc56
+		hlist_add_head(&cur->hnode, &json_cmd_assoc_hash[key]);
acfc56
+	}
acfc56
+
acfc56
+	key = seqnum % CMD_ASSOC_HSIZE;
acfc56
 	hlist_for_each_entry(cur, n, &json_cmd_assoc_hash[key], hnode) {
acfc56
 		if (cur->cmd->seqnum == seqnum)
acfc56
 			return cur->json;
acfc56
@@ -3865,8 +3881,11 @@ int json_events_cb(const struct nlmsghdr *nlh, struct netlink_mon_handler *monh)
acfc56
 		return MNL_CB_OK;
acfc56
 
acfc56
 	json = seqnum_to_json(nlh->nlmsg_seq);
acfc56
-	if (!json)
acfc56
+	if (!json) {
acfc56
+		json_echo_error(monh, "No JSON command found with seqnum %lu\n",
acfc56
+				nlh->nlmsg_seq);
acfc56
 		return MNL_CB_OK;
acfc56
+	}
acfc56
 
acfc56
 	tmp = json_object_get(json, "add");
acfc56
 	if (!tmp)
acfc56
-- 
acfc56
1.8.3.1
acfc56