From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 25 Jul 2025 23:58:48 -0400 Subject: [PATCH] libmpathpersist: Fix-up reservation_key checking The reservation key checking in do_mpath_persistent_reserve_out() was slightly wrong. It allowed invalid keys for preempting. It now correctly checks the reservation key for the preempt commands. It also was a little overly strict in some places. Formerly, it only allowed registering from any key to the configured key or registering from the configured key to any key (as long as you use the prkeys file). Now it also allows unregistering from any key and registering an unregistered device to any key (as long as you use the prkeys file). Also, clarify the code by replacing prkey with a bool tracking if you are registering or unregistering. Signed-off-by: Benjamin Marzinski --- libmpathpersist/mpath_persist_int.c | 53 +++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c index 76bdbc63..ded1af38 100644 --- a/libmpathpersist/mpath_persist_int.c +++ b/libmpathpersist/mpath_persist_int.c @@ -722,9 +722,9 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd, struct multipath *mpp; char *alias; int ret; - uint64_t prkey; + uint64_t zerokey = 0; struct config *conf; - bool preempting_reservation = false; + bool unregistering, preempting_reservation = false; ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp); if (ret != MPATH_PR_SUCCESS) @@ -744,11 +744,12 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd, if (rq_servact == MPATH_PROUT_REG_IGN_SA) set_ignored_key(mpp, paramp->key); - memcpy(&prkey, paramp->sa_key, 8); - if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey && + unregistering = (memcmp(&zerokey, paramp->sa_key, 8) == 0); + if (mpp->prkey_source == PRKEY_SOURCE_FILE && !unregistering && (rq_servact == MPATH_PROUT_REG_IGN_SA || (rq_servact == MPATH_PROUT_REG_SA && (!get_be64(mpp->reservation_key) || + memcmp(paramp->key, &zerokey, 8) == 0 || memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) { memcpy(&mpp->reservation_key, paramp->sa_key, 8); if (update_prkey_flags(alias, get_be64(mpp->reservation_key), @@ -760,12 +761,42 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd, } } - if (memcmp(paramp->key, &mpp->reservation_key, 8) && - memcmp(paramp->sa_key, &mpp->reservation_key, 8) && - (prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) { - condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key)); - ret = MPATH_PR_SYNTAX_ERROR; - goto out1; + /* + * If you are registering a non-zero key, mpp->reservation_key + * must be set and must equal paramp->sa_key. + * If you're not registering a key, mpp->reservation_key must be + * set, and must equal paramp->key + * If you updated the reservation key above, then you cannot fail + * these checks, since mpp->reservation_key has already been set + * to match paramp->sa_key, and if you are registering a non-zero + * key, then it must be set to a non-zero value. + */ + if ((rq_servact == MPATH_PROUT_REG_IGN_SA || + rq_servact == MPATH_PROUT_REG_SA)) { + if (!unregistering && !get_be64(mpp->reservation_key)) { + condlog(0, "%s: no configured reservation key", alias); + ret = MPATH_PR_SYNTAX_ERROR; + goto out1; + } + if (!unregistering && + memcmp(paramp->sa_key, &mpp->reservation_key, 8)) { + condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, + alias, get_be64(mpp->reservation_key)); + ret = MPATH_PR_SYNTAX_ERROR; + goto out1; + } + } else { + if (!get_be64(mpp->reservation_key)) { + condlog(0, "%s: no configured reservation key", alias); + ret = MPATH_PR_SYNTAX_ERROR; + goto out1; + } + if (memcmp(paramp->key, &mpp->reservation_key, 8)) { + condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, + alias, get_be64(mpp->reservation_key)); + ret = MPATH_PR_SYNTAX_ERROR; + goto out1; + } } switch(rq_servact) @@ -798,7 +829,7 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd, switch (rq_servact) { case MPATH_PROUT_REG_SA: case MPATH_PROUT_REG_IGN_SA: - if (prkey == 0) { + if (unregistering) { update_prflag(alias, 0); update_prkey(alias, 0); } else