tools: ynl: make sure we always pass yarg to mnl_cb_run
authorJakub Kicinski <kuba@kernel.org>
Tue, 20 Feb 2024 16:11:11 +0000 (08:11 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Mar 2024 12:35:09 +0000 (13:35 +0100)
[ Upstream commit e4fe082c38cd74a8fa384bc7542cf3edf1cb7318 ]

There is one common error handler in ynl - ynl_cb_error().
It expects priv to be a pointer to struct ynl_parse_arg AKA yarg.
To avoid potential crashes if we encounter a stray NLMSG_ERROR
always pass yarg as priv (or a struct which has it as the first
member).

ynl_cb_null() has a similar problem directly - it expects yarg
but priv passed by the caller is ys.

Found by code inspection.

Fixes: 86878f14d71a ("tools: ynl: user space helpers")
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Link: https://lore.kernel.org/r/20240220161112.2735195-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
tools/net/ynl/lib/ynl.c

index 514e0d69e73106a867270eebb41948128a1befe3..0a7fe6a13f7b9618c558b11cc29e31de858a7743 100644 (file)
@@ -450,6 +450,8 @@ ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version)
 
 int ynl_recv_ack(struct ynl_sock *ys, int ret)
 {
+       struct ynl_parse_arg yarg = { .ys = ys, };
+
        if (!ret) {
                yerr(ys, YNL_ERROR_EXPECT_ACK,
                     "Expecting an ACK but nothing received");
@@ -462,7 +464,7 @@ int ynl_recv_ack(struct ynl_sock *ys, int ret)
                return ret;
        }
        return mnl_cb_run(ys->rx_buf, ret, ys->seq, ys->portid,
-                         ynl_cb_null, ys);
+                         ynl_cb_null, &yarg);
 }
 
 int ynl_cb_null(const struct nlmsghdr *nlh, void *data)
@@ -725,11 +727,14 @@ err_free:
 
 static int ynl_ntf_trampoline(const struct nlmsghdr *nlh, void *data)
 {
-       return ynl_ntf_parse((struct ynl_sock *)data, nlh);
+       struct ynl_parse_arg *yarg = data;
+
+       return ynl_ntf_parse(yarg->ys, nlh);
 }
 
 int ynl_ntf_check(struct ynl_sock *ys)
 {
+       struct ynl_parse_arg yarg = { .ys = ys, };
        ssize_t len;
        int err;
 
@@ -751,7 +756,7 @@ int ynl_ntf_check(struct ynl_sock *ys)
                        return len;
 
                err = mnl_cb_run2(ys->rx_buf, len, ys->seq, ys->portid,
-                                 ynl_ntf_trampoline, ys,
+                                 ynl_ntf_trampoline, &yarg,
                                  ynl_cb_array, NLMSG_MIN_TYPE);
                if (err < 0)
                        return err;