From a617fd904789cd3a05cf4cb2f54649e2a1f73d33 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Dec 2023 18:10:02 +0100 Subject: [PATCH 1/2] json: add new dispatch flag JSON_ALLOW_EXTENSIONS This is a subset of JSON_PERMISSIVE focussed on allowing parsing of varlink replies that get extended, i.e. gain new fields, without allowing more than that (i.e. without allowing missing fields, or bad field types or such). --- src/shared/json.c | 6 +++++- src/shared/json.h | 15 ++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/shared/json.c b/src/shared/json.c index 19e8e0c77e..aeb1b36af3 100644 --- a/src/shared/json.c +++ b/src/shared/json.c @@ -4615,8 +4615,12 @@ int json_dispatch_full( done++; } else { - json_log(value, flags, 0, "Unexpected object field '%s'.", json_variant_string(key)); + if (flags & JSON_ALLOW_EXTENSIONS) { + json_log(value, flags, 0, "Unrecognized object field '%s', assuming extension.", json_variant_string(key)); + continue; + } + json_log(value, flags, 0, "Unexpected object field '%s'.", json_variant_string(key)); if (flags & JSON_PERMISSIVE) continue; diff --git a/src/shared/json.h b/src/shared/json.h index 975cf562a9..8fb7c1be78 100644 --- a/src/shared/json.h +++ b/src/shared/json.h @@ -376,15 +376,16 @@ int json_buildv(JsonVariant **ret, va_list ap); * entry, as well the bitmask specified for json_log() calls */ typedef enum JsonDispatchFlags { /* The following three may be set in JsonDispatch's .flags field or the json_dispatch() flags parameter */ - JSON_PERMISSIVE = 1 << 0, /* Shall parsing errors be considered fatal for this property? */ - JSON_MANDATORY = 1 << 1, /* Should existence of this property be mandatory? */ - JSON_LOG = 1 << 2, /* Should the parser log about errors? */ - JSON_SAFE = 1 << 3, /* Don't accept "unsafe" strings in json_dispatch_string() + json_dispatch_string() */ - JSON_RELAX = 1 << 4, /* Use relaxed user name checking in json_dispatch_user_group_name */ + JSON_PERMISSIVE = 1 << 0, /* Shall parsing errors be considered fatal for this field or object? */ + JSON_MANDATORY = 1 << 1, /* Should existence of this property be mandatory? */ + JSON_LOG = 1 << 2, /* Should the parser log about errors? */ + JSON_SAFE = 1 << 3, /* Don't accept "unsafe" strings in json_dispatch_string() + json_dispatch_string() */ + JSON_RELAX = 1 << 4, /* Use relaxed user name checking in json_dispatch_user_group_name */ + JSON_ALLOW_EXTENSIONS = 1 << 5, /* Subset of JSON_PERMISSIVE: allow additional fields, but no other permissive handling */ /* The following two may be passed into log_json() in addition to those above */ - JSON_DEBUG = 1 << 5, /* Indicates that this log message is a debug message */ - JSON_WARNING = 1 << 6, /* Indicates that this log message is a warning message */ + JSON_DEBUG = 1 << 6, /* Indicates that this log message is a debug message */ + JSON_WARNING = 1 << 7, /* Indicates that this log message is a warning message */ } JsonDispatchFlags; typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); From f0e4244b2fda1b3de3da1c2792ed1cd21c72087b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Jan 2024 12:39:28 +0100 Subject: [PATCH 2/2] tree-wide: use JSON_ALLOW_EXTENSIONS when disptching at various places If we want to allow method replies to be extended without this breaking compat, then we should set this flag. Do so at various method call replies hence. Also do it when parsing user/group records, which are expressly documented to be extensible, as well as the hibernate JSON record. --- src/hibernate-resume/hibernate-resume-config.c | 2 +- src/network/networkctl.c | 2 +- src/nss-resolve/nss-resolve.c | 2 +- src/shared/group-record.c | 2 +- src/shared/user-record.c | 2 +- src/shared/userdb.c | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hibernate-resume/hibernate-resume-config.c b/src/hibernate-resume/hibernate-resume-config.c index a751a0ac4c..c6db83a9d3 100644 --- a/src/hibernate-resume/hibernate-resume-config.c +++ b/src/hibernate-resume/hibernate-resume-config.c @@ -192,7 +192,7 @@ static int get_efi_hibernate_location(EFIHibernateLocation **ret) { if (!e) return log_oom(); - r = json_dispatch(v, dispatch_table, JSON_LOG, e); + r = json_dispatch(v, dispatch_table, JSON_LOG|JSON_ALLOW_EXTENSIONS, e); if (r < 0) return r; diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 8e677cc010..95e22cd9e3 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -113,7 +113,7 @@ static int check_netns_match(void) { {}, }; - r = json_dispatch(reply, dispatch_table, JSON_LOG, &id); + r = json_dispatch(reply, dispatch_table, JSON_LOG|JSON_ALLOW_EXTENSIONS, &id); if (r < 0) return r; diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index c4e02bc7c1..822ad4f622 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -20,7 +20,7 @@ #include "strv.h" #include "varlink.h" -static JsonDispatchFlags json_dispatch_flags = 0; +static JsonDispatchFlags json_dispatch_flags = JSON_ALLOW_EXTENSIONS; static void setup_logging(void) { log_parse_environment_variables(); diff --git a/src/shared/group-record.c b/src/shared/group-record.c index 1e33bdfed5..4fed5c671c 100644 --- a/src/shared/group-record.c +++ b/src/shared/group-record.c @@ -230,7 +230,7 @@ int group_record_load( if (r < 0) return r; - r = json_dispatch(h->json, group_dispatch_table, json_flags, h); + r = json_dispatch(h->json, group_dispatch_table, json_flags | JSON_ALLOW_EXTENSIONS, h); if (r < 0) return r; diff --git a/src/shared/user-record.c b/src/shared/user-record.c index 3fe3e80b83..035e2a7124 100644 --- a/src/shared/user-record.c +++ b/src/shared/user-record.c @@ -1625,7 +1625,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla if (r < 0) return r; - r = json_dispatch(h->json, user_dispatch_table, json_flags, h); + r = json_dispatch(h->json, user_dispatch_table, json_flags | JSON_ALLOW_EXTENSIONS, h); if (r < 0) return r; diff --git a/src/shared/userdb.c b/src/shared/userdb.c index f60d48ace4..540573390c 100644 --- a/src/shared/userdb.c +++ b/src/shared/userdb.c @@ -199,7 +199,7 @@ static int userdb_on_query_reply( assert_se(!iterator->found_user); - r = json_dispatch(parameters, dispatch_table, 0, &user_data); + r = json_dispatch(parameters, dispatch_table, JSON_ALLOW_EXTENSIONS, &user_data); if (r < 0) goto finish; @@ -256,7 +256,7 @@ static int userdb_on_query_reply( assert_se(!iterator->found_group); - r = json_dispatch(parameters, dispatch_table, 0, &group_data); + r = json_dispatch(parameters, dispatch_table, JSON_ALLOW_EXTENSIONS, &group_data); if (r < 0) goto finish; @@ -309,7 +309,7 @@ static int userdb_on_query_reply( assert(!iterator->found_user_name); assert(!iterator->found_group_name); - r = json_dispatch(parameters, dispatch_table, 0, &membership_data); + r = json_dispatch(parameters, dispatch_table, JSON_ALLOW_EXTENSIONS, &membership_data); if (r < 0) goto finish;