Skip site navigation (1)Skip section navigation (2)


index | | raw e-mail

This is a multipart MIME message.

--==_Exmh_1766000677_84540
Content-Type: text/plain; charset=us-ascii

In message <20251217190348.7df7c756@hermann>, FreeBSD User writes:
> On Wed, 17 Dec 2025 14:08:55 +0000
> Bojan Novkovi=C4=87 <bnovkov@FreeBSD.org> wrote:
>
> > The branch main has been updated by bnovkov:
> >=20
> > URL:
> > https://cgit.FreeBSD.org/src/commit/?id=3D1092ec8b337595ed8d52accf41c6904=
> d75b3689d
> >=20
> > commit 1092ec8b337595ed8d52accf41c6904d75b3689d
> > Author:     Bojan Novkovi=C4=87 <bnovkov@FreeBSD.org>
> > AuthorDate: 2025-11-07 13:11:03 +0000
> > Commit:     Bojan Novkovi=C4=87 <bnovkov@FreeBSD.org>
> > CommitDate: 2025-12-17 14:08:31 +0000
> >=20
> >     kern: Introduce RLIMIT_VMM
> >    =20
> >     This change introduces a new per-UID limit for controlling the
> >     number of vmm instances, in anticipation of unprivileged bhyve.
> >     This allows ut to limit the amount of kernel memory allocated
> >     by the vmm driver and prevent potential memory exhaustion attacks.
> >    =20
> >     Differential Revision:  https://reviews.freebsd.org/D53728
> >     Reviewed by:    markj, olce, corvink
> >     MFC after:      3 months
> >     Sponsored by:   The FreeBSD Foundation
> >     Sponsored by:   Klara, Inc.
> > ---
> >  sys/dev/vmm/vmm_dev.c              | 18 +++++++++++++++---
> >  sys/kern/kern_resource.c           | 13 +++++++++++++
> >  sys/sys/resource.h                 |  4 +++-
> >  sys/sys/resourcevar.h              |  2 ++
> >  usr.bin/procstat/procstat_rlimit.c |  1 +
> >  5 files changed, 34 insertions(+), 4 deletions(-)
> >=20
> > diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
> > index d6543bf6534e..3a86a8f966ef 100644
> > --- a/sys/dev/vmm/vmm_dev.c
> > +++ b/sys/dev/vmm/vmm_dev.c
> > @@ -18,6 +18,7 @@
> >  #include <sys/priv.h>
> >  #include <sys/proc.h>
> >  #include <sys/queue.h>
> > +#include <sys/resourcevar.h>
> >  #include <sys/smp.h>
> >  #include <sys/sx.h>
> >  #include <sys/sysctl.h>
> > @@ -96,6 +97,10 @@ u_int vm_maxcpu;
> >  SYSCTL_UINT(_hw_vmm, OID_AUTO, maxcpu, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
> >      &vm_maxcpu, 0, "Maximum number of vCPUs");
> > =20
> > +u_int vm_maxvmms;
> > +SYSCTL_UINT(_hw_vmm, OID_AUTO, maxvmms, CTLFLAG_RWTUN,
> > +    &vm_maxvmms, 0, "Maximum number of VMM instances per user");
> > +
> >  static void devmem_destroy(void *arg);
> >  static int devmem_create_cdev(struct vmmdev_softc *sc, int id, char *dev=
> mem);
> > =20
> > @@ -870,6 +875,7 @@ vmmdev_destroy(struct vmmdev_softc *sc)
> >  	int error __diagused;
> > =20
> >  	KASSERT(sc->cdev =3D=3D NULL, ("%s: cdev not free", __func__));
> > +	KASSERT(sc->ucred !=3D NULL, ("%s: missing ucred", __func__));
> > =20
> >  	/*
> >  	 * Destroy all cdevs:
> > @@ -898,8 +904,8 @@ vmmdev_destroy(struct vmmdev_softc *sc)
> >  	if (sc->vm !=3D NULL)
> >  		vm_destroy(sc->vm);
> > =20
> > -	if (sc->ucred !=3D NULL)
> > -		crfree(sc->ucred);
> > +	chgvmmcnt(sc->ucred->cr_ruidinfo, -1, 0);
> > +	crfree(sc->ucred);
> > =20
> >  	sx_xlock(&vmmdev_mtx);
> >  	SLIST_REMOVE(&head, sc, vmmdev_softc, link);
> > @@ -1021,6 +1027,12 @@ vmmdev_create(const char *name, struct ucred *cred)
> >  		vmmdev_destroy(sc);
> >  		return (error);
> >  	}
> > +	if (!chgvmmcnt(cred->cr_ruidinfo, 1, vm_maxvmms)) {
> > +		sx_xunlock(&vmmdev_mtx);
> > +		destroy_dev(cdev);
> > +		vmmdev_destroy(sc);
> > +		return (ENOMEM);
> > +	}
> >  	sc->cdev =3D cdev;
> >  	sx_xunlock(&vmmdev_mtx);
> >  	return (0);
> > @@ -1172,7 +1184,7 @@ vmm_handler(module_t mod, int what, void *arg)
> >  		}
> >  		if (vm_maxcpu =3D=3D 0)
> >  			vm_maxcpu =3D 1;
> > -
> > +		vm_maxvmms =3D 4 * mp_ncpus;
> >  		error =3D vmm_modinit();
> >  		if (error =3D=3D 0)
> >  			vmm_initialized =3D true;
> > diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
> > index dcd38c6e6fbe..31f89bd41f6d 100644
> > --- a/sys/kern/kern_resource.c
> > +++ b/sys/kern/kern_resource.c
> > @@ -895,6 +895,9 @@ getrlimitusage_one(struct proc *p, u_int which, int
> > flags, rlim_t *res) case RLIMIT_PIPEBUF:
> >  		*res =3D ui->ui_pipecnt;
> >  		break;
> > +	case RLIMIT_VMM:
> > +		*res =3D ui->ui_vmmcnt;
> > +		break;
> >  	default:
> >  		error =3D EINVAL;
> >  		break;
> > @@ -1643,6 +1646,9 @@ uifree(struct uidinfo *uip)
> >  	if (uip->ui_inotifywatchcnt !=3D 0)
> >  		printf("freeing uidinfo: uid =3D %d, inotifywatchcnt =3D %ld\n"
> ,
> >  		    uip->ui_uid, uip->ui_inotifywatchcnt);
> > +	if (uip->ui_vmmcnt !=3D 0)
> > +		printf("freeing vmmcnt: uid =3D %d, vmmcnt =3D %ld\n",
> > +		    uip->ui_uid, uip->ui_vmmcnt);
> >  	free(uip, M_UIDINFO);
> >  }
> > =20
> > @@ -1763,6 +1769,13 @@ chginotifywatchcnt(struct uidinfo *uip, int diff,
> > rlim_t max) "inotifywatchcnt"));
> >  }
> > =20
> > +int
> > +chgvmmcnt(struct uidinfo *uip, int diff, rlim_t max)
> > +{
> > +
> > +	return (chglimit(uip, &uip->ui_vmmcnt, diff, max, "vmmcnt"));
> > +}
> > +
> >  static int
> >  sysctl_kern_proc_rlimit_usage(SYSCTL_HANDLER_ARGS)
> >  {
> > diff --git a/sys/sys/resource.h b/sys/sys/resource.h
> > index 2725aa1ef646..9e0635cdb328 100644
> > --- a/sys/sys/resource.h
> > +++ b/sys/sys/resource.h
> > @@ -115,8 +115,9 @@ struct __wrusage {
> >  #define	RLIMIT_KQUEUES	13		/* kqueues allocated
> > */ #define	RLIMIT_UMTXP	14		/* process-shared
> > umtx */ #define	RLIMIT_PIPEBUF	15		/* pipes/fifos
> > buffers */ +#define	RLIMIT_VMM	16		/* virtual
> > machines */=20
> > -#define	RLIM_NLIMITS	16		/* number of resource
> > limits */ +#define	RLIM_NLIMITS	17		/* number of
> > resource limits */=20
> >  #define	RLIM_INFINITY	((rlim_t)(((__uint64_t)1 << 63) - 1))
> >  #define	RLIM_SAVED_MAX	RLIM_INFINITY
> > @@ -144,6 +145,7 @@ static const char *rlimit_ident[] =3D {
> >  	"kqueues",
> >  	"umtx",
> >  	"pipebuf",
> > +	"vmm",
> >  };
> >  #endif
> > =20
> > diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h
> > index 61411890c85b..d5c4561eec66 100644
> > --- a/sys/sys/resourcevar.h
> > +++ b/sys/sys/resourcevar.h
> > @@ -124,6 +124,7 @@ struct uidinfo {
> >  	long	ui_pipecnt;		/* (b) consumption of pipe
> > buffers */ long	ui_inotifycnt;		/* (b) number of inotify
> > descriptors */ long	ui_inotifywatchcnt;	/* (b) number of
> > inotify watches */
> > +	long	ui_vmmcnt;		/* (b) number of vmm instances
> > */ uid_t	ui_uid;			/* (a) uid */
> >  	u_int	ui_ref;			/* (b) reference count */
> >  #ifdef	RACCT
> > @@ -148,6 +149,7 @@ int	 chgumtxcnt(struct uidinfo *uip, int diff,
> > rlim_t maxval); int	 chgpipecnt(struct uidinfo *uip, int diff, rlim_t
> > max); int	 chginotifycnt(struct uidinfo *uip, int diff, rlim_t maxval);
> >  int	 chginotifywatchcnt(struct uidinfo *uip, int diff, rlim_t maxva
> l);
> > +int	 chgvmmcnt(struct uidinfo *uip, int diff, rlim_t max);
> >  int	 kern_proc_setrlimit(struct thread *td, struct proc *p, u_int
> > which, struct rlimit *limp);
> >  struct plimit
> > diff --git a/usr.bin/procstat/procstat_rlimit.c
> > b/usr.bin/procstat/procstat_rlimit.c index c34550295f05..f3132758e005 100=
> 644
> > --- a/usr.bin/procstat/procstat_rlimit.c
> > +++ b/usr.bin/procstat/procstat_rlimit.c
> > @@ -64,6 +64,7 @@ static struct {
> >  	{"kqueues",          "   "},
> >  	{"umtxp",            "   "},
> >  	{"pipebuf",          "B  "},
> > +	{"virtual-machines", "   "},
> >  };
> > =20
> >  _Static_assert(nitems(rlimit_param) =3D=3D RLIM_NLIMITS,
> >=20
>
> After this commit - probably - my kernel pollutes the console with lots of=
> =20
>
> pid XXXXX (limits), jid 0, uid 0: exited on signal 11 (core dumped)
>
> Especially bind920 (named) is failing immediately, surprisingly the mouse i=
> sn't
> working anymore and so on ... ssgd is also dying on startup - no access
> possible.
>
> Environment: customized kernel (especially commenting out unused driver and
> ZFS/IPFW in-kernel).
>
> Kind regards,
>
> oh
>
> =20
>

I have a local patch that addresses this, at least partially. I don't know 
if there are other places that also need attention in the tree. Nor is this 
anywhere near ready for commit but it should get you going for now.

Maybe someone else can clean it up and commit it.




--==_Exmh_1766000677_84540
Content-Type: application/x-patch ; name="0001-CSES-Finish-VMM-commit.patch"
Content-Description: 0001-CSES-Finish-VMM-commit.patch
Content-Transfer-Encoding: quoted-printable

>From 730eede73b453b775a1ce323e454c2b10db25b62 Mon Sep 17 00:00:00 2001
From: Cy Schubert <cy@FreeBSD.org>
Date: Wed, 17 Dec 2025 09:56:33 -0800
Subject: [PATCH 1/2] CSES: Finish VMM commit

Fixes:	1092ec8b3375
---
 bin/sh/miscbltin.c        |  3 +++
 lib/libutil/login.conf.5  |  1 +
 lib/libutil/login_class.3 |  1 +
 lib/libutil/login_class.c |  1 +
 usr.bin/limits/limits.1   |  3 +++
 usr.bin/limits/limits.c   | 14 +++++++++++---
 6 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c
index bbf0aa5b8bde..60417a09d86c 100644
--- a/bin/sh/miscbltin.c
+++ b/bin/sh/miscbltin.c
@@ -517,6 +517,9 @@ static const struct limits limits[] =3D {
 #endif
 #ifdef RLIMIT_PIPEBUF
 	{ "pipebuf",		(char *)0,	RLIMIT_PIPEBUF, 1024, 'y' },
+#endif
+#ifdef RLIMIT_VMM
+	{ "vmm",		(char *)0,	RLIMIT_VMM, 1024, 'y' },
 #endif
 	{ (char *) 0,		(char *)0,	0,		   0, '\0' }
 };
diff --git a/lib/libutil/login.conf.5 b/lib/libutil/login.conf.5
index 942f3ecd2661..b78e279100e4 100644
--- a/lib/libutil/login.conf.5
+++ b/lib/libutil/login.conf.5
@@ -205,6 +205,7 @@ login environment.
 .It "swapuse	size		Maximum swap space size limit."
 .It "umtxp	number		Maximum number of process-shared pthread locks."
 .It "pipebuf	size		Maximum size of pipe buffers."
+.It "vmm	size		Maximum number of virtual machines."
 .El
 .Pp
 These resource limit entries actually specify both the maximum
diff --git a/lib/libutil/login_class.3 b/lib/libutil/login_class.3
index 46e6a70f8ca8..86fb6507eb67 100644
--- a/lib/libutil/login_class.3
+++ b/lib/libutil/login_class.3
@@ -119,6 +119,7 @@ swapuse          RLIMIT_SWAP
 kqueues          RLIMIT_KQUEUES
 umtxp            RLIMIT_UMTXP
 pipebuf          RLIMIT_PIPEBUF
+vmm              RLIMIT_VMM
 .Ed
 .It LOGIN_SETPRIORITY
 Set the scheduling priority for the current process based on the
diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c
index 9478b4dc98ca..04ee26c45e46 100644
--- a/lib/libutil/login_class.c
+++ b/lib/libutil/login_class.c
@@ -66,6 +66,7 @@ static struct login_res {
     { "kqueues",         login_getcapsize, RLIMIT_KQUEUES },
     { "umtxp",           login_getcapnum,  RLIMIT_UMTXP   },
     { "pipebuf",         login_getcapnum,  RLIMIT_PIPEBUF },
+    { "vmm",             login_getcapnum,  RLIMIT_VMM },
     { NULL,              0,                0              }
 };
 =

diff --git a/usr.bin/limits/limits.1 b/usr.bin/limits/limits.1
index 0e374acd991b..e56fabf508b9 100644
--- a/usr.bin/limits/limits.1
+++ b/usr.bin/limits/limits.1
@@ -284,6 +284,9 @@ resource limit.
 Select or set the
 .Va pipebuf
 resource limit.
+Select or set the
+.Va vmm
+resource limit.
 .El
 .Pp
 Valid values for
diff --git a/usr.bin/limits/limits.c b/usr.bin/limits/limits.c
index c53066b52a9f..c6d3493cddc1 100644
--- a/usr.bin/limits/limits.c
+++ b/usr.bin/limits/limits.c
@@ -92,6 +92,7 @@ static struct {
 	  { "  kqueues%-4s          %8s", "\n",       1    },
 	  { "  umtxp%-4s            %8s", "\n",       1    },
 	  { "  pipebuf%-4s          %8s", " kB\n",    1024 },
+	  { "  vmm%-4s              %8s", " \n",      1    }
       }
     },
     { "sh", "unlimited", "", " -H", " -S", "",
@@ -112,6 +113,7 @@ static struct {
 	  { "ulimit%s -k %s", ";\n",  1    },
 	  { "ulimit%s -o %s", ";\n",  1    },
 	  { "ulimit%s -y %s", ";\n",  1024 },
+	  { "ulimit%s -v %s", ";\n",  1    }
       }
     },
     { "csh", "unlimited", "", " -h", "", NULL,
@@ -131,6 +133,7 @@ static struct {
 	  { "limit%s swapsize %s",        ";\n",  1024 },
 	  { "limit%s kqueues %s",         ";\n",  1    },
 	  { "limit%s umtxp %s",           ";\n",  1    },
+	  { "limit%s vmm %s",             ";\n",  1    }
       }
     },
     { "bash|bash2", "unlimited", "", " -H", " -S", "",
@@ -147,7 +150,8 @@ static struct {
 	  { "ulimit%s -b %s", ";\n",  1    },
 	  { "ulimit%s -v %s", ";\n",  1024 },
 	  { "ulimit%s -p %s", ";\n",  1    },
-	  { "ulimit%s -w %s", ";\n",  1024 }
+	  { "ulimit%s -w %s", ";\n",  1024 },
+	  { "ulimit%s -v %s", ";\n",  1    }
       }
     },
     { "tcsh", "unlimited", "", " -h", "", NULL,
@@ -167,6 +171,7 @@ static struct {
 	  { "limit%s swapsize %s",        ";\n",  1024 },
 	  { "limit%s kqueues %s",         ";\n",  1    },
 	  { "limit%s umtxp %s",           ";\n",  1    },
+	  { "limit%s vmm %s",             ";\n",  1    }
       }
     },
     { "ksh|pdksh", "unlimited", "", " -H", " -S", "",
@@ -183,7 +188,8 @@ static struct {
 	  { "ulimit%s -b %s", ";\n",  1    },
 	  { "ulimit%s -v %s", ";\n",  1024 },
 	  { "ulimit%s -p %s", ";\n",  1    },
-	  { "ulimit%s -w %s", ";\n",  1024 }
+	  { "ulimit%s -w %s", ";\n",  1024 },
+	  { "ulimit%s -v %s", ";\n",  1    }
       }
     },
     { "zsh", "unlimited", "", " -H", " -S", "",
@@ -200,7 +206,8 @@ static struct {
 	  { "ulimit%s -b %s", ";\n",  1    },
 	  { "ulimit%s -v %s", ";\n",  1024 },
 	  { "ulimit%s -p %s", ";\n",  1    },
-	  { "ulimit%s -w %s", ";\n",  1024 }
+	  { "ulimit%s -w %s", ";\n",  1024 },
+	  { "ulimit%s -v %s", ";\n",  1    }
       }
     },
     { "rc|es", "unlimited", "", " -h", "", NULL,
@@ -245,6 +252,7 @@ static struct {
     { "kqueues",	login_getcapnum  },
     { "umtxp",		login_getcapnum  },
     { "pipebuf",	login_getcapnum  },
+    { "vmm",		login_getcapnum  },
 };
 =

 /*
-- =

2.52.0

--==_Exmh_1766000677_84540
Content-Type: text/plain; charset=us-ascii

Cheers,
Cy Schubert <Cy.Schubert@cschubert.com>
FreeBSD UNIX:  <cy@FreeBSD.org>   Web:  https://FreeBSD.org
NTP:           <cy@nwtime.org>    Web:  https://nwtime.org

			e**(i*pi)+1=0

--==_Exmh_1766000677_84540--




help