aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2009-08-26 17:45:34 -0400
committerJiri Slaby <jirislaby@gmail.com>2010-07-16 03:48:46 -0400
commit7855c35da7ba16b389d17710401c4a55a3ea2102 (patch)
treec8092ed1fee23f044f9ac622a7263591901b6b35
parenteb2d55a32b9a91bca0dea299eedb560bafa8b14e (diff)
rlimits: split sys_setrlimit
Create do_setrlimit from sys_setrlimit and declare do_setrlimit in the resource header. This is the first phase to have generic do_prlimit which allows to be called from read, write and compat rlimits code. The new do_setrlimit also accepts a task pointer to change the limits of. Currently, it cannot be other than current, but this will change with locking later. Also pass tsk->group_leader to security_task_setrlimit to check whether current is allowed to change rlimits of the process and not its arbitrary thread because it makes more sense given that rlimit are per process and not per-thread. Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-rw-r--r--include/linux/resource.h2
-rw-r--r--kernel/sys.c40
2 files changed, 26 insertions, 16 deletions
diff --git a/include/linux/resource.h b/include/linux/resource.h
index f1e914eefeab..cf8dc96653ee 100644
--- a/include/linux/resource.h
+++ b/include/linux/resource.h
@@ -73,6 +73,8 @@ struct rlimit {
73struct task_struct; 73struct task_struct;
74 74
75int getrusage(struct task_struct *p, int who, struct rusage __user *ru); 75int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
76int do_setrlimit(struct task_struct *tsk, unsigned int resource,
77 struct rlimit *new_rlim);
76 78
77#endif /* __KERNEL__ */ 79#endif /* __KERNEL__ */
78 80
diff --git a/kernel/sys.c b/kernel/sys.c
index f2b2d7aa3818..b5b96e30e0d6 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1272,42 +1272,41 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
1272 1272
1273#endif 1273#endif
1274 1274
1275SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim) 1275int do_setrlimit(struct task_struct *tsk, unsigned int resource,
1276 struct rlimit *new_rlim)
1276{ 1277{
1277 struct rlimit new_rlim, *old_rlim; 1278 struct rlimit *old_rlim;
1278 int retval; 1279 int retval;
1279 1280
1280 if (resource >= RLIM_NLIMITS) 1281 if (resource >= RLIM_NLIMITS)
1281 return -EINVAL; 1282 return -EINVAL;
1282 if (copy_from_user(&new_rlim, rlim, sizeof(*rlim))) 1283 if (new_rlim->rlim_cur > new_rlim->rlim_max)
1283 return -EFAULT;
1284 if (new_rlim.rlim_cur > new_rlim.rlim_max)
1285 return -EINVAL; 1284 return -EINVAL;
1286 if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open) 1285 if (resource == RLIMIT_NOFILE && new_rlim->rlim_max > sysctl_nr_open)
1287 return -EPERM; 1286 return -EPERM;
1288 1287
1289 retval = security_task_setrlimit(current, resource, &new_rlim); 1288 retval = security_task_setrlimit(tsk->group_leader, resource, new_rlim);
1290 if (retval) 1289 if (retval)
1291 return retval; 1290 return retval;
1292 1291
1293 if (resource == RLIMIT_CPU && new_rlim.rlim_cur == 0) { 1292 if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
1294 /* 1293 /*
1295 * The caller is asking for an immediate RLIMIT_CPU 1294 * The caller is asking for an immediate RLIMIT_CPU
1296 * expiry. But we use the zero value to mean "it was 1295 * expiry. But we use the zero value to mean "it was
1297 * never set". So let's cheat and make it one second 1296 * never set". So let's cheat and make it one second
1298 * instead 1297 * instead
1299 */ 1298 */
1300 new_rlim.rlim_cur = 1; 1299 new_rlim->rlim_cur = 1;
1301 } 1300 }
1302 1301
1303 old_rlim = current->signal->rlim + resource; 1302 old_rlim = tsk->signal->rlim + resource;
1304 task_lock(current->group_leader); 1303 task_lock(tsk->group_leader);
1305 if (new_rlim.rlim_max > old_rlim->rlim_max && 1304 if (new_rlim->rlim_max > old_rlim->rlim_max &&
1306 !capable(CAP_SYS_RESOURCE)) 1305 !capable(CAP_SYS_RESOURCE))
1307 retval = -EPERM; 1306 retval = -EPERM;
1308 else 1307 else
1309 *old_rlim = new_rlim; 1308 *old_rlim = *new_rlim;
1310 task_unlock(current->group_leader); 1309 task_unlock(tsk->group_leader);
1311 1310
1312 if (retval || resource != RLIMIT_CPU) 1311 if (retval || resource != RLIMIT_CPU)
1313 goto out; 1312 goto out;
@@ -1318,14 +1317,23 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
1318 * very long-standing error, and fixing it now risks breakage of 1317 * very long-standing error, and fixing it now risks breakage of
1319 * applications, so we live with it 1318 * applications, so we live with it
1320 */ 1319 */
1321 if (new_rlim.rlim_cur == RLIM_INFINITY) 1320 if (new_rlim->rlim_cur == RLIM_INFINITY)
1322 goto out; 1321 goto out;
1323 1322
1324 update_rlimit_cpu(current, new_rlim.rlim_cur); 1323 update_rlimit_cpu(tsk, new_rlim->rlim_cur);
1325out: 1324out:
1326 return retval; 1325 return retval;
1327} 1326}
1328 1327
1328SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
1329{
1330 struct rlimit new_rlim;
1331
1332 if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
1333 return -EFAULT;
1334 return do_setrlimit(current, resource, &new_rlim);
1335}
1336
1329/* 1337/*
1330 * It would make sense to put struct rusage in the task_struct, 1338 * It would make sense to put struct rusage in the task_struct,
1331 * except that would make the task_struct be *really big*. After 1339 * except that would make the task_struct be *really big*. After