lkml.org 
[lkml]   [2009]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH 1/3] extend get/setrlimit to support setting rlimits external to a process (v7)
        Modify setrlimit syscall to accomodate various usages.

    Split the sys_setrlimit syscall into two parts:
    1) a DEFINE_SYSCALL wrapper that implements the sys_setrlimit function
    2) a core do_setrlimit function that accepts as a parameter a task on which to
    operate on the limits of

    This allows us later to implement sys_setprlimit, which allows us to change the
    limits of any process from userspace

    Signed-off-by: Neil Horman <nhorman@tuxdriver.com


    include/linux/sched.h | 3 +++
    kernel/sys.c | 48 ++++++++++++++++++++++++++++++------------------
    2 files changed, 33 insertions(+), 18 deletions(-)

    diff --git a/include/linux/sched.h b/include/linux/sched.h
    index 7755763..ce95005 100644
    --- a/include/linux/sched.h
    +++ b/include/linux/sched.h
    @@ -672,6 +672,9 @@ struct signal_struct {
    int oom_adj; /* OOM kill score adjustment (bit shift) */
    };

    +extern int do_setrlimit(unsigned int resource, struct rlimit *new_rlim,
    + struct task_struct *tsk);
    +
    /* Context switch must be unlocked if interrupts are to be enabled */
    #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
    # define __ARCH_WANT_UNLOCKED_CTXSW
    diff --git a/kernel/sys.c b/kernel/sys.c
    index 1828f8d..0e210a4 100644
    --- a/kernel/sys.c
    +++ b/kernel/sys.c
    @@ -1238,41 +1238,41 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,

    #endif

    -SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
    +int do_setrlimit(unsigned int resource, struct rlimit *new_rlim,
    + struct task_struct *tsk)
    {
    - struct rlimit new_rlim, *old_rlim;
    int retval;
    + struct rlimit *old_rlim;

    - if (resource >= RLIM_NLIMITS)
    - return -EINVAL;
    - if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
    - return -EFAULT;
    - if (new_rlim.rlim_cur > new_rlim.rlim_max)
    +
    + if (new_rlim->rlim_cur > new_rlim->rlim_max)
    return -EINVAL;
    - old_rlim = current->signal->rlim + resource;
    - if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
    + old_rlim = tsk->signal->rlim + resource;
    +
    + if ((new_rlim->rlim_max > old_rlim->rlim_max) &&
    !capable(CAP_SYS_RESOURCE))
    return -EPERM;
    - if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
    +
    + if (resource == RLIMIT_NOFILE && new_rlim->rlim_max > sysctl_nr_open)
    return -EPERM;

    - retval = security_task_setrlimit(resource, &new_rlim);
    + retval = security_task_setrlimit(resource, new_rlim);
    if (retval)
    return retval;

    - if (resource == RLIMIT_CPU && new_rlim.rlim_cur == 0) {
    + if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
    /*
    * The caller is asking for an immediate RLIMIT_CPU
    * expiry. But we use the zero value to mean "it was
    * never set". So let's cheat and make it one second
    * instead
    */
    - new_rlim.rlim_cur = 1;
    + new_rlim->rlim_cur = 1;
    }

    - task_lock(current->group_leader);
    - *old_rlim = new_rlim;
    - task_unlock(current->group_leader);
    + task_lock(tsk->group_leader);
    + *old_rlim = *new_rlim;
    + task_unlock(tsk->group_leader);

    if (resource != RLIMIT_CPU)
    goto out;
    @@ -1283,14 +1283,26 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
    * very long-standing error, and fixing it now risks breakage of
    * applications, so we live with it
    */
    - if (new_rlim.rlim_cur == RLIM_INFINITY)
    + if (new_rlim->rlim_cur == RLIM_INFINITY)
    goto out;

    - update_rlimit_cpu(new_rlim.rlim_cur);
    + update_rlimit_cpu(new_rlim->rlim_cur);
    out:
    return 0;
    }

    +SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
    +{
    + struct rlimit new_rlim;
    +
    + if (resource >= RLIM_NLIMITS)
    + return -EINVAL;
    + if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
    + return -EFAULT;
    +
    + return do_setrlimit(resource, &new_rlim, current);
    +}
    +
    /*
    * It would make sense to put struct rusage in the task_struct,
    * except that would make the task_struct be *really big*. After

    \
     
     \ /
      Last update: 2009-10-20 02:55    [W:0.036 / U:66.800 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site