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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to