aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sys.c71
1 files changed, 37 insertions, 34 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index c762eebdebf7..bc7d1be0960e 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1273,18 +1273,21 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
1273#endif 1273#endif
1274 1274
1275/* make sure you are allowed to change @tsk limits before calling this */ 1275/* make sure you are allowed to change @tsk limits before calling this */
1276int do_setrlimit(struct task_struct *tsk, unsigned int resource, 1276int do_prlimit(struct task_struct *tsk, unsigned int resource,
1277 struct rlimit *new_rlim) 1277 struct rlimit *new_rlim, struct rlimit *old_rlim)
1278{ 1278{
1279 struct rlimit *old_rlim; 1279 struct rlimit *rlim;
1280 int retval = 0; 1280 int retval = 0;
1281 1281
1282 if (resource >= RLIM_NLIMITS) 1282 if (resource >= RLIM_NLIMITS)
1283 return -EINVAL; 1283 return -EINVAL;
1284 if (new_rlim->rlim_cur > new_rlim->rlim_max) 1284 if (new_rlim) {
1285 return -EINVAL; 1285 if (new_rlim->rlim_cur > new_rlim->rlim_max)
1286 if (resource == RLIMIT_NOFILE && new_rlim->rlim_max > sysctl_nr_open) 1286 return -EINVAL;
1287 return -EPERM; 1287 if (resource == RLIMIT_NOFILE &&
1288 new_rlim->rlim_max > sysctl_nr_open)
1289 return -EPERM;
1290 }
1288 1291
1289 /* protect tsk->signal and tsk->sighand from disappearing */ 1292 /* protect tsk->signal and tsk->sighand from disappearing */
1290 read_lock(&tasklist_lock); 1293 read_lock(&tasklist_lock);
@@ -1293,42 +1296,42 @@ int do_setrlimit(struct task_struct *tsk, unsigned int resource,
1293 goto out; 1296 goto out;
1294 } 1297 }
1295 1298
1296 old_rlim = tsk->signal->rlim + resource; 1299 rlim = tsk->signal->rlim + resource;
1297 task_lock(tsk->group_leader); 1300 task_lock(tsk->group_leader);
1298 if (new_rlim->rlim_max > old_rlim->rlim_max && 1301 if (new_rlim) {
1299 !capable(CAP_SYS_RESOURCE)) 1302 if (new_rlim->rlim_max > rlim->rlim_max &&
1300 retval = -EPERM; 1303 !capable(CAP_SYS_RESOURCE))
1301 if (!retval) 1304 retval = -EPERM;
1302 retval = security_task_setrlimit(tsk->group_leader, resource, 1305 if (!retval)
1303 new_rlim); 1306 retval = security_task_setrlimit(tsk->group_leader,
1304 1307 resource, new_rlim);
1305 if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) { 1308 if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
1306 /* 1309 /*
1307 * The caller is asking for an immediate RLIMIT_CPU 1310 * The caller is asking for an immediate RLIMIT_CPU
1308 * expiry. But we use the zero value to mean "it was 1311 * expiry. But we use the zero value to mean "it was
1309 * never set". So let's cheat and make it one second 1312 * never set". So let's cheat and make it one second
1310 * instead 1313 * instead
1311 */ 1314 */
1312 new_rlim->rlim_cur = 1; 1315 new_rlim->rlim_cur = 1;
1316 }
1317 }
1318 if (!retval) {
1319 if (old_rlim)
1320 *old_rlim = *rlim;
1321 if (new_rlim)
1322 *rlim = *new_rlim;
1313 } 1323 }
1314
1315 if (!retval)
1316 *old_rlim = *new_rlim;
1317 task_unlock(tsk->group_leader); 1324 task_unlock(tsk->group_leader);
1318 1325
1319 if (retval || resource != RLIMIT_CPU)
1320 goto out;
1321
1322 /* 1326 /*
1323 * RLIMIT_CPU handling. Note that the kernel fails to return an error 1327 * RLIMIT_CPU handling. Note that the kernel fails to return an error
1324 * code if it rejected the user's attempt to set RLIMIT_CPU. This is a 1328 * code if it rejected the user's attempt to set RLIMIT_CPU. This is a
1325 * very long-standing error, and fixing it now risks breakage of 1329 * very long-standing error, and fixing it now risks breakage of
1326 * applications, so we live with it 1330 * applications, so we live with it
1327 */ 1331 */
1328 if (new_rlim->rlim_cur == RLIM_INFINITY) 1332 if (!retval && new_rlim && resource == RLIMIT_CPU &&
1329 goto out; 1333 new_rlim->rlim_cur != RLIM_INFINITY)
1330 1334 update_rlimit_cpu(tsk, new_rlim->rlim_cur);
1331 update_rlimit_cpu(tsk, new_rlim->rlim_cur);
1332out: 1335out:
1333 read_unlock(&tasklist_lock); 1336 read_unlock(&tasklist_lock);
1334 return retval; 1337 return retval;
@@ -1340,7 +1343,7 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
1340 1343
1341 if (copy_from_user(&new_rlim, rlim, sizeof(*rlim))) 1344 if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
1342 return -EFAULT; 1345 return -EFAULT;
1343 return do_setrlimit(current, resource, &new_rlim); 1346 return do_prlimit(current, resource, &new_rlim, NULL);
1344} 1347}
1345 1348
1346/* 1349/*