The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=3458bbd397783f3bb62713c54ae87f19eeb98dc0

commit 3458bbd397783f3bb62713c54ae87f19eeb98dc0
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2024-09-10 03:57:58 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2024-09-20 06:46:06 +0000

    kernel: add RLIMIT_PIPEBUF
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D46619
---
 sys/kern/kern_resource.c |  7 +++++++
 sys/kern/sys_pipe.c      | 16 ++++++++++++++++
 sys/sys/pipe.h           |  1 +
 sys/sys/resource.h       |  3 ++-
 sys/sys/resourcevar.h    |  2 ++
 5 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 2e9cce727bee..d1a1d3ea3811 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -1607,3 +1607,10 @@ chgumtxcnt(struct uidinfo *uip, int diff, rlim_t max)
 
        return (chglimit(uip, &uip->ui_umtxcnt, diff, max, "umtxcnt"));
 }
+
+int
+chgpipecnt(struct uidinfo *uip, int diff, rlim_t max)
+{
+
+       return (chglimit(uip, &uip->ui_pipecnt, diff, max, "pipecnt"));
+}
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 73b6facec6c7..7ee2b5c76da3 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -375,6 +375,7 @@ pipe_paircreate(struct thread *td, struct pipepair **p_pp)
 #endif
        rpipe = &pp->pp_rpipe;
        wpipe = &pp->pp_wpipe;
+       pp->pp_owner = crhold(td->td_ucred);
 
        knlist_init_mtx(&rpipe->pipe_sel.si_note, PIPE_MTX(rpipe));
        knlist_init_mtx(&wpipe->pipe_sel.si_note, PIPE_MTX(wpipe));
@@ -408,6 +409,7 @@ pipe_paircreate(struct thread *td, struct pipepair **p_pp)
 fail:
        knlist_destroy(&rpipe->pipe_sel.si_note);
        knlist_destroy(&wpipe->pipe_sel.si_note);
+       crfree(pp->pp_owner);
 #ifdef MAC
        mac_pipe_destroy(pp);
 #endif
@@ -574,9 +576,20 @@ retry:
        size = round_page(size);
        buffer = (caddr_t) vm_map_min(pipe_map);
 
+       if (!chgpipecnt(cpipe->pipe_pair->pp_owner->cr_ruidinfo,
+           size, lim_cur(curthread, RLIMIT_PIPEBUF))) {
+               if (cpipe->pipe_buffer.buffer == NULL &&
+                   size > SMALL_PIPE_SIZE) {
+                       size = SMALL_PIPE_SIZE;
+                       goto retry;
+               }
+               return (ENOMEM);
+       }
+
        error = vm_map_find(pipe_map, NULL, 0, (vm_offset_t *)&buffer, size, 0,
            VMFS_ANY_SPACE, VM_PROT_RW, VM_PROT_RW, 0);
        if (error != KERN_SUCCESS) {
+               chgpipecnt(cpipe->pipe_pair->pp_owner->cr_ruidinfo, -size, 0);
                if (cpipe->pipe_buffer.buffer == NULL &&
                    size > SMALL_PIPE_SIZE) {
                        size = SMALL_PIPE_SIZE;
@@ -1645,6 +1658,8 @@ pipe_free_kmem(struct pipe *cpipe)
 
        if (cpipe->pipe_buffer.buffer != NULL) {
                atomic_subtract_long(&amountpipekva, cpipe->pipe_buffer.size);
+               chgpipecnt(cpipe->pipe_pair->pp_owner->cr_uidinfo,
+                   -cpipe->pipe_buffer.size, 0);
                vm_map_remove(pipe_map,
                    (vm_offset_t)cpipe->pipe_buffer.buffer,
                    (vm_offset_t)cpipe->pipe_buffer.buffer + 
cpipe->pipe_buffer.size);
@@ -1731,6 +1746,7 @@ pipeclose(struct pipe *cpipe)
         */
        if (ppipe->pipe_present == PIPE_FINALIZED) {
                PIPE_UNLOCK(cpipe);
+               crfree(cpipe->pipe_pair->pp_owner);
 #ifdef MAC
                mac_pipe_destroy(pp);
 #endif
diff --git a/sys/sys/pipe.h b/sys/sys/pipe.h
index 61fb57480605..0f35316432eb 100644
--- a/sys/sys/pipe.h
+++ b/sys/sys/pipe.h
@@ -136,6 +136,7 @@ struct pipepair {
        struct pipe     pp_wpipe;
        struct mtx      pp_mtx;
        struct label    *pp_label;
+       struct ucred    *pp_owner;      /* to dec pipe usage count */
 };
 
 #define PIPE_MTX(pipe)         (&(pipe)->pipe_pair->pp_mtx)
diff --git a/sys/sys/resource.h b/sys/sys/resource.h
index 8c014210aade..c18e45d50b30 100644
--- a/sys/sys/resource.h
+++ b/sys/sys/resource.h
@@ -114,8 +114,9 @@ struct __wrusage {
 #define        RLIMIT_SWAP     12              /* swap used */
 #define        RLIMIT_KQUEUES  13              /* kqueues allocated */
 #define        RLIMIT_UMTXP    14              /* process-shared umtx */
+#define        RLIMIT_PIPEBUF  15              /* pipes/fifos buffers */
 
-#define        RLIM_NLIMITS    15              /* number of resource limits */
+#define        RLIM_NLIMITS    16              /* number of resource limits */
 
 #define        RLIM_INFINITY   ((rlim_t)(((__uint64_t)1 << 63) - 1))
 #define        RLIM_SAVED_MAX  RLIM_INFINITY
diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h
index c9b8cb3989d6..b15dace8cfa0 100644
--- a/sys/sys/resourcevar.h
+++ b/sys/sys/resourcevar.h
@@ -121,6 +121,7 @@ struct uidinfo {
        long    ui_ptscnt;              /* (b) number of pseudo-terminals */
        long    ui_kqcnt;               /* (b) number of kqueues */
        long    ui_umtxcnt;             /* (b) number of shared umtxs */
+       long    ui_pipecnt;             /* (b) consumption of pipe buffers */
        uid_t   ui_uid;                 /* (a) uid */
        u_int   ui_ref;                 /* (b) reference count */
 #ifdef RACCT
@@ -142,6 +143,7 @@ int  chgsbsize(struct uidinfo *uip, u_int *hiwat, u_int to,
            rlim_t maxval);
 int     chgptscnt(struct uidinfo *uip, int diff, rlim_t maxval);
 int     chgumtxcnt(struct uidinfo *uip, int diff, rlim_t maxval);
+int     chgpipecnt(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

Reply via email to