PERFORCE change 146140 for review
Ed Schouten
ed at FreeBSD.org
Mon Jul 28 18:11:46 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=146140
Change 146140 by ed at ed_dull on 2008/07/28 18:10:59
Introduce a new resource limit: RLIMIT_NPTS.
We can now place limits on pseudo-terminals. Unfortunately,
OpenSSH doesn't want to play along, but applications like screen
and xterm should behave nicely.
Affected files ...
.. //depot/projects/mpsafetty/bin/sh/miscbltin.c#2 edit
.. //depot/projects/mpsafetty/etc/login.conf#2 edit
.. //depot/projects/mpsafetty/lib/libc/sys/getrlimit.2#2 edit
.. //depot/projects/mpsafetty/lib/libutil/login_class.c#3 edit
.. //depot/projects/mpsafetty/sys/dev/pts/pts.c#8 edit
.. //depot/projects/mpsafetty/sys/dev/pts/pts.h#3 edit
.. //depot/projects/mpsafetty/sys/dev/ptycompat/ptycompat.c#5 edit
.. //depot/projects/mpsafetty/sys/kern/kern_resource.c#2 edit
.. //depot/projects/mpsafetty/sys/sys/resource.h#2 edit
.. //depot/projects/mpsafetty/sys/sys/resourcevar.h#2 edit
Differences ...
==== //depot/projects/mpsafetty/bin/sh/miscbltin.c#2 (text+ko) ====
@@ -342,6 +342,9 @@
#ifdef RLIMIT_SBSIZE
{ "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' },
#endif
+#ifdef RLIMIT_NPTS
+ { "pseudo-terminals", (char *)0, RLIMIT_NPTS, 1, 'p' },
+#endif
{ (char *) 0, (char *)0, 0, 0, '\0' }
};
@@ -358,7 +361,7 @@
struct rlimit limit;
what = 'f';
- while ((optc = nextopt("HSatfdsmcnuvlb")) != '\0')
+ while ((optc = nextopt("HSatfdsmcnuvlbp")) != '\0')
switch (optc) {
case 'H':
how = HARD;
==== //depot/projects/mpsafetty/etc/login.conf#2 (text+ko) ====
@@ -40,6 +40,7 @@
:maxproc=unlimited:\
:sbsize=unlimited:\
:vmemoryuse=unlimited:\
+ :pseudoterminals=unlimited:\
:priority=0:\
:ignoretime@:\
:umask=022:
==== //depot/projects/mpsafetty/lib/libc/sys/getrlimit.2#2 (text+ko) ====
@@ -97,6 +97,8 @@
The maximum size (in bytes) of the stack segment for a process;
this defines how far a program's stack segment may be extended.
Stack extension is performed automatically by the system.
+.It Dv RLIMIT_NPTS
+The maximum number of pseudo-terminals created by this user id.
.El
.Pp
A resource limit is specified as a soft limit and a hard limit.
==== //depot/projects/mpsafetty/lib/libutil/login_class.c#3 (text+ko) ====
@@ -50,18 +50,19 @@
rlim_t (*who)(login_cap_t *, const char *, rlim_t, rlim_t);
int why;
} resources[] = {
- { "cputime", login_getcaptime, RLIMIT_CPU },
- { "filesize", login_getcapsize, RLIMIT_FSIZE },
- { "datasize", login_getcapsize, RLIMIT_DATA },
- { "stacksize", login_getcapsize, RLIMIT_STACK },
- { "memoryuse", login_getcapsize, RLIMIT_RSS },
- { "memorylocked", login_getcapsize, RLIMIT_MEMLOCK },
- { "maxproc", login_getcapnum, RLIMIT_NPROC },
- { "openfiles", login_getcapnum, RLIMIT_NOFILE },
- { "coredumpsize", login_getcapsize, RLIMIT_CORE },
- { "sbsize", login_getcapsize, RLIMIT_SBSIZE },
- { "vmemoryuse", login_getcapsize, RLIMIT_VMEM },
- { NULL, 0, 0 }
+ { "cputime", login_getcaptime, RLIMIT_CPU },
+ { "filesize", login_getcapsize, RLIMIT_FSIZE },
+ { "datasize", login_getcapsize, RLIMIT_DATA },
+ { "stacksize", login_getcapsize, RLIMIT_STACK },
+ { "memoryuse", login_getcapsize, RLIMIT_RSS },
+ { "memorylocked", login_getcapsize, RLIMIT_MEMLOCK },
+ { "maxproc", login_getcapnum, RLIMIT_NPROC },
+ { "openfiles", login_getcapnum, RLIMIT_NOFILE },
+ { "coredumpsize", login_getcapsize, RLIMIT_CORE },
+ { "sbsize", login_getcapsize, RLIMIT_SBSIZE },
+ { "vmemoryuse", login_getcapsize, RLIMIT_VMEM },
+ { "pseudoterminals", login_getcapnum, RLIMIT_NPTS },
+ { NULL, 0, 0 }
};
==== //depot/projects/mpsafetty/sys/dev/pts/pts.c#8 (text+ko) ====
@@ -51,6 +51,7 @@
#include <sys/mutex.h>
#include <sys/poll.h>
#include <sys/proc.h>
+#include <sys/resourcevar.h>
#include <sys/serial.h>
#include <sys/stat.h>
#include <sys/syscall.h>
@@ -89,19 +90,20 @@
*/
struct pts_softc {
int pts_unit; /* (c) Device unit number */
+ unsigned int pts_flags; /* (t) Device flags */
+#define PTS_PKT 0x1 /* Packet mode */
struct cv pts_inwait; /* (t) Blocking write() on master */
struct selinfo pts_inpoll; /* (t) Select queue for write() */
struct cv pts_outwait; /* (t) Blocking read() on master */
struct selinfo pts_outpoll; /* (t) Select queue for read() */
- unsigned int pts_flags; /* (t) Device flags */
-#define PTS_PKT 0x1 /* Packet mode */
-
#ifdef PTS_EXTERNAL
pts_external_free_t *pts_external_free; /* (c) Destructor callback */
void *pts_external_softc; /* (c) Destructor softc */
#endif /* PTS_EXTERNAL */
+
+ struct uidinfo *pts_uidinfo; /* (c) Resource limit */
};
/*
@@ -489,6 +491,9 @@
mtx_unlock(&pts_lock);
}
+ chgptscnt(psc->pts_uidinfo, -1, 0);
+ uifree(psc->pts_uidinfo);
+
#ifdef PTS_EXTERNAL
/* Call shutdown hook */
if (psc->pts_external_free != NULL)
@@ -509,15 +514,25 @@
static int
pts_alloc(int fflags, struct thread *td, struct file *fp)
{
- int unit;
+ int unit, ok;
struct tty *tp;
struct pts_softc *psc;
+ struct proc *p = td->td_proc;
+ struct uidinfo *uid = td->td_ucred->cr_ruidinfo;
+ /* Resource limiting */
+ PROC_LOCK(p);
+ ok = chgptscnt(uid, 1, lim_cur(p, RLIMIT_NPTS));
+ PROC_UNLOCK(p);
+ if (!ok)
+ return (EAGAIN);
+
/* Try to allocate a new pts unit number */
mtx_lock(&pts_lock);
unit = alloc_unrl(pts_pool);
if (unit < 0) {
mtx_unlock(&pts_lock);
+ chgptscnt(uid, -1, 0);
return (EAGAIN);
}
pts_ndevs++;
@@ -529,6 +544,8 @@
cv_init(&psc->pts_outwait, "pts outwait");
psc->pts_unit = unit;
+ psc->pts_uidinfo = uid;
+ uihold(uid);
tp = tty_alloc(&pts_class, psc, NULL);
@@ -541,12 +558,22 @@
}
#ifdef PTS_EXTERNAL
-void
+int
pts_alloc_external(int fflags, struct thread *td, struct file *fp,
pts_external_free_t freefunc, void *softc, const char *name)
{
+ int ok;
struct tty *tp;
struct pts_softc *psc;
+ struct proc *p = td->td_proc;
+ struct uidinfo *uid = td->td_ucred->cr_ruidinfo;
+
+ /* Resource limiting */
+ PROC_LOCK(p);
+ ok = chgptscnt(uid, 1, lim_cur(p, RLIMIT_NPTS));
+ PROC_UNLOCK(p);
+ if (!ok)
+ return (EAGAIN);
/* Allocate TTY and softc */
psc = malloc(sizeof(struct pts_softc), M_PTS, M_WAITOK|M_ZERO);
@@ -556,6 +583,8 @@
psc->pts_unit = -1;
psc->pts_external_free = freefunc;
psc->pts_external_softc = softc;
+ psc->pts_uidinfo = uid;
+ uihold(uid);
tp = tty_alloc(&pts_class, psc, NULL);
@@ -563,6 +592,8 @@
tty_makedev(tp, td->td_ucred, "%s", name);
finit(fp, fflags, DTYPE_PTS, tp, &ptsdev_ops);
+
+ return (0);
}
#endif /* PTS_EXTERNAL */
==== //depot/projects/mpsafetty/sys/dev/pts/pts.h#3 (text+ko) ====
@@ -41,7 +41,7 @@
typedef void pts_external_free_t(void *softc);
-void pts_alloc_external(int, struct thread *, struct file *,
+int pts_alloc_external(int, struct thread *, struct file *,
pts_external_free_t, void *, const char *);
#endif /* _PTS_H_ */
==== //depot/projects/mpsafetty/sys/dev/ptycompat/ptycompat.c#5 (text+ko) ====
@@ -62,7 +62,7 @@
static int
ptydev_fdopen(struct cdev *dev, int fflags, struct thread *td, struct file *fp)
{
- int u;
+ int u, error;
char name[] = "ttyXX";
if (!atomic_cmpset_ptr((uintptr_t *)&dev->si_drv1, 0, 1))
@@ -72,8 +72,13 @@
u = minor2unit(minor(dev));
name[3] = u >> 8;
name[4] = u;
- pts_alloc_external(fflags & (FREAD|FWRITE), td, fp,
+
+ error = pts_alloc_external(fflags & (FREAD|FWRITE), td, fp,
ptydev_free, dev, name);
+ if (error != 0) {
+ destroy_dev_sched(dev);
+ return (error);
+ }
/* Raise a warning when a legacy PTY has been allocated */
if (pty_warningcnt > 0) {
==== //depot/projects/mpsafetty/sys/kern/kern_resource.c#2 (text+ko) ====
@@ -1329,3 +1329,28 @@
*hiwat = to;
return (1);
}
+
+/*
+ * Change the count associated with number of pseudo-terminals
+ * a given user is using. When 'max' is 0, don't enforce a limit
+ */
+int
+chgptscnt(uip, diff, max)
+ struct uidinfo *uip;
+ int diff;
+ rlim_t max;
+{
+
+ /* Don't allow them to exceed max, but allow subtraction. */
+ if (diff > 0 && max != 0) {
+ if (atomic_fetchadd_long(&uip->ui_ptscnt, (long)diff) + diff > max) {
+ atomic_subtract_long(&uip->ui_ptscnt, (long)diff);
+ return (0);
+ }
+ } else {
+ atomic_add_long(&uip->ui_ptscnt, (long)diff);
+ if (uip->ui_ptscnt < 0)
+ printf("negative ptscnt for uid = %d\n", uip->ui_uid);
+ }
+ return (1);
+}
==== //depot/projects/mpsafetty/sys/sys/resource.h#2 (text+ko) ====
@@ -93,8 +93,9 @@
#define RLIMIT_SBSIZE 9 /* maximum size of all socket buffers */
#define RLIMIT_VMEM 10 /* virtual process size (inclusive of mmap) */
#define RLIMIT_AS RLIMIT_VMEM /* standard name for RLIMIT_VMEM */
+#define RLIMIT_NPTS 11 /* pseudo-terminals */
-#define RLIM_NLIMITS 11 /* number of resource limits */
+#define RLIM_NLIMITS 12 /* number of resource limits */
#define RLIM_INFINITY ((rlim_t)(((uint64_t)1 << 63) - 1))
/* XXX Missing: RLIM_SAVED_MAX, RLIM_SAVED_CUR */
==== //depot/projects/mpsafetty/sys/sys/resourcevar.h#2 (text+ko) ====
@@ -91,6 +91,7 @@
LIST_ENTRY(uidinfo) ui_hash; /* (c) hash chain of uidinfos */
long ui_sbsize; /* (b) socket buffer space consumed */
long ui_proccnt; /* (b) number of processes */
+ long ui_ptscnt; /* (a) number of pseudo-terminals */
uid_t ui_uid; /* (a) uid */
u_int ui_ref; /* (b) reference count */
};
@@ -106,6 +107,7 @@
int chgproccnt(struct uidinfo *uip, int diff, rlim_t maxval);
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 fuswintr(void *base);
struct plimit
*lim_alloc(void);
More information about the p4-projects
mailing list