From 97c1a0c4e457a007bd07db1baf401e1a0750c387 Mon Sep 17 00:00:00 2001 From: wguanghao Date: Mon, 31 Oct 2022 07:01:30 +0000 Subject: [PATCH 1/2] fix CVE-2022-41974 --- ...nd-set-cli_handlers-in-a-single-step.patch | 181 ++++ ...tipathd-make-all-cli_handlers-static.patch | 841 ++++++++++++++++ ...ommand-completion-in-interactive-mod.patch | 192 ++++ ...ltipathd-more-robust-command-parsing.patch | 923 ++++++++++++++++++ multipath-tools.spec | 10 +- 5 files changed, 2146 insertions(+), 1 deletion(-) create mode 100644 0019-multipathd-add-and-set-cli_handlers-in-a-single-step.patch create mode 100644 0020-multipathd-make-all-cli_handlers-static.patch create mode 100644 0021-multipathd-Fix-command-completion-in-interactive-mod.patch create mode 100644 0022-multipathd-more-robust-command-parsing.patch diff --git a/0019-multipathd-add-and-set-cli_handlers-in-a-single-step.patch b/0019-multipathd-add-and-set-cli_handlers-in-a-single-step.patch new file mode 100644 index 0000000..d7aff4b --- /dev/null +++ b/0019-multipathd-add-and-set-cli_handlers-in-a-single-step.patch @@ -0,0 +1,181 @@ +From db77d1b3cdb14ca0e32132ff7ad360e3d48f62ee Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 7 Sep 2021 22:41:46 +0200 +Subject: [PATCH] multipathd: add and set cli_handlers in a single step + +Modify set_handler_callback() such that a missing slot is created +if no matching slot is found. This way, we can skip the initialization +with NULL handlers on startup. Assigning the same handler multiple +times would be a bug which is tested with assert(). + +Reviewed-by: Benjamin Marzinski +--- + multipathd/cli.c | 96 ++++++++---------------------------------------- + multipathd/cli.h | 7 ++-- + 2 files changed, 20 insertions(+), 83 deletions(-) + +diff --git a/multipathd/cli.c b/multipathd/cli.c +index 4d6c37c..ddeb5fc 100644 +--- a/multipathd/cli.c ++++ b/multipathd/cli.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include "memory.h" + #include "vector.h" + #include "structs.h" +@@ -64,26 +65,27 @@ out: + return 1; + } + +-int +-add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *)) ++ ++static struct handler add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *), bool locked) + { + struct handler * h; + + h = alloc_handler(); + +- if (!h) +- return 1; ++ if (h == NULL) ++ return NULL; + + if (!vector_alloc_slot(handlers)) { + FREE(h); +- return 1; ++ return NULL; + } + + vector_set_slot(handlers, h); + h->fingerprint = fp; + h->fn = fn; ++ h->locked = locked; + +- return 0; ++ return h; + } + + static struct handler * +@@ -100,26 +102,17 @@ find_handler (uint64_t fp) + } + + int +-set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *)) ++__set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *), bool locked) + { +- struct handler * h = find_handler(fp); +- +- if (!h) +- return 1; +- h->fn = fn; +- h->locked = 1; +- return 0; +-} +- +-int +-set_unlocked_handler_callback (uint64_t fp,int (*fn)(void *, char **, int *, void *)) +-{ +- struct handler * h = find_handler(fp); ++ struct handler *h; + +- if (!h) ++ assert(find_handler(fp) == NULL); ++ h = add_handler(fp, fn, locked); ++ if (!h) { ++ condlog(0, "%s: failed to set handler for code %"PRIu64, ++ __func__, fp); + return 1; +- h->fn = fn; +- h->locked = 0; ++ } + return 0; + } + +@@ -513,63 +506,6 @@ cli_init (void) { + if (alloc_handlers()) + return 1; + +- add_handler(LIST+PATHS, NULL); +- add_handler(LIST+PATHS+FMT, NULL); +- add_handler(LIST+PATHS+RAW+FMT, NULL); +- add_handler(LIST+PATH, NULL); +- add_handler(LIST+STATUS, NULL); +- add_handler(LIST+DAEMON, NULL); +- add_handler(LIST+MAPS, NULL); +- add_handler(LIST+MAPS+STATUS, NULL); +- add_handler(LIST+MAPS+STATS, NULL); +- add_handler(LIST+MAPS+FMT, NULL); +- add_handler(LIST+MAPS+RAW+FMT, NULL); +- add_handler(LIST+MAPS+TOPOLOGY, NULL); +- add_handler(LIST+MAPS+JSON, NULL); +- add_handler(LIST+TOPOLOGY, NULL); +- add_handler(LIST+MAP+TOPOLOGY, NULL); +- add_handler(LIST+MAP+JSON, NULL); +- add_handler(LIST+MAP+FMT, NULL); +- add_handler(LIST+MAP+RAW+FMT, NULL); +- add_handler(LIST+CONFIG, NULL); +- add_handler(LIST+CONFIG+LOCAL, NULL); +- add_handler(LIST+BLACKLIST, NULL); +- add_handler(LIST+DEVICES, NULL); +- add_handler(LIST+WILDCARDS, NULL); +- add_handler(RESET+MAPS+STATS, NULL); +- add_handler(RESET+MAP+STATS, NULL); +- add_handler(ADD+PATH, NULL); +- add_handler(DEL+PATH, NULL); +- add_handler(ADD+MAP, NULL); +- add_handler(DEL+MAP, NULL); +- add_handler(DEL+MAPS, NULL); +- add_handler(SWITCH+MAP+GROUP, NULL); +- add_handler(RECONFIGURE, NULL); +- add_handler(SUSPEND+MAP, NULL); +- add_handler(RESUME+MAP, NULL); +- add_handler(RESIZE+MAP, NULL); +- add_handler(RESET+MAP, NULL); +- add_handler(RELOAD+MAP, NULL); +- add_handler(DISABLEQ+MAP, NULL); +- add_handler(RESTOREQ+MAP, NULL); +- add_handler(DISABLEQ+MAPS, NULL); +- add_handler(RESTOREQ+MAPS, NULL); +- add_handler(REINSTATE+PATH, NULL); +- add_handler(FAIL+PATH, NULL); +- add_handler(QUIT, NULL); +- add_handler(SHUTDOWN, NULL); +- add_handler(GETPRSTATUS+MAP, NULL); +- add_handler(SETPRSTATUS+MAP, NULL); +- add_handler(UNSETPRSTATUS+MAP, NULL); +- add_handler(GETPRKEY+MAP, NULL); +- add_handler(SETPRKEY+MAP+KEY, NULL); +- add_handler(UNSETPRKEY+MAP, NULL); +- add_handler(FORCEQ+DAEMON, NULL); +- add_handler(RESTOREQ+DAEMON, NULL); +- add_handler(SETMARGINAL+PATH, NULL); +- add_handler(UNSETMARGINAL+PATH, NULL); +- add_handler(UNSETMARGINAL+MAP, NULL); +- + return 0; + } + +diff --git a/multipathd/cli.h b/multipathd/cli.h +index fdfb9ae..a6704b1 100644 +--- a/multipathd/cli.h ++++ b/multipathd/cli.h +@@ -131,9 +131,10 @@ struct handler { + }; + + int alloc_handlers (void); +-int add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *)); +-int set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *)); +-int set_unlocked_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *)); ++int __set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *), bool locked); ++#define set_handler_callback(fp, fn) __set_handler_callback(fp, fn, true) ++#define set_unlocked_handler_callback(fp, fn) __set_handler_callback(fp, fn, false) ++ + int parse_cmd (char * cmd, char ** reply, int * len, void *, int); + int load_keys (void); + char * get_keyparam (vector v, uint64_t code); +-- +2.33.0 \ No newline at end of file diff --git a/0020-multipathd-make-all-cli_handlers-static.patch b/0020-multipathd-make-all-cli_handlers-static.patch new file mode 100644 index 0000000..7481cca --- /dev/null +++ b/0020-multipathd-make-all-cli_handlers-static.patch @@ -0,0 +1,841 @@ +From 70af8839ee8ac4e06de94dfa9cf80b36d033f2ab Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 7 Sep 2021 22:32:46 +0200 +Subject: [PATCH] multipathd: make all cli_handlers static + +The cli_handler functions are only called from the handler table and +need not be exported. + +Reviewed-by: Benjamin Marzinski +--- + multipathd/cli_handlers.c | 214 ++++++++++++++++++++++---------------- + multipathd/cli_handlers.h | 61 ++--------- + multipathd/main.c | 58 +---------- + 3 files changed, 134 insertions(+), 199 deletions(-) + +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index aeb2be5..f75e176 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -39,7 +39,7 @@ + *(__len) = *(__rep) ? sizeof(string_literal) : 0; \ + } while (0) + +-int ++static int + show_paths (char ** r, int * len, struct vectors * vecs, char * style, + int pretty) + { +@@ -70,7 +70,7 @@ show_paths (char ** r, int * len, struct vectors * vecs, char * style, + return 0; + } + +-int ++static int + show_path (char ** r, int * len, struct vectors * vecs, struct path *pp, + char * style) + { +@@ -85,7 +85,7 @@ show_path (char ** r, int * len, struct vectors * vecs, struct path *pp, + return 0; + } + +-int ++static int + show_map_topology (char ** r, int * len, struct multipath * mpp, + struct vectors * vecs) + { +@@ -102,7 +102,7 @@ show_map_topology (char ** r, int * len, struct multipath * mpp, + return 0; + } + +-int ++static int + show_maps_topology (char ** r, int * len, struct vectors * vecs) + { + STRBUF_ON_STACK(reply); +@@ -128,7 +128,7 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs) + return 0; + } + +-int ++static int + show_maps_json (char ** r, int * len, struct vectors * vecs) + { + STRBUF_ON_STACK(reply); +@@ -149,7 +149,7 @@ show_maps_json (char ** r, int * len, struct vectors * vecs) + return 0; + } + +-int ++static int + show_map_json (char ** r, int * len, struct multipath * mpp, + struct vectors * vecs) + { +@@ -194,7 +194,7 @@ reset_stats(struct multipath * mpp) + mpp->stat_map_failures = 0; + } + +-int ++static int + cli_list_config (void * v, char ** reply, int * len, void * data) + { + condlog(3, "list config (operator)"); +@@ -207,7 +207,7 @@ static void v_free(void *x) + vector_free(x); + } + +-int ++static int + cli_list_config_local (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -223,7 +223,7 @@ cli_list_config_local (void * v, char ** reply, int * len, void * data) + return ret; + } + +-int ++static int + cli_list_paths (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -233,7 +233,7 @@ cli_list_paths (void * v, char ** reply, int * len, void * data) + return show_paths(reply, len, vecs, PRINT_PATH_CHECKER, 1); + } + +-int ++static int + cli_list_paths_fmt (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -244,7 +244,7 @@ cli_list_paths_fmt (void * v, char ** reply, int * len, void * data) + return show_paths(reply, len, vecs, fmt, 1); + } + +-int ++static int + cli_list_paths_raw (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -255,7 +255,7 @@ cli_list_paths_raw (void * v, char ** reply, int * len, void * data) + return show_paths(reply, len, vecs, fmt, 0); + } + +-int ++static int + cli_list_path (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -272,7 +272,7 @@ cli_list_path (void * v, char ** reply, int * len, void * data) + return show_path(reply, len, vecs, pp, "%o"); + } + +-int ++static int + cli_list_map_topology (void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -291,7 +291,7 @@ cli_list_map_topology (void * v, char ** reply, int * len, void * data) + return show_map_topology(reply, len, mpp, vecs); + } + +-int ++static int + cli_list_maps_topology (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -301,7 +301,7 @@ cli_list_maps_topology (void * v, char ** reply, int * len, void * data) + return show_maps_topology(reply, len, vecs); + } + +-int ++static int + cli_list_map_json (void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -320,7 +320,7 @@ cli_list_map_json (void * v, char ** reply, int * len, void * data) + return show_map_json(reply, len, mpp, vecs); + } + +-int ++static int + cli_list_maps_json (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -330,7 +330,7 @@ cli_list_maps_json (void * v, char ** reply, int * len, void * data) + return show_maps_json(reply, len, vecs); + } + +-int ++static int + cli_list_wildcards (void * v, char ** reply, int * len, void * data) + { + STRBUF_ON_STACK(buf); +@@ -343,7 +343,7 @@ cli_list_wildcards (void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + show_status (char ** r, int *len, struct vectors * vecs) + { + STRBUF_ON_STACK(reply); +@@ -356,7 +356,7 @@ show_status (char ** r, int *len, struct vectors * vecs) + return 0; + } + +-int ++static int + show_daemon (char ** r, int *len) + { + STRBUF_ON_STACK(reply); +@@ -370,7 +370,7 @@ show_daemon (char ** r, int *len) + return 0; + } + +-int ++static int + show_map (char ** r, int *len, struct multipath * mpp, char * style, + int pretty) + { +@@ -384,7 +384,7 @@ show_map (char ** r, int *len, struct multipath * mpp, char * style, + return 0; + } + +-int ++static int + show_maps (char ** r, int *len, struct vectors * vecs, char * style, + int pretty) + { +@@ -419,7 +419,7 @@ show_maps (char ** r, int *len, struct vectors * vecs, char * style, + return 0; + } + +-int ++static int + cli_list_maps_fmt (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -430,7 +430,7 @@ cli_list_maps_fmt (void * v, char ** reply, int * len, void * data) + return show_maps(reply, len, vecs, fmt, 1); + } + +-int ++static int + cli_list_maps_raw (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -441,7 +441,7 @@ cli_list_maps_raw (void * v, char ** reply, int * len, void * data) + return show_maps(reply, len, vecs, fmt, 0); + } + +-int ++static int + cli_list_map_fmt (void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -461,27 +461,7 @@ cli_list_map_fmt (void * v, char ** reply, int * len, void * data) + return show_map(reply, len, mpp, fmt, 1); + } + +-int +-cli_list_map_raw (void * v, char ** reply, int * len, void * data) +-{ +- struct multipath * mpp; +- struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); +- char * fmt = get_keyparam(v, FMT); +- +- param = convert_dev(param, 0); +- get_path_layout(vecs->pathvec, 0); +- get_multipath_layout(vecs->mpvec, 1); +- mpp = find_mp_by_str(vecs->mpvec, param); +- if (!mpp) +- return 1; +- +- condlog(3, "list map %s fmt %s (operator)", param, fmt); +- +- return show_map(reply, len, mpp, fmt, 0); +-} +- +-int ++static int + cli_list_maps (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -491,7 +471,7 @@ cli_list_maps (void * v, char ** reply, int * len, void * data) + return show_maps(reply, len, vecs, PRINT_MAP_NAMES, 1); + } + +-int ++static int + cli_list_status (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -501,7 +481,7 @@ cli_list_status (void * v, char ** reply, int * len, void * data) + return show_status(reply, len, vecs); + } + +-int ++static int + cli_list_maps_status (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -511,7 +491,7 @@ cli_list_maps_status (void * v, char ** reply, int * len, void * data) + return show_maps(reply, len, vecs, PRINT_MAP_STATUS, 1); + } + +-int ++static int + cli_list_maps_stats (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -521,7 +501,7 @@ cli_list_maps_stats (void * v, char ** reply, int * len, void * data) + return show_maps(reply, len, vecs, PRINT_MAP_STATS, 1); + } + +-int ++static int + cli_list_daemon (void * v, char ** reply, int * len, void * data) + { + condlog(3, "list daemon (operator)"); +@@ -529,7 +509,7 @@ cli_list_daemon (void * v, char ** reply, int * len, void * data) + return show_daemon(reply, len); + } + +-int ++static int + cli_reset_maps_stats (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -544,7 +524,7 @@ cli_reset_maps_stats (void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_reset_map_stats (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -562,7 +542,7 @@ cli_reset_map_stats (void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_add_path (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -678,7 +658,7 @@ blacklisted: + return 0; + } + +-int ++static int + cli_del_path (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -701,7 +681,7 @@ cli_del_path (void * v, char ** reply, int * len, void * data) + return (ret == REMOVE_PATH_FAILURE); + } + +-int ++static int + cli_add_map (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -761,7 +741,7 @@ cli_add_map (void * v, char ** reply, int * len, void * data) + return rc; + } + +-int ++static int + cli_del_map (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -787,7 +767,7 @@ cli_del_map (void * v, char ** reply, int * len, void * data) + return rc; + } + +-int ++static int + cli_del_maps (void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -806,7 +786,7 @@ cli_del_maps (void *v, char **reply, int *len, void *data) + return ret; + } + +-int ++static int + cli_reload(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -834,7 +814,7 @@ cli_reload(void *v, char **reply, int *len, void *data) + return reload_and_sync_map(mpp, vecs, 0); + } + +-int resize_map(struct multipath *mpp, unsigned long long size, ++static int resize_map(struct multipath *mpp, unsigned long long size, + struct vectors * vecs) + { + char *params __attribute__((cleanup(cleanup_charp))) = NULL; +@@ -859,7 +839,7 @@ int resize_map(struct multipath *mpp, unsigned long long size, + return 0; + } + +-int ++static int + cli_resize(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -941,7 +921,7 @@ cli_resize(void *v, char **reply, int *len, void *data) + return 0; + } + +-int ++static int + cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data) + { + struct config *conf; +@@ -954,7 +934,7 @@ cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data) + { + struct config *conf; +@@ -967,7 +947,7 @@ cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_restore_queueing(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1008,7 +988,7 @@ cli_restore_queueing(void *v, char **reply, int *len, void *data) + return 0; + } + +-int ++static int + cli_restore_all_queueing(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1030,7 +1010,7 @@ cli_restore_all_queueing(void *v, char **reply, int *len, void *data) + return 0; + } + +-int ++static int + cli_disable_queueing(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1059,7 +1039,7 @@ cli_disable_queueing(void *v, char **reply, int *len, void *data) + return 0; + } + +-int ++static int + cli_disable_all_queueing(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1078,7 +1058,7 @@ cli_disable_all_queueing(void *v, char **reply, int *len, void *data) + return 0; + } + +-int ++static int + cli_switch_group(void * v, char ** reply, int * len, void * data) + { + char * mapname = get_keyparam(v, MAP); +@@ -1090,7 +1070,7 @@ cli_switch_group(void * v, char ** reply, int * len, void * data) + return dm_switchgroup(mapname, groupnum); + } + +-int ++static int + cli_reconfigure(void * v, char ** reply, int * len, void * data) + { + int rc; +@@ -1107,7 +1087,7 @@ cli_reconfigure(void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_suspend(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1137,7 +1117,7 @@ cli_suspend(void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_resume(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1169,7 +1149,7 @@ cli_resume(void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_reinstate(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1192,7 +1172,7 @@ cli_reinstate(void * v, char ** reply, int * len, void * data) + return dm_reinstate_path(pp->mpp->alias, pp->dev_t); + } + +-int ++static int + cli_reassign (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1216,7 +1196,7 @@ cli_reassign (void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_fail(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1245,7 +1225,7 @@ cli_fail(void * v, char ** reply, int * len, void * data) + return r; + } + +-int ++static int + show_blacklist (char ** r, int * len) + { + STRBUF_ON_STACK(reply); +@@ -1265,7 +1245,7 @@ show_blacklist (char ** r, int * len) + return 0; + } + +-int ++static int + cli_list_blacklist (void * v, char ** reply, int * len, void * data) + { + condlog(3, "list blacklist (operator)"); +@@ -1273,7 +1253,7 @@ cli_list_blacklist (void * v, char ** reply, int * len, void * data) + return show_blacklist(reply, len); + } + +-int ++static int + show_devices (char ** r, int * len, struct vectors *vecs) + { + STRBUF_ON_STACK(reply); +@@ -1294,7 +1274,7 @@ show_devices (char ** r, int * len, struct vectors *vecs) + return 0; + } + +-int ++static int + cli_list_devices (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +@@ -1304,13 +1284,13 @@ cli_list_devices (void * v, char ** reply, int * len, void * data) + return show_devices(reply, len, vecs); + } + +-int ++static int + cli_quit (void * v, char ** reply, int * len, void * data) + { + return 0; + } + +-int ++static int + cli_shutdown (void * v, char ** reply, int * len, void * data) + { + condlog(3, "shutdown (operator)"); +@@ -1318,7 +1298,7 @@ cli_shutdown (void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_getprstatus (void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -1343,7 +1323,7 @@ cli_getprstatus (void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_setprstatus(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -1366,7 +1346,7 @@ cli_setprstatus(void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_unsetprstatus(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -1388,7 +1368,7 @@ cli_unsetprstatus(void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_getprkey(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -1420,7 +1400,7 @@ cli_getprkey(void * v, char ** reply, int * len, void * data) + return 0; + } + +-int ++static int + cli_unsetprkey(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -1444,7 +1424,7 @@ cli_unsetprkey(void * v, char ** reply, int * len, void * data) + return ret; + } + +-int ++static int + cli_setprkey(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; +@@ -1476,7 +1456,7 @@ cli_setprkey(void * v, char ** reply, int * len, void * data) + return ret; + } + +-int cli_set_marginal(void * v, char ** reply, int * len, void * data) ++static int cli_set_marginal(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, PATH); +@@ -1503,7 +1483,7 @@ int cli_set_marginal(void * v, char ** reply, int * len, void * data) + return reload_and_sync_map(pp->mpp, vecs, 0); + } + +-int cli_unset_marginal(void * v, char ** reply, int * len, void * data) ++static int cli_unset_marginal(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, PATH); +@@ -1530,7 +1510,7 @@ int cli_unset_marginal(void * v, char ** reply, int * len, void * data) + return reload_and_sync_map(pp->mpp, vecs, 0); + } + +-int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data) ++static int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; + char * mapname = get_keyparam(v, MAP); +@@ -1566,3 +1546,63 @@ int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data) + + return reload_and_sync_map(mpp, vecs, 0); + } ++ ++void init_handler_callbacks(void) ++{ ++ set_handler_callback(LIST+PATHS, cli_list_paths); ++ set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt); ++ set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw); ++ set_handler_callback(LIST+PATH, cli_list_path); ++ set_handler_callback(LIST+MAPS, cli_list_maps); ++ set_handler_callback(LIST+STATUS, cli_list_status); ++ set_unlocked_handler_callback(LIST+DAEMON, cli_list_daemon); ++ set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status); ++ set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats); ++ set_handler_callback(LIST+MAPS+FMT, cli_list_maps_fmt); ++ set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw); ++ set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology); ++ set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology); ++ set_handler_callback(LIST+MAPS+JSON, cli_list_maps_json); ++ set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology); ++ set_handler_callback(LIST+MAP+FMT, cli_list_map_fmt); ++ set_handler_callback(LIST+MAP+RAW+FMT, cli_list_map_fmt); ++ set_handler_callback(LIST+MAP+JSON, cli_list_map_json); ++ set_handler_callback(LIST+CONFIG+LOCAL, cli_list_config_local); ++ set_handler_callback(LIST+CONFIG, cli_list_config); ++ set_handler_callback(LIST+BLACKLIST, cli_list_blacklist); ++ set_handler_callback(LIST+DEVICES, cli_list_devices); ++ set_handler_callback(LIST+WILDCARDS, cli_list_wildcards); ++ set_handler_callback(RESET+MAPS+STATS, cli_reset_maps_stats); ++ set_handler_callback(RESET+MAP+STATS, cli_reset_map_stats); ++ set_handler_callback(ADD+PATH, cli_add_path); ++ set_handler_callback(DEL+PATH, cli_del_path); ++ set_handler_callback(ADD+MAP, cli_add_map); ++ set_handler_callback(DEL+MAP, cli_del_map); ++ set_handler_callback(DEL+MAPS, cli_del_maps); ++ set_handler_callback(SWITCH+MAP+GROUP, cli_switch_group); ++ set_unlocked_handler_callback(RECONFIGURE, cli_reconfigure); ++ set_handler_callback(SUSPEND+MAP, cli_suspend); ++ set_handler_callback(RESUME+MAP, cli_resume); ++ set_handler_callback(RESIZE+MAP, cli_resize); ++ set_handler_callback(RELOAD+MAP, cli_reload); ++ set_handler_callback(RESET+MAP, cli_reassign); ++ set_handler_callback(REINSTATE+PATH, cli_reinstate); ++ set_handler_callback(FAIL+PATH, cli_fail); ++ set_handler_callback(DISABLEQ+MAP, cli_disable_queueing); ++ set_handler_callback(RESTOREQ+MAP, cli_restore_queueing); ++ set_handler_callback(DISABLEQ+MAPS, cli_disable_all_queueing); ++ set_handler_callback(RESTOREQ+MAPS, cli_restore_all_queueing); ++ set_unlocked_handler_callback(QUIT, cli_quit); ++ set_unlocked_handler_callback(SHUTDOWN, cli_shutdown); ++ set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus); ++ set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus); ++ set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus); ++ set_handler_callback(FORCEQ+DAEMON, cli_force_no_daemon_q); ++ set_handler_callback(RESTOREQ+DAEMON, cli_restore_no_daemon_q); ++ set_handler_callback(GETPRKEY+MAP, cli_getprkey); ++ set_handler_callback(SETPRKEY+MAP+KEY, cli_setprkey); ++ set_handler_callback(UNSETPRKEY+MAP, cli_unsetprkey); ++ set_handler_callback(SETMARGINAL+PATH, cli_set_marginal); ++ set_handler_callback(UNSETMARGINAL+PATH, cli_unset_marginal); ++ set_handler_callback(UNSETMARGINAL+MAP, cli_unset_all_marginal); ++} +diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h +index 6f57b42..7eaf847 100644 +--- a/multipathd/cli_handlers.h ++++ b/multipathd/cli_handlers.h +@@ -1,55 +1,6 @@ +-int cli_list_paths (void * v, char ** reply, int * len, void * data); +-int cli_list_paths_fmt (void * v, char ** reply, int * len, void * data); +-int cli_list_paths_raw (void * v, char ** reply, int * len, void * data); +-int cli_list_path (void * v, char ** reply, int * len, void * data); +-int cli_list_status (void * v, char ** reply, int * len, void * data); +-int cli_list_daemon (void * v, char ** reply, int * len, void * data); +-int cli_list_maps (void * v, char ** reply, int * len, void * data); +-int cli_list_maps_fmt (void * v, char ** reply, int * len, void * data); +-int cli_list_maps_raw (void * v, char ** reply, int * len, void * data); +-int cli_list_map_fmt (void * v, char ** reply, int * len, void * data); +-int cli_list_map_raw (void * v, char ** reply, int * len, void * data); +-int cli_list_maps_status (void * v, char ** reply, int * len, void * data); +-int cli_list_maps_stats (void * v, char ** reply, int * len, void * data); +-int cli_list_map_topology (void * v, char ** reply, int * len, void * data); +-int cli_list_maps_topology (void * v, char ** reply, int * len, void * data); +-int cli_list_map_json (void * v, char ** reply, int * len, void * data); +-int cli_list_maps_json (void * v, char ** reply, int * len, void * data); +-int cli_list_config (void * v, char ** reply, int * len, void * data); +-int cli_list_config_local (void * v, char ** reply, int * len, void * data); +-int cli_list_blacklist (void * v, char ** reply, int * len, void * data); +-int cli_list_devices (void * v, char ** reply, int * len, void * data); +-int cli_list_wildcards (void * v, char ** reply, int * len, void * data); +-int cli_reset_maps_stats (void * v, char ** reply, int * len, void * data); +-int cli_reset_map_stats (void * v, char ** reply, int * len, void * data); +-int cli_add_path (void * v, char ** reply, int * len, void * data); +-int cli_del_path (void * v, char ** reply, int * len, void * data); +-int cli_add_map (void * v, char ** reply, int * len, void * data); +-int cli_del_map (void * v, char ** reply, int * len, void * data); +-int cli_del_maps (void * v, char ** reply, int * len, void * data); +-int cli_switch_group(void * v, char ** reply, int * len, void * data); +-int cli_reconfigure(void * v, char ** reply, int * len, void * data); +-int cli_resize(void * v, char ** reply, int * len, void * data); +-int cli_reload(void * v, char ** reply, int * len, void * data); +-int cli_disable_queueing(void * v, char ** reply, int * len, void * data); +-int cli_disable_all_queueing(void * v, char ** reply, int * len, void * data); +-int cli_restore_queueing(void * v, char ** reply, int * len, void * data); +-int cli_restore_all_queueing(void * v, char ** reply, int * len, void * data); +-int cli_suspend(void * v, char ** reply, int * len, void * data); +-int cli_resume(void * v, char ** reply, int * len, void * data); +-int cli_reinstate(void * v, char ** reply, int * len, void * data); +-int cli_fail(void * v, char ** reply, int * len, void * data); +-int cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data); +-int cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data); +-int cli_quit(void * v, char ** reply, int * len, void * data); +-int cli_shutdown(void * v, char ** reply, int * len, void * data); +-int cli_reassign (void * v, char ** reply, int * len, void * data); +-int cli_getprstatus(void * v, char ** reply, int * len, void * data); +-int cli_setprstatus(void * v, char ** reply, int * len, void * data); +-int cli_unsetprstatus(void * v, char ** reply, int * len, void * data); +-int cli_getprkey(void * v, char ** reply, int * len, void * data); +-int cli_setprkey(void * v, char ** reply, int * len, void * data); +-int cli_unsetprkey(void * v, char ** reply, int * len, void * data); +-int cli_set_marginal(void * v, char ** reply, int * len, void * data); +-int cli_unset_marginal(void * v, char ** reply, int * len, void * data); +-int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data); ++#ifndef _CLI_HANDLERS_H ++#define _CLI_HANDLERS_H ++ ++void init_handler_callbacks(void); ++ ++#endif +diff --git a/multipathd/main.c b/multipathd/main.c +index 118dadd..08fb992 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1669,63 +1669,7 @@ uxlsnrloop (void * ap) + /* Tell main thread that thread has started */ + post_config_state(DAEMON_CONFIGURE); + +- set_handler_callback(LIST+PATHS, cli_list_paths); +- set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt); +- set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw); +- set_handler_callback(LIST+PATH, cli_list_path); +- set_handler_callback(LIST+MAPS, cli_list_maps); +- set_handler_callback(LIST+STATUS, cli_list_status); +- set_unlocked_handler_callback(LIST+DAEMON, cli_list_daemon); +- set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status); +- set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats); +- set_handler_callback(LIST+MAPS+FMT, cli_list_maps_fmt); +- set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw); +- set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology); +- set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology); +- set_handler_callback(LIST+MAPS+JSON, cli_list_maps_json); +- set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology); +- set_handler_callback(LIST+MAP+FMT, cli_list_map_fmt); +- set_handler_callback(LIST+MAP+RAW+FMT, cli_list_map_fmt); +- set_handler_callback(LIST+MAP+JSON, cli_list_map_json); +- set_handler_callback(LIST+CONFIG+LOCAL, cli_list_config_local); +- set_handler_callback(LIST+CONFIG, cli_list_config); +- set_handler_callback(LIST+BLACKLIST, cli_list_blacklist); +- set_handler_callback(LIST+DEVICES, cli_list_devices); +- set_handler_callback(LIST+WILDCARDS, cli_list_wildcards); +- set_handler_callback(RESET+MAPS+STATS, cli_reset_maps_stats); +- set_handler_callback(RESET+MAP+STATS, cli_reset_map_stats); +- set_handler_callback(ADD+PATH, cli_add_path); +- set_handler_callback(DEL+PATH, cli_del_path); +- set_handler_callback(ADD+MAP, cli_add_map); +- set_handler_callback(DEL+MAP, cli_del_map); +- set_handler_callback(DEL+MAPS, cli_del_maps); +- set_handler_callback(SWITCH+MAP+GROUP, cli_switch_group); +- set_unlocked_handler_callback(RECONFIGURE, cli_reconfigure); +- set_handler_callback(SUSPEND+MAP, cli_suspend); +- set_handler_callback(RESUME+MAP, cli_resume); +- set_handler_callback(RESIZE+MAP, cli_resize); +- set_handler_callback(RELOAD+MAP, cli_reload); +- set_handler_callback(RESET+MAP, cli_reassign); +- set_handler_callback(REINSTATE+PATH, cli_reinstate); +- set_handler_callback(FAIL+PATH, cli_fail); +- set_handler_callback(DISABLEQ+MAP, cli_disable_queueing); +- set_handler_callback(RESTOREQ+MAP, cli_restore_queueing); +- set_handler_callback(DISABLEQ+MAPS, cli_disable_all_queueing); +- set_handler_callback(RESTOREQ+MAPS, cli_restore_all_queueing); +- set_unlocked_handler_callback(QUIT, cli_quit); +- set_unlocked_handler_callback(SHUTDOWN, cli_shutdown); +- set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus); +- set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus); +- set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus); +- set_handler_callback(FORCEQ+DAEMON, cli_force_no_daemon_q); +- set_handler_callback(RESTOREQ+DAEMON, cli_restore_no_daemon_q); +- set_handler_callback(GETPRKEY+MAP, cli_getprkey); +- set_handler_callback(SETPRKEY+MAP+KEY, cli_setprkey); +- set_handler_callback(UNSETPRKEY+MAP, cli_unsetprkey); +- set_handler_callback(SETMARGINAL+PATH, cli_set_marginal); +- set_handler_callback(UNSETMARGINAL+PATH, cli_unset_marginal); +- set_handler_callback(UNSETMARGINAL+MAP, cli_unset_all_marginal); +- ++ init_handler_callbacks(); + umask(077); + uxsock_listen(&uxsock_trigger, ux_sock, ap); + +-- +2.33.0 \ No newline at end of file diff --git a/0021-multipathd-Fix-command-completion-in-interactive-mod.patch b/0021-multipathd-Fix-command-completion-in-interactive-mod.patch new file mode 100644 index 0000000..d9a98e4 --- /dev/null +++ b/0021-multipathd-Fix-command-completion-in-interactive-mod.patch @@ -0,0 +1,192 @@ +From 146126a01c97dcc9faba14e56e1bed951e40450b Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 24 Aug 2022 22:39:44 +0200 +Subject: [PATCH] multipathd: Fix command completion in interactive mode + +The command completion never worked, because the handlers +array wasn't initialized in client mode. + +The handlers array is now also required in multipathc, +but it doesn't need the actual handler functions. To keep +multipathc as small as possible, we just add a handler table +with NULL handler functions. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +--- + multipathd/callbacks.c | 60 ++++++++++++++++++++++++++++++++++++++ + multipathd/cli.c | 2 ++ + multipathd/cli_handlers.c | 61 ++------------------------------------- + multipathd/main.c | 1 - + 4 files changed, 64 insertions(+), 60 deletions(-) + create mode 100644 multipathd/callbacks.c + +diff --git a/multipathd/callbacks.c b/multipathd/callbacks.c +new file mode 100644 +index 0000000..0bd76b7 +--- /dev/null ++++ b/multipathd/callbacks.c +@@ -0,0 +1,60 @@ ++void init_handler_callbacks(void) ++{ ++ set_handler_callback(LIST+PATHS, HANDLER(cli_list_paths)); ++ set_handler_callback(LIST+PATHS+FMT, HANDLER(cli_list_paths_fmt)); ++ set_handler_callback(LIST+PATHS+RAW+FMT, HANDLER(cli_list_paths_raw)); ++ set_handler_callback(LIST+PATH, HANDLER(cli_list_path)); ++ set_handler_callback(LIST+MAPS, HANDLER(cli_list_maps)); ++ set_handler_callback(LIST+STATUS, HANDLER(cli_list_status)); ++ set_unlocked_handler_callback(LIST+DAEMON, HANDLER(cli_list_daemon)); ++ set_handler_callback(LIST+MAPS+STATUS, HANDLER(cli_list_maps_status)); ++ set_handler_callback(LIST+MAPS+STATS, HANDLER(cli_list_maps_stats)); ++ set_handler_callback(LIST+MAPS+FMT, HANDLER(cli_list_maps_fmt)); ++ set_handler_callback(LIST+MAPS+RAW+FMT, HANDLER(cli_list_maps_raw)); ++ set_handler_callback(LIST+MAPS+TOPOLOGY, HANDLER(cli_list_maps_topology)); ++ set_handler_callback(LIST+TOPOLOGY, HANDLER(cli_list_maps_topology)); ++ set_handler_callback(LIST+MAPS+JSON, HANDLER(cli_list_maps_json)); ++ set_handler_callback(LIST+MAP+TOPOLOGY, HANDLER(cli_list_map_topology)); ++ set_handler_callback(LIST+MAP+FMT, HANDLER(cli_list_map_fmt)); ++ set_handler_callback(LIST+MAP+RAW+FMT, HANDLER(cli_list_map_fmt)); ++ set_handler_callback(LIST+MAP+JSON, HANDLER(cli_list_map_json)); ++ set_handler_callback(LIST+CONFIG+LOCAL, HANDLER(cli_list_config_local)); ++ set_handler_callback(LIST+CONFIG, HANDLER(cli_list_config)); ++ set_handler_callback(LIST+BLACKLIST, HANDLER(cli_list_blacklist)); ++ set_handler_callback(LIST+DEVICES, HANDLER(cli_list_devices)); ++ set_handler_callback(LIST+WILDCARDS, HANDLER(cli_list_wildcards)); ++ set_handler_callback(RESET+MAPS+STATS, HANDLER(cli_reset_maps_stats)); ++ set_handler_callback(RESET+MAP+STATS, HANDLER(cli_reset_map_stats)); ++ set_handler_callback(ADD+PATH, HANDLER(cli_add_path)); ++ set_handler_callback(DEL+PATH, HANDLER(cli_del_path)); ++ set_handler_callback(ADD+MAP, HANDLER(cli_add_map)); ++ set_handler_callback(DEL+MAP, HANDLER(cli_del_map)); ++ set_handler_callback(DEL+MAPS, HANDLER(cli_del_maps)); ++ set_handler_callback(SWITCH+MAP+GROUP, HANDLER(cli_switch_group)); ++ set_unlocked_handler_callback(RECONFIGURE, HANDLER(cli_reconfigure)); ++ set_unlocked_handler_callback(RECONFIGURE+ALL, HANDLER(cli_reconfigure_all)); ++ set_handler_callback(SUSPEND+MAP, HANDLER(cli_suspend)); ++ set_handler_callback(RESUME+MAP, HANDLER(cli_resume)); ++ set_handler_callback(RESIZE+MAP, HANDLER(cli_resize)); ++ set_handler_callback(RELOAD+MAP, HANDLER(cli_reload)); ++ set_handler_callback(RESET+MAP, HANDLER(cli_reassign)); ++ set_handler_callback(REINSTATE+PATH, HANDLER(cli_reinstate)); ++ set_handler_callback(FAIL+PATH, HANDLER(cli_fail)); ++ set_handler_callback(DISABLEQ+MAP, HANDLER(cli_disable_queueing)); ++ set_handler_callback(RESTOREQ+MAP, HANDLER(cli_restore_queueing)); ++ set_handler_callback(DISABLEQ+MAPS, HANDLER(cli_disable_all_queueing)); ++ set_handler_callback(RESTOREQ+MAPS, HANDLER(cli_restore_all_queueing)); ++ set_unlocked_handler_callback(QUIT, HANDLER(cli_quit)); ++ set_unlocked_handler_callback(SHUTDOWN, HANDLER(cli_shutdown)); ++ set_handler_callback(GETPRSTATUS+MAP, HANDLER(cli_getprstatus)); ++ set_handler_callback(SETPRSTATUS+MAP, HANDLER(cli_setprstatus)); ++ set_handler_callback(UNSETPRSTATUS+MAP, HANDLER(cli_unsetprstatus)); ++ set_handler_callback(FORCEQ+DAEMON, HANDLER(cli_force_no_daemon_q)); ++ set_handler_callback(RESTOREQ+DAEMON, HANDLER(cli_restore_no_daemon_q)); ++ set_handler_callback(GETPRKEY+MAP, HANDLER(cli_getprkey)); ++ set_handler_callback(SETPRKEY+MAP+KEY, HANDLER(cli_setprkey)); ++ set_handler_callback(UNSETPRKEY+MAP, HANDLER(cli_unsetprkey)); ++ set_handler_callback(SETMARGINAL+PATH, HANDLER(cli_set_marginal)); ++ set_handler_callback(UNSETMARGINAL+PATH, HANDLER(cli_unset_marginal)); ++ set_handler_callback(UNSETMARGINAL+MAP, HANDLER(cli_unset_all_marginal)); ++} +diff --git a/multipathd/cli.c b/multipathd/cli.c +index ddeb5fc..7cc1d44 100644 +--- a/multipathd/cli.c ++++ b/multipathd/cli.c +@@ -16,6 +16,7 @@ + + #include "mpath_cmd.h" + #include "cli.h" ++#include "cli_handlers.h" + #include "debug.h" + #include "strbuf.h" + +@@ -506,6 +507,7 @@ cli_init (void) { + if (alloc_handlers()) + return 1; + ++ init_handler_callbacks(); + return 0; + } + +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index f75e176..7d4f267 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -1547,62 +1547,5 @@ static int cli_unset_all_marginal(void * v, char ** reply, int * len, void * dat + return reload_and_sync_map(mpp, vecs, 0); + } + +-void init_handler_callbacks(void) +-{ +- set_handler_callback(LIST+PATHS, cli_list_paths); +- set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt); +- set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw); +- set_handler_callback(LIST+PATH, cli_list_path); +- set_handler_callback(LIST+MAPS, cli_list_maps); +- set_handler_callback(LIST+STATUS, cli_list_status); +- set_unlocked_handler_callback(LIST+DAEMON, cli_list_daemon); +- set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status); +- set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats); +- set_handler_callback(LIST+MAPS+FMT, cli_list_maps_fmt); +- set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw); +- set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology); +- set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology); +- set_handler_callback(LIST+MAPS+JSON, cli_list_maps_json); +- set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology); +- set_handler_callback(LIST+MAP+FMT, cli_list_map_fmt); +- set_handler_callback(LIST+MAP+RAW+FMT, cli_list_map_fmt); +- set_handler_callback(LIST+MAP+JSON, cli_list_map_json); +- set_handler_callback(LIST+CONFIG+LOCAL, cli_list_config_local); +- set_handler_callback(LIST+CONFIG, cli_list_config); +- set_handler_callback(LIST+BLACKLIST, cli_list_blacklist); +- set_handler_callback(LIST+DEVICES, cli_list_devices); +- set_handler_callback(LIST+WILDCARDS, cli_list_wildcards); +- set_handler_callback(RESET+MAPS+STATS, cli_reset_maps_stats); +- set_handler_callback(RESET+MAP+STATS, cli_reset_map_stats); +- set_handler_callback(ADD+PATH, cli_add_path); +- set_handler_callback(DEL+PATH, cli_del_path); +- set_handler_callback(ADD+MAP, cli_add_map); +- set_handler_callback(DEL+MAP, cli_del_map); +- set_handler_callback(DEL+MAPS, cli_del_maps); +- set_handler_callback(SWITCH+MAP+GROUP, cli_switch_group); +- set_unlocked_handler_callback(RECONFIGURE, cli_reconfigure); +- set_handler_callback(SUSPEND+MAP, cli_suspend); +- set_handler_callback(RESUME+MAP, cli_resume); +- set_handler_callback(RESIZE+MAP, cli_resize); +- set_handler_callback(RELOAD+MAP, cli_reload); +- set_handler_callback(RESET+MAP, cli_reassign); +- set_handler_callback(REINSTATE+PATH, cli_reinstate); +- set_handler_callback(FAIL+PATH, cli_fail); +- set_handler_callback(DISABLEQ+MAP, cli_disable_queueing); +- set_handler_callback(RESTOREQ+MAP, cli_restore_queueing); +- set_handler_callback(DISABLEQ+MAPS, cli_disable_all_queueing); +- set_handler_callback(RESTOREQ+MAPS, cli_restore_all_queueing); +- set_unlocked_handler_callback(QUIT, cli_quit); +- set_unlocked_handler_callback(SHUTDOWN, cli_shutdown); +- set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus); +- set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus); +- set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus); +- set_handler_callback(FORCEQ+DAEMON, cli_force_no_daemon_q); +- set_handler_callback(RESTOREQ+DAEMON, cli_restore_no_daemon_q); +- set_handler_callback(GETPRKEY+MAP, cli_getprkey); +- set_handler_callback(SETPRKEY+MAP+KEY, cli_setprkey); +- set_handler_callback(UNSETPRKEY+MAP, cli_unsetprkey); +- set_handler_callback(SETMARGINAL+PATH, cli_set_marginal); +- set_handler_callback(UNSETMARGINAL+PATH, cli_unset_marginal); +- set_handler_callback(UNSETMARGINAL+MAP, cli_unset_all_marginal); +-} ++#define HANDLER(x) x ++#include "callbacks.c" +diff --git a/multipathd/main.c b/multipathd/main.c +index 08fb992..be7ae60 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1669,7 +1669,6 @@ uxlsnrloop (void * ap) + /* Tell main thread that thread has started */ + post_config_state(DAEMON_CONFIGURE); + +- init_handler_callbacks(); + umask(077); + uxsock_listen(&uxsock_trigger, ux_sock, ap); + +-- +2.33.0 \ No newline at end of file diff --git a/0022-multipathd-more-robust-command-parsing.patch b/0022-multipathd-more-robust-command-parsing.patch new file mode 100644 index 0000000..e058015 --- /dev/null +++ b/0022-multipathd-more-robust-command-parsing.patch @@ -0,0 +1,923 @@ +From 2ae4f1581892b4a613fa58ad9ba7b5815057d0c8 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 24 Aug 2022 19:05:08 +0200 +Subject: [PATCH] multipathd: more robust command parsing + +The current parser allows commands like "path sda show" or "list list +add path sda", because it doesn't enforce ordering of the keywords +and simply adds rather than or-s the values of the keys. + +Rework this by using a separate byte for the "verb" and the allowed +qualifiers in the different positions of the command. No command +needs more than 3 qualifiers, so we disallow command vectors with +more than 4 elements, and change the type of the fingerprint to +uint32_t. + +init_callbacks() is now required in both multipathc and multipathd +to initialize the table of handlers and fingerprints. But as m +ultipathc never calls any handler, we need not link the +entire handlers code into it. + +Signed-off-by: Martin Wilck +Reviewed-by: Benjamin Marzinski +--- + multipathd/callbacks.c | 124 ++++++++++++++------------ + multipathd/cli.c | 160 ++++++++++++++++++---------------- + multipathd/cli.h | 179 +++++++++++++++++++------------------- + multipathd/cli_handlers.c | 70 +++++++-------- + 4 files changed, 277 insertions(+), 256 deletions(-) + +diff --git a/multipathd/callbacks.c b/multipathd/callbacks.c +index 0bd76b7..6b766b1 100644 +--- a/multipathd/callbacks.c ++++ b/multipathd/callbacks.c +@@ -1,60 +1,70 @@ + void init_handler_callbacks(void) + { +- set_handler_callback(LIST+PATHS, HANDLER(cli_list_paths)); +- set_handler_callback(LIST+PATHS+FMT, HANDLER(cli_list_paths_fmt)); +- set_handler_callback(LIST+PATHS+RAW+FMT, HANDLER(cli_list_paths_raw)); +- set_handler_callback(LIST+PATH, HANDLER(cli_list_path)); +- set_handler_callback(LIST+MAPS, HANDLER(cli_list_maps)); +- set_handler_callback(LIST+STATUS, HANDLER(cli_list_status)); +- set_unlocked_handler_callback(LIST+DAEMON, HANDLER(cli_list_daemon)); +- set_handler_callback(LIST+MAPS+STATUS, HANDLER(cli_list_maps_status)); +- set_handler_callback(LIST+MAPS+STATS, HANDLER(cli_list_maps_stats)); +- set_handler_callback(LIST+MAPS+FMT, HANDLER(cli_list_maps_fmt)); +- set_handler_callback(LIST+MAPS+RAW+FMT, HANDLER(cli_list_maps_raw)); +- set_handler_callback(LIST+MAPS+TOPOLOGY, HANDLER(cli_list_maps_topology)); +- set_handler_callback(LIST+TOPOLOGY, HANDLER(cli_list_maps_topology)); +- set_handler_callback(LIST+MAPS+JSON, HANDLER(cli_list_maps_json)); +- set_handler_callback(LIST+MAP+TOPOLOGY, HANDLER(cli_list_map_topology)); +- set_handler_callback(LIST+MAP+FMT, HANDLER(cli_list_map_fmt)); +- set_handler_callback(LIST+MAP+RAW+FMT, HANDLER(cli_list_map_fmt)); +- set_handler_callback(LIST+MAP+JSON, HANDLER(cli_list_map_json)); +- set_handler_callback(LIST+CONFIG+LOCAL, HANDLER(cli_list_config_local)); +- set_handler_callback(LIST+CONFIG, HANDLER(cli_list_config)); +- set_handler_callback(LIST+BLACKLIST, HANDLER(cli_list_blacklist)); +- set_handler_callback(LIST+DEVICES, HANDLER(cli_list_devices)); +- set_handler_callback(LIST+WILDCARDS, HANDLER(cli_list_wildcards)); +- set_handler_callback(RESET+MAPS+STATS, HANDLER(cli_reset_maps_stats)); +- set_handler_callback(RESET+MAP+STATS, HANDLER(cli_reset_map_stats)); +- set_handler_callback(ADD+PATH, HANDLER(cli_add_path)); +- set_handler_callback(DEL+PATH, HANDLER(cli_del_path)); +- set_handler_callback(ADD+MAP, HANDLER(cli_add_map)); +- set_handler_callback(DEL+MAP, HANDLER(cli_del_map)); +- set_handler_callback(DEL+MAPS, HANDLER(cli_del_maps)); +- set_handler_callback(SWITCH+MAP+GROUP, HANDLER(cli_switch_group)); +- set_unlocked_handler_callback(RECONFIGURE, HANDLER(cli_reconfigure)); +- set_unlocked_handler_callback(RECONFIGURE+ALL, HANDLER(cli_reconfigure_all)); +- set_handler_callback(SUSPEND+MAP, HANDLER(cli_suspend)); +- set_handler_callback(RESUME+MAP, HANDLER(cli_resume)); +- set_handler_callback(RESIZE+MAP, HANDLER(cli_resize)); +- set_handler_callback(RELOAD+MAP, HANDLER(cli_reload)); +- set_handler_callback(RESET+MAP, HANDLER(cli_reassign)); +- set_handler_callback(REINSTATE+PATH, HANDLER(cli_reinstate)); +- set_handler_callback(FAIL+PATH, HANDLER(cli_fail)); +- set_handler_callback(DISABLEQ+MAP, HANDLER(cli_disable_queueing)); +- set_handler_callback(RESTOREQ+MAP, HANDLER(cli_restore_queueing)); +- set_handler_callback(DISABLEQ+MAPS, HANDLER(cli_disable_all_queueing)); +- set_handler_callback(RESTOREQ+MAPS, HANDLER(cli_restore_all_queueing)); +- set_unlocked_handler_callback(QUIT, HANDLER(cli_quit)); +- set_unlocked_handler_callback(SHUTDOWN, HANDLER(cli_shutdown)); +- set_handler_callback(GETPRSTATUS+MAP, HANDLER(cli_getprstatus)); +- set_handler_callback(SETPRSTATUS+MAP, HANDLER(cli_setprstatus)); +- set_handler_callback(UNSETPRSTATUS+MAP, HANDLER(cli_unsetprstatus)); +- set_handler_callback(FORCEQ+DAEMON, HANDLER(cli_force_no_daemon_q)); +- set_handler_callback(RESTOREQ+DAEMON, HANDLER(cli_restore_no_daemon_q)); +- set_handler_callback(GETPRKEY+MAP, HANDLER(cli_getprkey)); +- set_handler_callback(SETPRKEY+MAP+KEY, HANDLER(cli_setprkey)); +- set_handler_callback(UNSETPRKEY+MAP, HANDLER(cli_unsetprkey)); +- set_handler_callback(SETMARGINAL+PATH, HANDLER(cli_set_marginal)); +- set_handler_callback(UNSETMARGINAL+PATH, HANDLER(cli_unset_marginal)); +- set_handler_callback(UNSETMARGINAL+MAP, HANDLER(cli_unset_all_marginal)); ++ set_handler_callback(VRB_LIST | Q1_PATHS, HANDLER(cli_list_paths)); ++ set_handler_callback(VRB_LIST | Q1_PATHS | Q2_FMT, HANDLER(cli_list_paths_fmt)); ++ set_handler_callback(VRB_LIST | Q1_PATHS | Q2_RAW | Q3_FMT, ++ HANDLER(cli_list_paths_raw)); ++ set_handler_callback(VRB_LIST | Q1_PATH, HANDLER(cli_list_path)); ++ set_handler_callback(VRB_LIST | Q1_MAPS, HANDLER(cli_list_maps)); ++ set_handler_callback(VRB_LIST | Q1_STATUS, HANDLER(cli_list_status)); ++ set_unlocked_handler_callback(VRB_LIST | Q1_DAEMON, HANDLER(cli_list_daemon)); ++ set_handler_callback(VRB_LIST | Q1_MAPS | Q2_STATUS, ++ HANDLER(cli_list_maps_status)); ++ set_handler_callback(VRB_LIST | Q1_MAPS | Q2_STATS, ++ HANDLER(cli_list_maps_stats)); ++ set_handler_callback(VRB_LIST | Q1_MAPS | Q2_FMT, HANDLER(cli_list_maps_fmt)); ++ set_handler_callback(VRB_LIST | Q1_MAPS | Q2_RAW | Q3_FMT, ++ HANDLER(cli_list_maps_raw)); ++ set_handler_callback(VRB_LIST | Q1_MAPS | Q2_TOPOLOGY, ++ HANDLER(cli_list_maps_topology)); ++ set_handler_callback(VRB_LIST | Q1_TOPOLOGY, HANDLER(cli_list_maps_topology)); ++ set_handler_callback(VRB_LIST | Q1_MAPS | Q2_JSON, HANDLER(cli_list_maps_json)); ++ set_handler_callback(VRB_LIST | Q1_MAP | Q2_TOPOLOGY, ++ HANDLER(cli_list_map_topology)); ++ set_handler_callback(VRB_LIST | Q1_MAP | Q2_FMT, HANDLER(cli_list_map_fmt)); ++ set_handler_callback(VRB_LIST | Q1_MAP | Q2_RAW | Q3_FMT, ++ HANDLER(cli_list_map_fmt)); ++ set_handler_callback(VRB_LIST | Q1_MAP | Q2_JSON, HANDLER(cli_list_map_json)); ++ set_handler_callback(VRB_LIST | Q1_CONFIG | Q2_LOCAL, ++ HANDLER(cli_list_config_local)); ++ set_handler_callback(VRB_LIST | Q1_CONFIG, HANDLER(cli_list_config)); ++ set_handler_callback(VRB_LIST | Q1_BLACKLIST, HANDLER(cli_list_blacklist)); ++ set_handler_callback(VRB_LIST | Q1_DEVICES, HANDLER(cli_list_devices)); ++ set_handler_callback(VRB_LIST | Q1_WILDCARDS, HANDLER(cli_list_wildcards)); ++ set_handler_callback(VRB_RESET | Q1_MAPS | Q2_STATS, ++ HANDLER(cli_reset_maps_stats)); ++ set_handler_callback(VRB_RESET | Q1_MAP | Q2_STATS, ++ HANDLER(cli_reset_map_stats)); ++ set_handler_callback(VRB_ADD | Q1_PATH, HANDLER(cli_add_path)); ++ set_handler_callback(VRB_DEL | Q1_PATH, HANDLER(cli_del_path)); ++ set_handler_callback(VRB_ADD | Q1_MAP, HANDLER(cli_add_map)); ++ set_handler_callback(VRB_DEL | Q1_MAP, HANDLER(cli_del_map)); ++ set_handler_callback(VRB_DEL | Q1_MAPS, HANDLER(cli_del_maps)); ++ set_handler_callback(VRB_SWITCH | Q1_MAP | Q2_GROUP, HANDLER(cli_switch_group)); ++ set_unlocked_handler_callback(VRB_RECONFIGURE, HANDLER(cli_reconfigure)); ++ set_handler_callback(VRB_SUSPEND | Q1_MAP, HANDLER(cli_suspend)); ++ set_handler_callback(VRB_RESUME | Q1_MAP, HANDLER(cli_resume)); ++ set_handler_callback(VRB_RESIZE | Q1_MAP, HANDLER(cli_resize)); ++ set_handler_callback(VRB_RELOAD | Q1_MAP, HANDLER(cli_reload)); ++ set_handler_callback(VRB_RESET | Q1_MAP, HANDLER(cli_reassign)); ++ set_handler_callback(VRB_REINSTATE | Q1_PATH, HANDLER(cli_reinstate)); ++ set_handler_callback(VRB_FAIL | Q1_PATH, HANDLER(cli_fail)); ++ set_handler_callback(VRB_DISABLEQ | Q1_MAP, HANDLER(cli_disable_queueing)); ++ set_handler_callback(VRB_RESTOREQ | Q1_MAP, HANDLER(cli_restore_queueing)); ++ set_handler_callback(VRB_DISABLEQ | Q1_MAPS, HANDLER(cli_disable_all_queueing)); ++ set_handler_callback(VRB_RESTOREQ | Q1_MAPS, HANDLER(cli_restore_all_queueing)); ++ set_unlocked_handler_callback(VRB_QUIT, HANDLER(cli_quit)); ++ set_unlocked_handler_callback(VRB_SHUTDOWN, HANDLER(cli_shutdown)); ++ set_handler_callback(VRB_GETPRSTATUS | Q1_MAP, HANDLER(cli_getprstatus)); ++ set_handler_callback(VRB_SETPRSTATUS | Q1_MAP, HANDLER(cli_setprstatus)); ++ set_handler_callback(VRB_UNSETPRSTATUS | Q1_MAP, HANDLER(cli_unsetprstatus)); ++ set_handler_callback(VRB_FORCEQ | Q1_DAEMON, HANDLER(cli_force_no_daemon_q)); ++ set_handler_callback(VRB_RESTOREQ | Q1_DAEMON, HANDLER(cli_restore_no_daemon_q)); ++ set_handler_callback(VRB_GETPRKEY | Q1_MAP, HANDLER(cli_getprkey)); ++ set_handler_callback(VRB_SETPRKEY | Q1_MAP | Q2_KEY, HANDLER(cli_setprkey)); ++ set_handler_callback(VRB_UNSETPRKEY | Q1_MAP, HANDLER(cli_unsetprkey)); ++ set_handler_callback(VRB_SETMARGINAL | Q1_PATH, HANDLER(cli_set_marginal)); ++ set_handler_callback(VRB_UNSETMARGINAL | Q1_PATH, HANDLER(cli_unset_marginal)); ++ set_handler_callback(VRB_UNSETMARGINAL | Q1_MAP, ++ HANDLER(cli_unset_all_marginal)); + } +diff --git a/multipathd/cli.c b/multipathd/cli.c +index 8033db0..333e995 100644 +--- a/multipathd/cli.c ++++ b/multipathd/cli.c +@@ -23,6 +23,9 @@ + static vector keys; + static vector handlers; + ++/* See KEY_INVALID in cli.h */ ++#define INVALID_FINGERPRINT ((uint32_t)(0)) ++ + static struct key * + alloc_key (void) + { +@@ -36,7 +39,7 @@ alloc_handler (void) + } + + static int +-add_key (vector vec, char * str, uint64_t code, int has_param) ++add_key (vector vec, char * str, uint8_t code, int has_param) + { + struct key * kw; + +@@ -67,7 +70,7 @@ out: + } + + +-static struct handler *add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *), bool locked) ++static struct handler *add_handler (uint32_t fp, int (*fn)(void *, char **, int *, void *), bool locked) + { + struct handler * h; + +@@ -90,11 +93,13 @@ static struct handler *add_handler (uint64_t fp, int (*fn)(void *, char **, int + } + + static struct handler * +-find_handler (uint64_t fp) ++find_handler (uint32_t fp) + { + int i; + struct handler *h; + ++ if (fp == INVALID_FINGERPRINT) ++ return NULL; + vector_foreach_slot (handlers, h, i) + if (h->fingerprint == fp) + return h; +@@ -103,14 +108,14 @@ find_handler (uint64_t fp) + } + + int +-__set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *), bool locked) ++__set_handler_callback (uint32_t fp, int (*fn)(void *, char **, int *, void *), bool locked) + { + struct handler *h; + + assert(find_handler(fp) == NULL); + h = add_handler(fp, fn, locked); + if (!h) { +- condlog(0, "%s: failed to set handler for code %"PRIu64, ++ condlog(0, "%s: failed to set handler for code %"PRIu32, + __func__, fp); + return 1; + } +@@ -163,55 +168,55 @@ load_keys (void) + if (!keys) + return 1; + +- r += add_key(keys, "list", LIST, 0); +- r += add_key(keys, "show", LIST, 0); +- r += add_key(keys, "add", ADD, 0); +- r += add_key(keys, "remove", DEL, 0); +- r += add_key(keys, "del", DEL, 0); +- r += add_key(keys, "switch", SWITCH, 0); +- r += add_key(keys, "switchgroup", SWITCH, 0); +- r += add_key(keys, "suspend", SUSPEND, 0); +- r += add_key(keys, "resume", RESUME, 0); +- r += add_key(keys, "reinstate", REINSTATE, 0); +- r += add_key(keys, "fail", FAIL, 0); +- r += add_key(keys, "resize", RESIZE, 0); +- r += add_key(keys, "reset", RESET, 0); +- r += add_key(keys, "reload", RELOAD, 0); +- r += add_key(keys, "forcequeueing", FORCEQ, 0); +- r += add_key(keys, "disablequeueing", DISABLEQ, 0); +- r += add_key(keys, "restorequeueing", RESTOREQ, 0); +- r += add_key(keys, "paths", PATHS, 0); +- r += add_key(keys, "maps", MAPS, 0); +- r += add_key(keys, "multipaths", MAPS, 0); +- r += add_key(keys, "path", PATH, 1); +- r += add_key(keys, "map", MAP, 1); +- r += add_key(keys, "multipath", MAP, 1); +- r += add_key(keys, "group", GROUP, 1); +- r += add_key(keys, "reconfigure", RECONFIGURE, 0); +- r += add_key(keys, "daemon", DAEMON, 0); +- r += add_key(keys, "status", STATUS, 0); +- r += add_key(keys, "stats", STATS, 0); +- r += add_key(keys, "topology", TOPOLOGY, 0); +- r += add_key(keys, "config", CONFIG, 0); +- r += add_key(keys, "blacklist", BLACKLIST, 0); +- r += add_key(keys, "devices", DEVICES, 0); +- r += add_key(keys, "raw", RAW, 0); +- r += add_key(keys, "wildcards", WILDCARDS, 0); +- r += add_key(keys, "quit", QUIT, 0); +- r += add_key(keys, "exit", QUIT, 0); +- r += add_key(keys, "shutdown", SHUTDOWN, 0); +- r += add_key(keys, "getprstatus", GETPRSTATUS, 0); +- r += add_key(keys, "setprstatus", SETPRSTATUS, 0); +- r += add_key(keys, "unsetprstatus", UNSETPRSTATUS, 0); +- r += add_key(keys, "format", FMT, 1); +- r += add_key(keys, "json", JSON, 0); +- r += add_key(keys, "getprkey", GETPRKEY, 0); +- r += add_key(keys, "setprkey", SETPRKEY, 0); +- r += add_key(keys, "unsetprkey", UNSETPRKEY, 0); +- r += add_key(keys, "key", KEY, 1); +- r += add_key(keys, "local", LOCAL, 0); +- r += add_key(keys, "setmarginal", SETMARGINAL, 0); +- r += add_key(keys, "unsetmarginal", UNSETMARGINAL, 0); ++ r += add_key(keys, "list", VRB_LIST, 0); ++ r += add_key(keys, "show", VRB_LIST, 0); ++ r += add_key(keys, "add", VRB_ADD, 0); ++ r += add_key(keys, "remove", VRB_DEL, 0); ++ r += add_key(keys, "del", VRB_DEL, 0); ++ r += add_key(keys, "switch", VRB_SWITCH, 0); ++ r += add_key(keys, "switchgroup", VRB_SWITCH, 0); ++ r += add_key(keys, "suspend", VRB_SUSPEND, 0); ++ r += add_key(keys, "resume", VRB_RESUME, 0); ++ r += add_key(keys, "reinstate", VRB_REINSTATE, 0); ++ r += add_key(keys, "fail", VRB_FAIL, 0); ++ r += add_key(keys, "resize", VRB_RESIZE, 0); ++ r += add_key(keys, "reset", VRB_RESET, 0); ++ r += add_key(keys, "reload", VRB_RELOAD, 0); ++ r += add_key(keys, "forcequeueing", VRB_FORCEQ, 0); ++ r += add_key(keys, "disablequeueing", VRB_DISABLEQ, 0); ++ r += add_key(keys, "restorequeueing", VRB_RESTOREQ, 0); ++ r += add_key(keys, "paths", KEY_PATHS, 0); ++ r += add_key(keys, "maps", KEY_MAPS, 0); ++ r += add_key(keys, "multipaths", KEY_MAPS, 0); ++ r += add_key(keys, "path", KEY_PATH, 1); ++ r += add_key(keys, "map", KEY_MAP, 1); ++ r += add_key(keys, "multipath", KEY_MAP, 1); ++ r += add_key(keys, "group", KEY_GROUP, 1); ++ r += add_key(keys, "reconfigure", VRB_RECONFIGURE, 0); ++ r += add_key(keys, "daemon", KEY_DAEMON, 0); ++ r += add_key(keys, "status", KEY_STATUS, 0); ++ r += add_key(keys, "stats", KEY_STATS, 0); ++ r += add_key(keys, "topology", KEY_TOPOLOGY, 0); ++ r += add_key(keys, "config", KEY_CONFIG, 0); ++ r += add_key(keys, "blacklist", KEY_BLACKLIST, 0); ++ r += add_key(keys, "devices", KEY_DEVICES, 0); ++ r += add_key(keys, "raw", KEY_RAW, 0); ++ r += add_key(keys, "wildcards", KEY_WILDCARDS, 0); ++ r += add_key(keys, "quit", VRB_QUIT, 0); ++ r += add_key(keys, "exit", VRB_QUIT, 0); ++ r += add_key(keys, "shutdown", VRB_SHUTDOWN, 0); ++ r += add_key(keys, "getprstatus", VRB_GETPRSTATUS, 0); ++ r += add_key(keys, "setprstatus", VRB_SETPRSTATUS, 0); ++ r += add_key(keys, "unsetprstatus", VRB_UNSETPRSTATUS, 0); ++ r += add_key(keys, "format", KEY_FMT, 1); ++ r += add_key(keys, "json", KEY_JSON, 0); ++ r += add_key(keys, "getprkey", VRB_GETPRKEY, 0); ++ r += add_key(keys, "setprkey", VRB_SETPRKEY, 0); ++ r += add_key(keys, "unsetprkey", VRB_UNSETPRKEY, 0); ++ r += add_key(keys, "key", KEY_KEY, 1); ++ r += add_key(keys, "local", KEY_LOCAL, 0); ++ r += add_key(keys, "setmarginal", VRB_SETMARGINAL, 0); ++ r += add_key(keys, "unsetmarginal", VRB_UNSETMARGINAL, 0); + + + if (r) { +@@ -325,15 +330,17 @@ static uint64_t + fingerprint(vector vec) + { + int i; +- uint64_t fp = 0; ++ uint32_t fp = 0; + struct key * kw; + +- if (!vec) +- return 0; +- +- vector_foreach_slot(vec, kw, i) +- fp += kw->code; ++ if (!vec || VECTOR_SIZE(vec) > 4) ++ return INVALID_FINGERPRINT; + ++ vector_foreach_slot(vec, kw, i) { ++ if (i >= 4) ++ break; ++ fp |= (uint32_t)kw->code << (8 * i); ++ } + return fp; + } + +@@ -367,8 +374,8 @@ genhelp_sprint_aliases (struct strbuf *reply, vector keys, + + static int + do_genhelp(struct strbuf *reply, const char *cmd, int error) { +- int i, j; +- uint64_t fp; ++ int i, j, k; ++ uint32_t fp; + struct handler * h; + struct key * kw; + int rc = 0; +@@ -394,17 +401,24 @@ do_genhelp(struct strbuf *reply, const char *cmd, int error) { + + vector_foreach_slot (handlers, h, i) { + fp = h->fingerprint; +- vector_foreach_slot (keys, kw, j) { +- if ((kw->code & fp)) { +- fp -= kw->code; +- if (print_strbuf(reply, " %s", kw->str) < 0 || +- genhelp_sprint_aliases(reply, keys, kw) < 0) +- return -1; +- +- if (kw->has_param) { +- if (print_strbuf(reply, " $%s", +- kw->str) < 0) ++ for (k = 0; k < 4; k++, fp >>= 8) { ++ uint32_t code = fp & 0xff; ++ ++ if (!code) ++ break; ++ ++ vector_foreach_slot (keys, kw, j) { ++ if ((uint32_t)kw->code == code) { ++ if (print_strbuf(reply, " %s", kw->str) < 0 || ++ genhelp_sprint_aliases(reply, keys, kw) < 0) + return -1; ++ ++ if (kw->has_param) { ++ if (print_strbuf(reply, " $%s", ++ kw->str) < 0) ++ return -1; ++ } ++ break; + } + } + } +@@ -487,7 +501,7 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout ) + } + + char * +-get_keyparam (vector v, uint64_t code) ++get_keyparam (vector v, uint8_t code) + { + struct key * kw; + int i; +diff --git a/multipathd/cli.h b/multipathd/cli.h +index a6704b1..7f53003 100644 +--- a/multipathd/cli.h ++++ b/multipathd/cli.h +@@ -4,96 +4,93 @@ + #include + + enum { +- __LIST, +- __ADD, +- __DEL, +- __SWITCH, +- __SUSPEND, +- __RESUME, +- __REINSTATE, +- __FAIL, +- __RESIZE, +- __RESET, +- __RELOAD, +- __FORCEQ, +- __DISABLEQ, +- __RESTOREQ, +- __PATHS, +- __MAPS, +- __PATH, +- __MAP, +- __GROUP, +- __RECONFIGURE, +- __DAEMON, +- __STATUS, +- __STATS, +- __TOPOLOGY, +- __CONFIG, +- __BLACKLIST, +- __DEVICES, +- __RAW, +- __WILDCARDS, +- __QUIT, +- __SHUTDOWN, +- __GETPRSTATUS, +- __SETPRSTATUS, +- __UNSETPRSTATUS, +- __FMT, +- __JSON, +- __GETPRKEY, +- __SETPRKEY, +- __UNSETPRKEY, +- __KEY, +- __LOCAL, +- __SETMARGINAL, +- __UNSETMARGINAL, ++ /* See INVALID_FINGERPRINT in cli.c */ ++ KEY_INVALID = 0, ++ ++ /* Verbs */ ++ VRB_LIST = 1, ++ VRB_ADD = 2, ++ VRB_DEL = 3, ++ VRB_RESET = 4, ++ VRB_SWITCH = 5, ++ VRB_RECONFIGURE = 6, ++ VRB_SUSPEND = 7, ++ VRB_RESUME = 8, ++ VRB_RESIZE = 9, ++ VRB_RELOAD = 10, ++ VRB_FAIL = 11, ++ VRB_REINSTATE = 12, ++ VRB_DISABLEQ = 13, ++ VRB_RESTOREQ = 14, ++ VRB_FORCEQ = 15, ++ VRB_GETPRSTATUS = 16, ++ VRB_SETPRSTATUS = 17, ++ VRB_UNSETPRSTATUS = 18, ++ VRB_GETPRKEY = 19, ++ VRB_SETPRKEY = 20, ++ VRB_UNSETPRKEY = 21, ++ VRB_SETMARGINAL = 22, ++ VRB_UNSETMARGINAL = 23, ++ VRB_SHUTDOWN = 24, ++ VRB_QUIT = 25, ++ ++ /* Qualifiers, values must be different from verbs */ ++ KEY_PATH = 65, ++ KEY_PATHS = 66, ++ KEY_MAP = 67, ++ KEY_MAPS = 68, ++ KEY_TOPOLOGY = 69, ++ KEY_CONFIG = 70, ++ KEY_BLACKLIST = 71, ++ KEY_DEVICES = 72, ++ KEY_WILDCARDS = 73, ++ KEY_ALL = 74, ++ KEY_DAEMON = 75, ++ KEY_FMT = 76, ++ KEY_RAW = 77, ++ KEY_STATUS = 78, ++ KEY_STATS = 79, ++ KEY_JSON = 80, ++ KEY_LOCAL = 81, ++ KEY_GROUP = 82, ++ KEY_KEY = 83, + }; + +-#define LIST (1 << __LIST) +-#define ADD (1 << __ADD) +-#define DEL (1 << __DEL) +-#define SWITCH (1 << __SWITCH) +-#define SUSPEND (1 << __SUSPEND) +-#define RESUME (1 << __RESUME) +-#define REINSTATE (1 << __REINSTATE) +-#define FAIL (1 << __FAIL) +-#define RESIZE (1 << __RESIZE) +-#define RESET (1 << __RESET) +-#define RELOAD (1 << __RELOAD) +-#define FORCEQ (1 << __FORCEQ) +-#define DISABLEQ (1 << __DISABLEQ) +-#define RESTOREQ (1 << __RESTOREQ) +-#define PATHS (1 << __PATHS) +-#define MAPS (1 << __MAPS) +-#define PATH (1 << __PATH) +-#define MAP (1 << __MAP) +-#define GROUP (1 << __GROUP) +-#define RECONFIGURE (1 << __RECONFIGURE) +-#define DAEMON (1 << __DAEMON) +-#define STATUS (1 << __STATUS) +-#define STATS (1 << __STATS) +-#define TOPOLOGY (1 << __TOPOLOGY) +-#define CONFIG (1 << __CONFIG) +-#define BLACKLIST (1 << __BLACKLIST) +-#define DEVICES (1 << __DEVICES) +-#define RAW (1 << __RAW) +-#define COUNT (1 << __COUNT) +-#define WILDCARDS (1 << __WILDCARDS) +-#define QUIT (1 << __QUIT) +-#define SHUTDOWN (1 << __SHUTDOWN) +-#define GETPRSTATUS (1ULL << __GETPRSTATUS) +-#define SETPRSTATUS (1ULL << __SETPRSTATUS) +-#define UNSETPRSTATUS (1ULL << __UNSETPRSTATUS) +-#define FMT (1ULL << __FMT) +-#define JSON (1ULL << __JSON) +-#define GETPRKEY (1ULL << __GETPRKEY) +-#define SETPRKEY (1ULL << __SETPRKEY) +-#define UNSETPRKEY (1ULL << __UNSETPRKEY) +-#define KEY (1ULL << __KEY) +-#define LOCAL (1ULL << __LOCAL) +-#define SETMARGINAL (1ULL << __SETMARGINAL) +-#define UNSETMARGINAL (1ULL << __UNSETMARGINAL) ++/* ++ * The shifted qualifiers determine valid positions of the ++ * keywords in the known commands. E.g. the only qualifier ++ * that's valid in position 3 is "fmt", e.g. "list maps raw fmt". ++ */ ++enum { ++ /* byte 1: qualifier 1 */ ++ Q1_PATH = KEY_PATH << 8, ++ Q1_PATHS = KEY_PATHS << 8, ++ Q1_MAP = KEY_MAP << 8, ++ Q1_MAPS = KEY_MAPS << 8, ++ Q1_TOPOLOGY = KEY_TOPOLOGY << 8, ++ Q1_CONFIG = KEY_CONFIG << 8, ++ Q1_BLACKLIST = KEY_BLACKLIST << 8, ++ Q1_DEVICES = KEY_DEVICES << 8, ++ Q1_WILDCARDS = KEY_WILDCARDS << 8, ++ Q1_ALL = KEY_ALL << 8, ++ Q1_DAEMON = KEY_DAEMON << 8, ++ Q1_STATUS = KEY_STATUS << 8, ++ ++ /* byte 2: qualifier 2 */ ++ Q2_FMT = KEY_FMT << 16, ++ Q2_RAW = KEY_RAW << 16, ++ Q2_STATUS = KEY_STATUS << 16, ++ Q2_STATS = KEY_STATS << 16, ++ Q2_TOPOLOGY = KEY_TOPOLOGY << 16, ++ Q2_JSON = KEY_JSON << 16, ++ Q2_LOCAL = KEY_LOCAL << 16, ++ Q2_GROUP = KEY_GROUP << 16, ++ Q2_KEY = KEY_KEY << 16, + ++ /* byte 3: qualifier 3 */ ++ Q3_FMT = KEY_FMT << 24, ++}; ++ + #define INITIAL_REPLY_LEN 1200 + + #define REALLOC_REPLY(r, a, m) \ +@@ -120,24 +117,24 @@ enum { + struct key { + char * str; + char * param; +- uint64_t code; ++ uint8_t code; + int has_param; + }; + + struct handler { +- uint64_t fingerprint; ++ uint32_t fingerprint; + int locked; + int (*fn)(void *, char **, int *, void *); + }; + + int alloc_handlers (void); +-int __set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *), bool locked); ++int __set_handler_callback (uint32_t fp, int (*fn)(void *, char **, int *, void *), bool locked); + #define set_handler_callback(fp, fn) __set_handler_callback(fp, fn, true) + #define set_unlocked_handler_callback(fp, fn) __set_handler_callback(fp, fn, false) + + int parse_cmd (char * cmd, char ** reply, int * len, void *, int); + int load_keys (void); +-char * get_keyparam (vector v, uint64_t code); ++char * get_keyparam (vector v, uint8_t code); + void free_keys (vector vec); + void free_handlers (void); + int cli_init (void); +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index 7d4f267..6d79287 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -237,7 +237,7 @@ static int + cli_list_paths_fmt (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * fmt = get_keyparam(v, FMT); ++ char * fmt = get_keyparam(v, KEY_FMT); + + condlog(3, "list paths (operator)"); + +@@ -248,7 +248,7 @@ static int + cli_list_paths_raw (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * fmt = get_keyparam(v, FMT); ++ char * fmt = get_keyparam(v, KEY_FMT); + + condlog(3, "list paths (operator)"); + +@@ -259,7 +259,7 @@ static int + cli_list_path (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, PATH); ++ char * param = get_keyparam(v, KEY_PATH); + struct path *pp; + + param = convert_dev(param, 1); +@@ -277,7 +277,7 @@ cli_list_map_topology (void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + + param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); +@@ -306,7 +306,7 @@ cli_list_map_json (void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + + param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); +@@ -423,7 +423,7 @@ static int + cli_list_maps_fmt (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * fmt = get_keyparam(v, FMT); ++ char * fmt = get_keyparam(v, KEY_FMT); + + condlog(3, "list maps (operator)"); + +@@ -434,7 +434,7 @@ static int + cli_list_maps_raw (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * fmt = get_keyparam(v, FMT); ++ char * fmt = get_keyparam(v, KEY_FMT); + + condlog(3, "list maps (operator)"); + +@@ -446,8 +446,8 @@ cli_list_map_fmt (void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); +- char * fmt = get_keyparam(v, FMT); ++ char * param = get_keyparam(v, KEY_MAP); ++ char * fmt = get_keyparam(v, KEY_FMT); + + param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); +@@ -529,7 +529,7 @@ cli_reset_map_stats (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; + struct multipath * mpp; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + + param = convert_dev(param, 0); + mpp = find_mp_by_str(vecs->mpvec, param); +@@ -546,7 +546,7 @@ static int + cli_add_path (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, PATH); ++ char * param = get_keyparam(v, KEY_PATH); + struct path *pp; + int r; + struct config *conf; +@@ -662,7 +662,7 @@ static int + cli_del_path (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, PATH); ++ char * param = get_keyparam(v, KEY_PATH); + struct path *pp; + int ret; + +@@ -685,7 +685,7 @@ static int + cli_add_map (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + int major = -1, minor = -1; + char dev_path[PATH_SIZE]; + char *refwwid, *alias = NULL; +@@ -745,7 +745,7 @@ static int + cli_del_map (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + int major, minor; + char *alias; + int rc; +@@ -790,7 +790,7 @@ static int + cli_reload(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +- char * mapname = get_keyparam(v, MAP); ++ char * mapname = get_keyparam(v, KEY_MAP); + struct multipath *mpp; + int minor; + +@@ -843,7 +843,7 @@ static int + cli_resize(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +- char * mapname = get_keyparam(v, MAP); ++ char * mapname = get_keyparam(v, KEY_MAP); + struct multipath *mpp; + int minor; + unsigned long long size, sz; +@@ -951,7 +951,7 @@ static int + cli_restore_queueing(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +- char * mapname = get_keyparam(v, MAP); ++ char * mapname = get_keyparam(v, KEY_MAP); + struct multipath *mpp; + int minor; + struct config *conf; +@@ -1014,7 +1014,7 @@ static int + cli_disable_queueing(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +- char * mapname = get_keyparam(v, MAP); ++ char * mapname = get_keyparam(v, KEY_MAP); + struct multipath *mpp; + int minor; + +@@ -1061,8 +1061,8 @@ cli_disable_all_queueing(void *v, char **reply, int *len, void *data) + static int + cli_switch_group(void * v, char ** reply, int * len, void * data) + { +- char * mapname = get_keyparam(v, MAP); +- int groupnum = atoi(get_keyparam(v, GROUP)); ++ char * mapname = get_keyparam(v, KEY_MAP); ++ int groupnum = atoi(get_keyparam(v, KEY_GROUP)); + + mapname = convert_dev(mapname, 0); + condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum); +@@ -1091,7 +1091,7 @@ static int + cli_suspend(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + int r; + struct multipath * mpp; + +@@ -1121,7 +1121,7 @@ static int + cli_resume(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + int r; + struct multipath * mpp; + uint16_t udev_flags; +@@ -1153,7 +1153,7 @@ static int + cli_reinstate(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, PATH); ++ char * param = get_keyparam(v, KEY_PATH); + struct path * pp; + + param = convert_dev(param, 1); +@@ -1176,7 +1176,7 @@ static int + cli_reassign (void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + struct multipath *mpp; + + param = convert_dev(param, 0); +@@ -1200,7 +1200,7 @@ static int + cli_fail(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, PATH); ++ char * param = get_keyparam(v, KEY_PATH); + struct path * pp; + int r; + +@@ -1303,7 +1303,7 @@ cli_getprstatus (void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + + param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); +@@ -1328,7 +1328,7 @@ cli_setprstatus(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + + param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); +@@ -1351,7 +1351,7 @@ cli_unsetprstatus(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, MAP); ++ char * param = get_keyparam(v, KEY_MAP); + + param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); +@@ -1373,7 +1373,7 @@ cli_getprkey(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char *mapname = get_keyparam(v, MAP); ++ char *mapname = get_keyparam(v, KEY_MAP); + uint64_t key; + + mapname = convert_dev(mapname, 0); +@@ -1405,7 +1405,7 @@ cli_unsetprkey(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char *mapname = get_keyparam(v, MAP); ++ char *mapname = get_keyparam(v, KEY_MAP); + int ret; + struct config *conf; + +@@ -1429,8 +1429,8 @@ cli_setprkey(void * v, char ** reply, int * len, void * data) + { + struct multipath * mpp; + struct vectors * vecs = (struct vectors *)data; +- char *mapname = get_keyparam(v, MAP); +- char *keyparam = get_keyparam(v, KEY); ++ char *mapname = get_keyparam(v, KEY_MAP); ++ char *keyparam = get_keyparam(v, KEY_KEY); + uint64_t prkey; + uint8_t flags; + int ret; +@@ -1459,7 +1459,7 @@ cli_setprkey(void * v, char ** reply, int * len, void * data) + static int cli_set_marginal(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, PATH); ++ char * param = get_keyparam(v, KEY_PATH); + struct path * pp; + + param = convert_dev(param, 1); +@@ -1486,7 +1486,7 @@ static int cli_set_marginal(void * v, char ** reply, int * len, void * data) + static int cli_unset_marginal(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * param = get_keyparam(v, PATH); ++ char * param = get_keyparam(v, KEY_PATH); + struct path * pp; + + param = convert_dev(param, 1); +@@ -1513,7 +1513,7 @@ static int cli_unset_marginal(void * v, char ** reply, int * len, void * data) + static int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data) + { + struct vectors * vecs = (struct vectors *)data; +- char * mapname = get_keyparam(v, MAP); ++ char * mapname = get_keyparam(v, KEY_MAP); + struct multipath *mpp; + struct pathgroup * pgp; + struct path * pp; +-- +2.33.0 \ No newline at end of file diff --git a/multipath-tools.spec b/multipath-tools.spec index 2197fb3..b892121 100644 --- a/multipath-tools.spec +++ b/multipath-tools.spec @@ -1,7 +1,7 @@ #needsrootforbuild Name: multipath-tools Version: 0.8.7 -Release: 5 +Release: 6 Summary: Tools to manage multipath devices with the device-mapper License: GPL-2.0-or-later and LGPL-2.0-only URL: http://christophe.varoqui.free.fr/ @@ -27,6 +27,11 @@ Patch15: 0015-clear-mpp-path-reference-when-path-is-freed-otherwis.patch Patch16: 0016-multipath-return-failure-on-an-invalid-remove-cmd.patch Patch17: 0017-multipath-fix-exit-status-of-multipath-T.patch Patch18: 0018-multipath-tools-use-run-instead-of-dev-shm.patch +Patch19: 0019-multipathd-add-and-set-cli_handlers-in-a-single-step.patch +Patch20: 0020-multipathd-make-all-cli_handlers-static.patch +Patch21: 0021-multipathd-Fix-command-completion-in-interactive-mod.patch +Patch22: 0022-multipathd-more-robust-command-parsing.patch + BuildRequires: multipath-tools, libcmocka, libcmocka-devel BuildRequires: gcc, libaio-devel, userspace-rcu-devel, device-mapper-devel >= 1.02.89 BuildRequires: libselinux-devel, libsepol-devel, readline-devel, ncurses-devel, @@ -173,6 +178,9 @@ fi %changelog +* Mon Oct 31 2022 wuguanghao - 0.8.7-6 +- fix CVE-2022-41974 + * Wed Oct 26 2022 shikemeng - 0.8.7-5 - use /run instead of /dev/shm to fix CVE-2022-41973 -- Gitee From 9975a132344045b92487a2ad654a7f09405dc46b Mon Sep 17 00:00:00 2001 From: wguanghao Date: Mon, 31 Oct 2022 09:05:55 +0000 Subject: [PATCH 2/2] add 0001-multipathd-add-and-set-cli_handlers-in-a-single-step.patch. --- ...nd-set-cli_handlers-in-a-single-step.patch | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 0001-multipathd-add-and-set-cli_handlers-in-a-single-step.patch diff --git a/0001-multipathd-add-and-set-cli_handlers-in-a-single-step.patch b/0001-multipathd-add-and-set-cli_handlers-in-a-single-step.patch new file mode 100644 index 0000000..79d03ee --- /dev/null +++ b/0001-multipathd-add-and-set-cli_handlers-in-a-single-step.patch @@ -0,0 +1,48 @@ +From db77d1b3cdb14ca0e32132ff7ad360e3d48f62ee Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 7 Sep 2021 22:41:46 +0200 +Subject: [PATCH] multipathd: add and set cli_handlers in a single step + +Modify set_handler_callback() such that a missing slot is created +if no matching slot is found. This way, we can skip the initialization +with NULL handlers on startup. Assigning the same handler multiple +times would be a bug which is tested with assert(). + +Reviewed-by: Benjamin Marzinski +--- + multipathd/cli.c | 96 ++++++++---------------------------------------- + multipathd/cli.h | 7 ++-- + 2 files changed, 20 insertions(+), 83 deletions(-) + +diff --git a/multipathd/cli.c b/multipathd/cli.c +index 4d6c37c..ddeb5fc 100644 +--- a/multipathd/cli.c ++++ b/multipathd/cli.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include "memory.h" + #include "vector.h" + #include "structs.h" +@@ -64,26 +65,27 @@ out: + return 1; + } + +-int +-add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *)) ++ ++static struct handler add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *), bool locked) + { + struct handler * h; + + h = alloc_handler(); + +- if (!h) +- return 1; ++ if (h == NULL) ++ return NULL; + + if (!vector_alloc_slot(handlers)) { + FREE(h); \ No newline at end of file -- Gitee