LVS
lvs-devel
Google
 
Web LinuxVirtualServer.org

[PATCH v2 net] ipvs: prevent integer overflow in do_ip_vs_get_ctl()

To: "Gustavo A. R. Silva" <gustavo@xxxxxxxxxxxxxx>
Subject: [PATCH v2 net] ipvs: prevent integer overflow in do_ip_vs_get_ctl()
Cc: Simon Horman <horms@xxxxxxxxxxxx>, Julian Anastasov <ja@xxxxxx>, Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>, Jozsef Kadlecsik <kadlec@xxxxxxxxxxxxx>, "David S. Miller" <davem@xxxxxxxxxxxxx>, Eric Dumazet <edumazet@xxxxxxxxxx>, Jakub Kicinski <kuba@xxxxxxxxxx>, Paolo Abeni <pabeni@xxxxxxxxxx>, netdev@xxxxxxxxxxxxxxx, lvs-devel@xxxxxxxxxxxxxxx, netfilter-devel@xxxxxxxxxxxxxxx, coreteam@xxxxxxxxxxxxx, linux-kernel@xxxxxxxxxxxxxxx, kernel-janitors@xxxxxxxxxxxxxxx
From: Dan Carpenter <dan.carpenter@xxxxxxxxxx>
Date: Mon, 10 Mar 2025 10:45:53 +0300
The get->num_services variable is an unsigned int which is controlled by
the user.  The struct_size() function ensures that the size calculation
does not overflow an unsigned long, however, we are saving the result to
an int so the calculation can overflow.

Both "len" and "get->num_services" come from the user.  This check is
just a sanity check to help the user and ensure they are using the API
correctly.  An integer overflow here is not a big deal.  This has no
security impact.

Save the result from struct_size() type size_t to fix this integer
overflow bug.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx>
---
v2: fix %lu vs %zu in the printk().  It breaks the build on 32bit
    systems.
    Remove the CC stable.

 net/netfilter/ipvs/ip_vs_ctl.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 7d13110ce188..0633276d96bf 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3091,12 +3091,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user 
*user, int *len)
        case IP_VS_SO_GET_SERVICES:
        {
                struct ip_vs_get_services *get;
-               int size;
+               size_t size;
 
                get = (struct ip_vs_get_services *)arg;
                size = struct_size(get, entrytable, get->num_services);
                if (*len != size) {
-                       pr_err("length: %u != %u\n", *len, size);
+                       pr_err("length: %u != %zu\n", *len, size);
                        ret = -EINVAL;
                        goto out;
                }
@@ -3132,12 +3132,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user 
*user, int *len)
        case IP_VS_SO_GET_DESTS:
        {
                struct ip_vs_get_dests *get;
-               int size;
+               size_t size;
 
                get = (struct ip_vs_get_dests *)arg;
                size = struct_size(get, entrytable, get->num_dests);
                if (*len != size) {
-                       pr_err("length: %u != %u\n", *len, size);
+                       pr_err("length: %u != %zu\n", *len, size);
                        ret = -EINVAL;
                        goto out;
                }
-- 
2.47.2



<Prev in Thread] Current Thread [Next in Thread>