lkml.org 
[lkml]   [2010]   [May]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 03/11] rlimits: make sure ->rlim_max never grows in sys_setrlimit
    Date
    From: Oleg Nesterov <oleg@redhat.com>

    Mostly preparation for Jiri's changes, but probably makes sense anyway.

    sys_setrlimit() checks new_rlim.rlim_max <= old_rlim->rlim_max, but when
    it takes task_lock() old_rlim->rlim_max can be already lowered. Move this
    check under task_lock().

    Currently this is not important, we can only race with our sub-thread,
    this means the application is stupid. But when we change the code to allow
    the update of !current task's limits, it becomes important to make sure
    ->rlim_max can be lowered "reliably" even if we race with the application
    doing sys_setrlimit().

    Signed-off-by: Oleg Nesterov <oleg@redhat.com>
    Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
    ---
    kernel/sys.c | 15 ++++++++-------
    1 files changed, 8 insertions(+), 7 deletions(-)
    diff --git a/kernel/sys.c b/kernel/sys.c
    index f5183b0..d527c46 100644
    --- a/kernel/sys.c
    +++ b/kernel/sys.c
    @@ -1283,10 +1283,6 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
    return -EFAULT;
    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) &&
    - !capable(CAP_SYS_RESOURCE))
    - return -EPERM;
    if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
    return -EPERM;

    @@ -1304,11 +1300,16 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
    new_rlim.rlim_cur = 1;
    }

    + old_rlim = current->signal->rlim + resource;
    task_lock(current->group_leader);
    - *old_rlim = new_rlim;
    + if ((new_rlim.rlim_max <= old_rlim->rlim_max) ||
    + capable(CAP_SYS_RESOURCE))
    + *old_rlim = new_rlim;
    + else
    + retval = -EPERM;
    task_unlock(current->group_leader);

    - if (resource != RLIMIT_CPU)
    + if (retval || resource != RLIMIT_CPU)
    goto out;

    /*
    @@ -1322,7 +1323,7 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)

    update_rlimit_cpu(current, new_rlim.rlim_cur);
    out:
    - return 0;
    + return retval;
    }

    /*
    --
    1.7.1



    \
     
     \ /
      Last update: 2010-05-12 10:35    [W:0.387 / U:0.812 seconds]
    ©2003-2014 Jasper Spaans. Advertise on this site