Page MenuHomeFreeBSD

D46619.id143365.diff
No OneTemporary

D46619.id143365.diff

diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c
--- a/bin/sh/miscbltin.c
+++ b/bin/sh/miscbltin.c
@@ -483,6 +483,9 @@
#endif
#ifdef RLIMIT_UMTXP
{ "umtx shared locks", (char *)0, RLIMIT_UMTXP, 1, 'o' },
+#endif
+#ifdef RLIMIT_PIPEBUF
+ { "pipebuf", (char *)0, RLIMIT_PIPEBUF, 1024, 'y' },
#endif
{ (char *) 0, (char *)0, 0, 0, '\0' }
};
@@ -519,7 +522,7 @@
struct rlimit limit;
what = 'f';
- while ((optc = nextopt("HSatfdsmcnuvlbpwko")) != '\0')
+ while ((optc = nextopt("HSatfdsmcnuvlbpwkoy")) != '\0')
switch (optc) {
case 'H':
how = HARD;
diff --git a/lib/libsys/getrlimit.2 b/lib/libsys/getrlimit.2
--- a/lib/libsys/getrlimit.2
+++ b/lib/libsys/getrlimit.2
@@ -84,6 +84,16 @@
The maximum number of simultaneous processes for this user id.
.It Dv RLIMIT_NPTS
The maximum number of pseudo-terminals this user id is allowed to create.
+.It Dv RLIMIT_PIPEBUF
+The maximum total size of in-kernel buffers for bi-directional pipes/fifos
+that this user id is allowed to consume.
+The buffers for kernel FIFOs created on the first open of a filesystem
+object created by
+.Pq Xr mkfifo 2
+are also charged to the user ID of the process opening it,
+not the FIFO's filesystem owner.
+Despite somewhat unexpected, this is in fact fair, since user of the fifo
+is not necessary its creator.
.It Dv RLIMIT_RSS
When there is memory pressure and swap is available, prioritize eviction of
a process' resident pages beyond this amount (in bytes).
diff --git a/lib/libutil/login.conf.5 b/lib/libutil/login.conf.5
--- a/lib/libutil/login.conf.5
+++ b/lib/libutil/login.conf.5
@@ -204,6 +204,7 @@
.It "pseudoterminals number Maximum number of pseudo-terminals."
.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."
.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
--- a/lib/libutil/login_class.3
+++ b/lib/libutil/login_class.3
@@ -118,6 +118,7 @@
swapuse RLIMIT_SWAP
kqueues RLIMIT_KQUEUES
umtxp RLIMIT_UMTXP
+pipebuf RLIMIT_PIPEBUF
.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
--- a/lib/libutil/login_class.c
+++ b/lib/libutil/login_class.c
@@ -65,6 +65,7 @@
{ "swapuse", login_getcapsize, RLIMIT_SWAP },
{ "kqueues", login_getcapsize, RLIMIT_KQUEUES },
{ "umtxp", login_getcapnum, RLIMIT_UMTXP },
+ { "pipebuf", login_getcapnum, RLIMIT_PIPEBUF },
{ NULL, 0, 0 }
};
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -1607,3 +1607,10 @@
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
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -103,6 +103,7 @@
#include <sys/stat.h>
#include <sys/malloc.h>
#include <sys/poll.h>
+#include <sys/priv.h>
#include <sys/selinfo.h>
#include <sys/signalvar.h>
#include <sys/syscallsubr.h>
@@ -206,6 +207,7 @@
static int piperesizefail;
static int piperesizeallowed = 1;
static long pipe_mindirect = PIPE_MINDIRECT;
+static int pipebuf_reserv = 2;
SYSCTL_LONG(_kern_ipc, OID_AUTO, maxpipekva, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
&maxpipekva, 0, "Pipe KVA limit");
@@ -219,6 +221,9 @@
&piperesizefail, 0, "Pipe resize failures");
SYSCTL_INT(_kern_ipc, OID_AUTO, piperesizeallowed, CTLFLAG_RW,
&piperesizeallowed, 0, "Pipe resizing allowed");
+SYSCTL_INT(_kern_ipc, OID_AUTO, pipebuf_reserv, CTLFLAG_RW,
+ &pipebuf_reserv, 0,
+ "Superuser-reserved percentage of the pipe buffers space");
static void pipeinit(void *dummy __unused);
static void pipeclose(struct pipe *cpipe);
@@ -375,6 +380,7 @@
#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 +414,7 @@
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 +581,34 @@
size = round_page(size);
buffer = (caddr_t) vm_map_min(pipe_map);
- 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 (!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);
+ }
+
+ vm_map_lock(pipe_map);
+ if (priv_check(curthread, PRIV_PIPEBUF) != 0 &&
+ (vm_map_max(pipe_map) - vm_map_min(pipe_map)) *
+ (100 - pipebuf_reserv) / 100 < pipe_map->size + size) {
+ vm_map_unlock(pipe_map);
+ if (cpipe->pipe_buffer.buffer == NULL &&
+ size > SMALL_PIPE_SIZE) {
+ size = SMALL_PIPE_SIZE;
+ pipefragretry++;
+ goto retry;
+ }
+ return (ENOMEM);
+ }
+ error = vm_map_find_locked(pipe_map, NULL, 0, (vm_offset_t *)&buffer,
+ size, 0, VMFS_ANY_SPACE, VM_PROT_RW, VM_PROT_RW, 0);
+ vm_map_unlock(pipe_map);
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 +1677,8 @@
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 +1765,7 @@
*/
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
--- a/sys/sys/pipe.h
+++ b/sys/sys/pipe.h
@@ -136,6 +136,7 @@
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/priv.h b/sys/sys/priv.h
--- a/sys/sys/priv.h
+++ b/sys/sys/priv.h
@@ -426,11 +426,13 @@
*/
#define PRIV_VM86_INTCALL 550 /* Allow invoking vm86 int handlers. */
+#define PRIV_PIPEBUF 560 /* Allow to allocate reserved pipebuf
+ space */
+
/*
* Set of reserved privilege values, which will be allocated to code as
* needed, in order to avoid renumbering later privileges due to insertion.
*/
-#define _PRIV_RESERVED0 560
#define _PRIV_RESERVED1 561
#define _PRIV_RESERVED2 562
#define _PRIV_RESERVED3 563
diff --git a/sys/sys/resource.h b/sys/sys/resource.h
--- a/sys/sys/resource.h
+++ b/sys/sys/resource.h
@@ -114,8 +114,9 @@
#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
--- a/sys/sys/resourcevar.h
+++ b/sys/sys/resourcevar.h
@@ -121,6 +121,7 @@
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 @@
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
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -473,6 +473,8 @@
int vm_map_delete(vm_map_t, vm_offset_t, vm_offset_t);
int vm_map_find(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t,
vm_offset_t, int, vm_prot_t, vm_prot_t, int);
+int vm_map_find_locked(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *,
+ vm_size_t, vm_offset_t, int, vm_prot_t, vm_prot_t, int);
int vm_map_find_min(vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *,
vm_size_t, vm_offset_t, vm_offset_t, int, vm_prot_t, vm_prot_t, int);
int vm_map_find_aligned(vm_map_t map, vm_offset_t *addr, vm_size_t length,
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2117,9 +2117,24 @@
*/
int
vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
- vm_offset_t *addr, /* IN/OUT */
- vm_size_t length, vm_offset_t max_addr, int find_space,
- vm_prot_t prot, vm_prot_t max, int cow)
+ vm_offset_t *addr, /* IN/OUT */
+ vm_size_t length, vm_offset_t max_addr, int find_space,
+ vm_prot_t prot, vm_prot_t max, int cow)
+{
+ int rv;
+
+ vm_map_lock(map);
+ rv = vm_map_find_locked(map, object, offset, addr, length, max_addr,
+ find_space, prot, max, cow);
+ vm_map_unlock(map);
+ return (rv);
+}
+
+int
+vm_map_find_locked(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
+ vm_offset_t *addr, /* IN/OUT */
+ vm_size_t length, vm_offset_t max_addr, int find_space,
+ vm_prot_t prot, vm_prot_t max, int cow)
{
vm_offset_t alignment, curr_min_addr, min_addr;
int gap, pidx, rv, try;
@@ -2127,7 +2142,7 @@
KASSERT((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0 ||
object == NULL,
- ("vm_map_find: non-NULL backing object for stack"));
+ ("non-NULL backing object for stack"));
MPASS((cow & MAP_REMAP) == 0 || (find_space == VMFS_NO_SPACE &&
(cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) == 0));
if (find_space == VMFS_OPTIMAL_SPACE && (object == NULL ||
@@ -2150,7 +2165,6 @@
(map->flags & MAP_ASLR_IGNSTART) != 0)
curr_min_addr = min_addr = vm_map_min(map);
try = 0;
- vm_map_lock(map);
if (cluster) {
curr_min_addr = map->anon_loc;
if (curr_min_addr == 0)
@@ -2235,8 +2249,7 @@
MPASS(try == 1);
goto again;
}
- rv = KERN_NO_SPACE;
- goto done;
+ return (KERN_NO_SPACE);
}
}
@@ -2250,16 +2263,14 @@
try = 0;
goto again;
}
- goto done;
+ return (rv);
}
} else if ((cow & MAP_REMAP) != 0) {
- if (!vm_map_range_valid(map, *addr, *addr + length)) {
- rv = KERN_INVALID_ADDRESS;
- goto done;
- }
+ if (!vm_map_range_valid(map, *addr, *addr + length))
+ return (KERN_INVALID_ADDRESS);
rv = vm_map_delete(map, *addr, *addr + length);
if (rv != KERN_SUCCESS)
- goto done;
+ return (rv);
}
if ((cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP)) != 0) {
rv = vm_map_stack_locked(map, *addr, length, sgrowsiz, prot,
@@ -2277,8 +2288,6 @@
if (update_anon && rv == KERN_SUCCESS && (map->anon_loc == 0 ||
*addr < map->anon_loc))
map->anon_loc = *addr;
-done:
- vm_map_unlock(map);
return (rv);
}
diff --git a/usr.bin/limits/limits.1 b/usr.bin/limits/limits.1
--- a/usr.bin/limits/limits.1
+++ b/usr.bin/limits/limits.1
@@ -32,7 +32,7 @@
.Nm
.Op Fl C Ar class | Fl U Ar user
.Op Fl SHB
-.Op Fl bcdfklmnopstuvw Op Ar val
+.Op Fl bcdfklmnopstuvwy Op Ar val
.Op Fl E
.Oo
.Op Ar name Ns = Ns Ar value ...
@@ -280,6 +280,10 @@
Select or set the
.Va swapuse
resource limit.
+.It Fl y Op Ar val
+Select or set the
+.Va pipebuf
+resource limit.
.El
.Pp
Valid values for
diff --git a/usr.bin/limits/limits.c b/usr.bin/limits/limits.c
--- a/usr.bin/limits/limits.c
+++ b/usr.bin/limits/limits.c
@@ -91,6 +91,7 @@
{ " swapuse%-4s %8s", " kB\n", 1024 },
{ " kqueues%-4s %8s", "\n", 1 },
{ " umtxp%-4s %8s", "\n", 1 },
+ { " pipebuf%-4s %8s", " kB\n", 1024 },
}
},
{ "sh", "unlimited", "", " -H", " -S", "",
@@ -110,6 +111,7 @@
{ "ulimit%s -w %s", ";\n", 1024 },
{ "ulimit%s -k %s", ";\n", 1 },
{ "ulimit%s -o %s", ";\n", 1 },
+ { "ulimit%s -y %s", ";\n", 1024 },
}
},
{ "csh", "unlimited", "", " -h", "", NULL,
@@ -242,6 +244,7 @@
{ "swapuse", login_getcapsize },
{ "kqueues", login_getcapnum },
{ "umtxp", login_getcapnum },
+ { "pipebuf", login_getcapnum },
};
/*
@@ -252,7 +255,7 @@
* to be modified accordingly!
*/
-#define RCS_STRING "tfdscmlunbvpwko"
+#define RCS_STRING "tfdscmlunbvpwkoy"
static rlim_t resource_num(int which, int ch, const char *str);
static void usage(void) __dead2;
@@ -292,7 +295,7 @@
pid = -1;
optarg = NULL;
while ((ch = getopt(argc, argv,
- ":EeC:U:BSHP:ab:c:d:f:l:m:n:s:t:u:v:p:w:k:o:")) != -1) {
+ ":EeC:U:BSHP:ab:c:d:f:l:m:n:s:t:u:v:p:w:k:o:y:")) != -1) {
switch(ch) {
case 'a':
doall = 1;
@@ -623,6 +626,7 @@
case RLIMIT_SBSIZE:
case RLIMIT_VMEM:
case RLIMIT_SWAP:
+ case RLIMIT_PIPEBUF:
errno = 0;
res = 0;
while (*s) {
diff --git a/usr.bin/login/login.conf b/usr.bin/login/login.conf
--- a/usr.bin/login/login.conf
+++ b/usr.bin/login/login.conf
@@ -44,6 +44,7 @@
:pseudoterminals=unlimited:\
:kqueues=unlimited:\
:umtxp=unlimited:\
+ :pipebuf=unlimited:\
:priority=0:\
:ignoretime@:\
:umask=022:\
diff --git a/usr.bin/procstat/procstat_rlimit.c b/usr.bin/procstat/procstat_rlimit.c
--- a/usr.bin/procstat/procstat_rlimit.c
+++ b/usr.bin/procstat/procstat_rlimit.c
@@ -63,6 +63,7 @@
{"swapuse", "B "},
{"kqueues", " "},
{"umtxp", " "},
+ {"pipebuf", "B "},
};
_Static_assert(nitems(rlimit_param) == RLIM_NLIMITS,

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 28, 6:36 AM (4 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26276468
Default Alt Text
D46619.id143365.diff (14 KB)

Event Timeline