diff -ur a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c 2008-07-30 21:44:44.000000000 +0200 +++ b/fs/proc/base.c 2008-07-30 21:53:07.000000000 +0200 @@ -423,6 +423,76 @@ #endif +static ssize_t pid_limits_write(struct file *file, const char __user *buf, + size_t count, loff_t *offs) +{ + int ret = 0; + struct task_struct *task; + + if (!count) + goto out_no_task; + char c; + char *s = buf, *tmp; + char buffer[256]; + unsigned long softlim, hardlim; + char hardlim_set = 0; + + task = get_proc_task(file->f_dentry->d_inode); + if (!task) { + ret = -ESRCH; + goto out_no_task; + } + if (get_user(c, s)) { + ret = -EFAULT; + goto out; + } + s += 2; + switch (c) { + case 'c': { + if (copy_from_user(buffer, s, 255)) { + ret = -EFAULT; + goto out; + } + if (strncmp(buffer, "unlimited", 9) == 0) + softlim = RLIM_INFINITY; + else { + softlim = strict_strtoul(buffer, &tmp, 10); + if (tmp == buffer) { + ret = -EFAULT; + goto out; + } + softlim *= 1024; + } + if ((tmp - buffer) < count) { + s = tmp+1; + if (strncmp(s, "unlimited", 9) == 0) { + hardlim = RLIM_INFINITY; + hardlim_set = 1; + } else { + hardlim = strict_strtoul(s, &tmp, 10); + if (s != tmp) { + hardlim *= 1024; + hardlim_set = 1; + } + } + } + task_lock(task->group_leader); + task->signal->rlim[RLIMIT_CORE].rlim_cur = softlim; + if (hardlim_set) { + if ((hardlim <= task->signal->rlim[RLIMIT_CORE].rlim_max) || + capable(CAP_SYS_ADMIN)) + task->signal->rlim[RLIMIT_CORE].rlim_max = hardlim; + } + task_unlock(task->group_leader); + } + } + ret = count; +out: + put_task_struct(task); +out_no_task: + return ret; +} + /* The badness from the OOM killer */ unsigned long badness(struct task_struct *p, unsigned long uptime); static int proc_oom_score(struct task_struct *task, char *buffer) @@ -462,19 +532,28 @@ }; /* Display limits for a process */ -static int proc_pid_limits(struct task_struct *task, char *buffer) +static int pid_limits_read(struct file *file, char __user *buf, + size_t cnt, loff_t *ppos) { unsigned int i; int count = 0; unsigned long flags; - char *bufptr = buffer; + char *bufptr = buf; + int ret = -ESRCH; struct rlimit rlim[RLIM_NLIMITS]; + struct task_struct *task; + if (*ppos > 0) + return 0; + + task = get_proc_task(file->f_dentry->d_inode); + if (!task) + goto out_no_task; rcu_read_lock(); if (!lock_task_sighand(task,&flags)) { rcu_read_unlock(); - return 0; + goto out; } memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS); unlock_task_sighand(task, &flags); @@ -506,8 +585,13 @@ else count += sprintf(&bufptr[count], "\n"); } - - return count; + + ret = count; + *ppos = count; +out: + put_task_struct(task); +out_no_task: + return ret; } #ifdef CONFIG_HAVE_ARCH_TRACEHOOK @@ -2456,7 +2540,7 @@ REG("environ", S_IRUSR, environ), INF("auxv", S_IRUSR, pid_auxv), ONE("status", S_IRUGO, pid_status), - INF("limits", S_IRUSR, pid_limits), + REG("limits", S_IRUSR|S_IWUSR, pid_limits), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, pid_sched), #endif @@ -2791,7 +2875,7 @@ REG("environ", S_IRUSR, environ), INF("auxv", S_IRUSR, pid_auxv), ONE("status", S_IRUGO, pid_status), - INF("limits", S_IRUSR, pid_limits), + REG("limits", S_IRUSR|S_IWUSR, pid_limits), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, pid_sched), #endif Only in b/fs/proc: base.c.orig Only in b/fs/proc: base.c.rej Only in b/fs/proc: .base.c.rej.swp