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

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