Re: [PATCH 2/3] extend get/setrlimit to support setting rlimitsexternal to a process (v4)

From: Neil Horman
Date: Mon Oct 05 2009 - 08:33:56 EST


On Mon, Oct 05, 2009 at 09:57:56AM +0800, Américo Wang wrote:
> On Sun, Oct 04, 2009 at 08:54:05PM -0400, Neil Horman wrote:
> >Add syscall infrastructure for getprlimit/setprlimit
> >
> >This patch adds the definitions for the get/setprlimit syscalls. They are
> >identical to the get/setlimit calls, except that they allow the caller to
> >manipulate limits for processes other than themselves.
> >
> >Signed-off-by: Neil Horman <nhorman@xxxxxxxxxxxxx>
>
> Hello, Neil.
>
> What is your point of adding two new syscalls?
> Why not add them to prctl(2)? :-)
>
See the conversations between Andrew and I over the first two version of this
changeset :). Initially I was opposed to adding syscalls at all, but Andrew
thought that this interface lent itself naturally to syscalls (given that
setrlimit and getrlimit are already syscalls). Since the core work here is
applicable to both syscalls and the proc interface, I figured it didn't hurt to
do both.

Best
Neil

>
> Thanks.
>
> >
> >
> > include/linux/syscalls.h | 4 ++
> > kernel/sys.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 88 insertions(+)
> >
> >diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> >index 80de700..535210a 100644
> >--- a/include/linux/syscalls.h
> >+++ b/include/linux/syscalls.h
> >@@ -584,11 +584,15 @@ asmlinkage long sys_newuname(struct new_utsname __user *name);
> >
> > asmlinkage long sys_getrlimit(unsigned int resource,
> > struct rlimit __user *rlim);
> >+asmlinkage long sys_getprlimit(pid_t pid, unsigned int resource,
> >+ struct rlimit __user *rlim);
> > #if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64))
> > asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim);
> > #endif
> > asmlinkage long sys_setrlimit(unsigned int resource,
> > struct rlimit __user *rlim);
> >+asmlinkage long sys_setprlimit(pid_t pid, unsigned int resource,
> >+ struct rlimit __user *rlim);
> > asmlinkage long sys_getrusage(int who, struct rusage __user *ru);
> > asmlinkage long sys_umask(int mask);
> >
> >diff --git a/kernel/sys.c b/kernel/sys.c
> >index 05bd22a..4fe1140 100644
> >--- a/kernel/sys.c
> >+++ b/kernel/sys.c
> >@@ -1211,6 +1211,50 @@ SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim)
> > }
> > }
> >
> >+SYSCALL_DEFINE3(getprlimit, pid_t, pid, unsigned int, resource,
> >+ struct rlimit __user *, rlim)
> >+{
> >+ unsigned long flags;
> >+ struct task_struct *tsk;
> >+ struct pid *ppid;
> >+ int retval = -EINVAL;
> >+
> >+ ppid = find_get_pid(pid);
> >+ if (!ppid)
> >+ goto out;
> >+
> >+ tsk = get_pid_task(ppid, PIDTYPE_PID);
> >+
> >+ if (!tsk)
> >+ goto out_put_pid;
> >+
> >+ if (resource >= RLIM_NLIMITS)
> >+ goto out_put_all;
> >+
> >+ retval = -EBUSY;
> >+ if (!lock_task_sighand(tsk, &flags))
> >+ goto out_put_all;
> >+
> >+ else {
> >+ struct rlimit val;
> >+
> >+ task_lock(tsk->group_leader);
> >+ val = current->signal->rlim[resource];
> >+ task_unlock(tsk->group_leader);
> >+ retval = copy_to_user(rlim, &val, sizeof(*rlim)) ? -EFAULT : 0;
> >+ }
> >+
> >+ unlock_task_sighand(tsk, &flags);
> >+
> >+out_put_all:
> >+ put_task_struct(tsk);
> >+out_put_pid:
> >+ put_pid(ppid);
> >+out:
> >+ return retval;
> >+}
> >+
> >+
> > #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
> >
> > /*
> >@@ -1301,6 +1345,46 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
> > return do_setrlimit(resource, &new_rlim, current);
> > }
> >
> >+SYSCALL_DEFINE3(setprlimit, pid_t, pid, unsigned int, resource,
> >+ struct rlimit __user *, rlim)
> >+{
> >+ struct task_struct *tsk;
> >+ struct pid *ppid;
> >+ unsigned long flags;
> >+ struct rlimit new_rlim;
> >+ int retval = -EINVAL;
> >+
> >+ ppid = find_get_pid(pid);
> >+ if (!ppid)
> >+ goto out;
> >+
> >+ tsk = get_pid_task(ppid, PIDTYPE_PID);
> >+
> >+ if (!tsk)
> >+ goto out_put_pid;
> >+
> >+ if (resource >= RLIM_NLIMITS)
> >+ goto out_put_all;
> >+
> >+ retval = -EFAULT;
> >+ if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
> >+ goto out_put_all;
> >+
> >+ if (!lock_task_sighand(tsk, &flags))
> >+ goto out_put_all;
> >+
> >+ retval = do_setrlimit(resource, &new_rlim, tsk);
> >+
> >+ unlock_task_sighand(tsk, &flags);
> >+
> >+out_put_all:
> >+ put_task_struct(tsk);
> >+out_put_pid:
> >+ put_pid(ppid);
> >+out:
> >+ return retval;
> >+}
> >+
> > /*
> > * It would make sense to put struct rusage in the task_struct,
> > * except that would make the task_struct be *really big*. After
> >--
> >To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> >the body of a message to majordomo@xxxxxxxxxxxxxxx
> >More majordomo info at http://vger.kernel.org/majordomo-info.html
> >Please read the FAQ at http://www.tux.org/lkml/
>
> --
> Live like a child, think like the god.
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/