Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137921074
D46619.id143365.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D46619.id143365.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D46619: RLIMIT_PIPE
Attached
Detach File
Event Timeline
Log In to Comment