Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Jan 2012 20:25:00 +0000 (UTC)
From:      Mikolaj Golub <trociny@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r230470 - in head/sys: kern sys
Message-ID:  <201201222025.q0MKP0Ix091451@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trociny
Date: Sun Jan 22 20:25:00 2012
New Revision: 230470
URL: http://svn.freebsd.org/changeset/base/230470

Log:
  Change kern.proc.rlimit sysctl to:
  
  - retrive only one, specified limit for a process, not the whole
    array, as it was previously (the sysctl has been added recently and
    has not been backported to stable yet, so this change is ok);
  
  - allow to set a resource limit for another process.
  
  Submitted by:	Andrey Zonov <andrey at zonov.org>
  Discussed with:	kib
  Reviewed by:	kib
  MFC after:	2 weeks

Modified:
  head/sys/kern/kern_proc.c
  head/sys/kern/kern_resource.c
  head/sys/sys/resourcevar.h

Modified: head/sys/kern/kern_proc.c
==============================================================================
--- head/sys/kern/kern_proc.c	Sun Jan 22 19:49:43 2012	(r230469)
+++ head/sys/kern/kern_proc.c	Sun Jan 22 20:25:00 2012	(r230470)
@@ -2372,7 +2372,7 @@ sysctl_kern_proc_groups(SYSCTL_HANDLER_A
 }
 
 /*
- * This sysctl allows a process to retrieve the resource limits for
+ * This sysctl allows a process to retrieve or/and set the resource limit for
  * another process.
  */
 static int
@@ -2380,30 +2380,53 @@ sysctl_kern_proc_rlimit(SYSCTL_HANDLER_A
 {
 	int *name = (int *)arg1;
 	u_int namelen = arg2;
-	struct plimit *limp;
+	struct rlimit rlim;
 	struct proc *p;
-	int error = 0;
+	u_int which;
+	int flags, error;
 
-	if (namelen != 1)
+	if (namelen != 2)
+		return (EINVAL);
+
+	which = (u_int)name[1];
+	if (which >= RLIM_NLIMITS)
 		return (EINVAL);
 
-	error = pget((pid_t)name[0], PGET_CANSEE, &p);
+	if (req->newptr != NULL && req->newlen != sizeof(rlim))
+		return (EINVAL);
+
+	flags = PGET_HOLD | PGET_NOTWEXIT;
+	if (req->newptr != NULL)
+		flags |= PGET_CANDEBUG;
+	else
+		flags |= PGET_CANSEE;
+	error = pget((pid_t)name[0], flags, &p);
 	if (error != 0)
 		return (error);
+
 	/*
-	 * Check the request size.  We alow sizes smaller rlimit array for
-	 * backward binary compatibility: the number of resource limits may
-	 * grow.
+	 * Retrieve limit.
 	 */
-	if (sizeof(limp->pl_rlimit) < req->oldlen) {
+	if (req->oldptr != NULL) {
+		PROC_LOCK(p);
+		lim_rlimit(p, which, &rlim);
 		PROC_UNLOCK(p);
-		return (EINVAL);
 	}
+	error = SYSCTL_OUT(req, &rlim, sizeof(rlim));
+	if (error != 0)
+		goto errout;
 
-	limp = lim_hold(p->p_limit);
-	PROC_UNLOCK(p);
-	error = SYSCTL_OUT(req, limp->pl_rlimit, req->oldlen);
-	lim_free(limp);
+	/*
+	 * Set limit.
+	 */
+	if (req->newptr != NULL) {
+		error = SYSCTL_IN(req, &rlim, sizeof(rlim));
+		if (error == 0)
+			error = kern_proc_setrlimit(curthread, p, which, &rlim);
+	}
+
+errout:
+	PRELE(p);
 	return (error);
 }
 
@@ -2544,8 +2567,9 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC
 static SYSCTL_NODE(_kern_proc, KERN_PROC_GROUPS, groups, CTLFLAG_RD |
 	CTLFLAG_MPSAFE, sysctl_kern_proc_groups, "Process groups");
 
-static SYSCTL_NODE(_kern_proc, KERN_PROC_RLIMIT, rlimit, CTLFLAG_RD |
-	CTLFLAG_MPSAFE, sysctl_kern_proc_rlimit, "Process resource limits");
+static SYSCTL_NODE(_kern_proc, KERN_PROC_RLIMIT, rlimit, CTLFLAG_RW |
+	CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_rlimit,
+	"Process resource limits");
 
 static SYSCTL_NODE(_kern_proc, KERN_PROC_PS_STRINGS, ps_strings,
 	CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,

Modified: head/sys/kern/kern_resource.c
==============================================================================
--- head/sys/kern/kern_resource.c	Sun Jan 22 19:49:43 2012	(r230469)
+++ head/sys/kern/kern_resource.c	Sun Jan 22 20:25:00 2012	(r230470)
@@ -649,13 +649,17 @@ lim_cb(void *arg)
 }
 
 int
-kern_setrlimit(td, which, limp)
-	struct thread *td;
-	u_int which;
-	struct rlimit *limp;
+kern_setrlimit(struct thread *td, u_int which, struct rlimit *limp)
+{
+
+	return (kern_proc_setrlimit(td, td->td_proc, which, limp));
+}
+
+int
+kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which,
+    struct rlimit *limp)
 {
 	struct plimit *newlim, *oldlim;
-	struct proc *p;
 	register struct rlimit *alimp;
 	struct rlimit oldssiz;
 	int error;
@@ -672,7 +676,6 @@ kern_setrlimit(td, which, limp)
 		limp->rlim_max = RLIM_INFINITY;
 
 	oldssiz.rlim_cur = 0;
-	p = td->td_proc;
 	newlim = lim_alloc();
 	PROC_LOCK(p);
 	oldlim = p->p_limit;

Modified: head/sys/sys/resourcevar.h
==============================================================================
--- head/sys/sys/resourcevar.h	Sun Jan 22 19:49:43 2012	(r230469)
+++ head/sys/sys/resourcevar.h	Sun Jan 22 20:25:00 2012	(r230470)
@@ -120,6 +120,8 @@ int	 chgsbsize(struct uidinfo *uip, u_in
 	    rlim_t maxval);
 int	 chgptscnt(struct uidinfo *uip, int diff, rlim_t maxval);
 int	 fuswintr(void *base);
+int	 kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which,
+	    struct rlimit *limp);
 struct plimit
 	*lim_alloc(void);
 void	 lim_copy(struct plimit *dst, struct plimit *src);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201222025.q0MKP0Ix091451>