The branch stable/12 has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=3f22f161b936b6279a68d6e9439b30f2abb50cad

commit 3f22f161b936b6279a68d6e9439b30f2abb50cad
Author:     Mark Johnston <[email protected]>
AuthorDate: 2021-11-29 18:50:30 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2021-12-06 14:18:24 +0000

    dummynet: Fix socket option length validation for IP_DUMMYNET3
    
    The socket option handler tries to ensure that the option length is no
    larger than some reasonable maximum, and no smaller than sizeof(struct
    dn_id).  But the loaded option length is stored in an int, which is
    converted to an unsigned integer for the comparison with a size_t, so
    negative values are not caught and instead get passed to malloc().
    
    Change the code to use a size_t for the buffer size.
    
    Reviewed by:    kp
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 1c732c85911eb9e39071cbdb50dfb1f0d76de40f)
---
 sys/netpfil/ipfw/ip_dn_private.h |  2 +-
 sys/netpfil/ipfw/ip_dummynet.c   | 16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/sys/netpfil/ipfw/ip_dn_private.h b/sys/netpfil/ipfw/ip_dn_private.h
index d33e0823f204..6a140e6b8a89 100644
--- a/sys/netpfil/ipfw/ip_dn_private.h
+++ b/sys/netpfil/ipfw/ip_dn_private.h
@@ -423,7 +423,7 @@ int dn_compat_copy_queue(struct copy_args *a, void *_o);
 int dn_compat_copy_pipe(struct copy_args *a, void *_o);
 int copy_data_helper_compat(void *_o, void *_arg);
 int dn_compat_calc_size(void);
-int do_config(void *p, int l);
+int do_config(void *p, size_t l);
 
 /* function to drain idle object */
 void dn_drain_scheduler(void);
diff --git a/sys/netpfil/ipfw/ip_dummynet.c b/sys/netpfil/ipfw/ip_dummynet.c
index 57dbcb3c9a35..a637d4bbd317 100644
--- a/sys/netpfil/ipfw/ip_dummynet.c
+++ b/sys/netpfil/ipfw/ip_dummynet.c
@@ -1992,7 +1992,7 @@ dummynet_flush(void)
  *   processed on a config_sched.
  */
 int
-do_config(void *p, int l)
+do_config(void *p, size_t l)
 {
        struct dn_id o;
        union {
@@ -2016,7 +2016,7 @@ do_config(void *p, int l)
        while (l >= sizeof(o)) {
                memcpy(&o, (char *)p + off, sizeof(o));
                if (o.len < sizeof(o) || l < o.len) {
-                       D("bad len o.len %d len %d", o.len, l);
+                       D("bad len o.len %d len %zu", o.len, l);
                        err = EINVAL;
                        break;
                }
@@ -2488,7 +2488,8 @@ ip_dn_ctl(struct sockopt *sopt)
 {
        struct epoch_tracker et;
        void *p = NULL;
-       int error, l;
+       size_t l;
+       int error;
 
        error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET);
        if (error)
@@ -2517,14 +2518,14 @@ ip_dn_ctl(struct sockopt *sopt)
                error = ip_dummynet_compat(sopt);
                break;
 
-       case IP_DUMMYNET3 :
+       case IP_DUMMYNET3:
                if (sopt->sopt_dir == SOPT_GET) {
                        error = dummynet_get(sopt, NULL);
                        break;
                }
                l = sopt->sopt_valsize;
                if (l < sizeof(struct dn_id) || l > 12000) {
-                       D("argument len %d invalid", l);
+                       D("argument len %zu invalid", l);
                        break;
                }
                p = malloc(l, M_TEMP, M_NOWAIT);
@@ -2533,9 +2534,8 @@ ip_dn_ctl(struct sockopt *sopt)
                        break;
                }
                error = sooptcopyin(sopt, p, l, l);
-               if (error)
-                       break ;
-               error = do_config(p, l);
+               if (error == 0)
+                       error = do_config(p, l);
                break;
        }
 

Reply via email to