aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/ia32/ia32entry.S1
-rw-r--r--arch/x86/include/asm/unistd_32.h3
-rw-r--r--arch/x86/include/asm/unistd_64.h2
-rw-r--r--arch/x86/kernel/syscall_table_32.S1
-rw-r--r--include/asm-generic/unistd.h4
-rw-r--r--include/linux/posix-timers.h2
-rw-r--r--include/linux/resource.h9
-rw-r--r--include/linux/security.h9
-rw-r--r--include/linux/syscalls.h4
-rw-r--r--kernel/compat.c17
-rw-r--r--kernel/posix-cpu-timers.c8
-rw-r--r--kernel/sys.c202
-rw-r--r--security/capability.c3
-rw-r--r--security/security.c5
-rw-r--r--security/selinux/hooks.c12
15 files changed, 207 insertions, 75 deletions
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 17cf65c94804..91dc4bb13032 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -844,4 +844,5 @@ ia32_sys_call_table:
844 .quad compat_sys_recvmmsg 844 .quad compat_sys_recvmmsg
845 .quad sys_fanotify_init 845 .quad sys_fanotify_init
846 .quad sys32_fanotify_mark 846 .quad sys32_fanotify_mark
847 .quad sys_prlimit64
847ia32_syscall_end: 848ia32_syscall_end:
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
index 80b799cd74f7..b766a5e8ba0e 100644
--- a/arch/x86/include/asm/unistd_32.h
+++ b/arch/x86/include/asm/unistd_32.h
@@ -345,10 +345,11 @@
345#define __NR_recvmmsg 337 345#define __NR_recvmmsg 337
346#define __NR_fanotify_init 338 346#define __NR_fanotify_init 338
347#define __NR_fanotify_mark 339 347#define __NR_fanotify_mark 339
348#define __NR_prlimit64 340
348 349
349#ifdef __KERNEL__ 350#ifdef __KERNEL__
350 351
351#define NR_syscalls 340 352#define NR_syscalls 341
352 353
353#define __ARCH_WANT_IPC_PARSE_VERSION 354#define __ARCH_WANT_IPC_PARSE_VERSION
354#define __ARCH_WANT_OLD_READDIR 355#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index 5b7b1d585616..363e9b8a715b 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -667,6 +667,8 @@ __SYSCALL(__NR_recvmmsg, sys_recvmmsg)
667__SYSCALL(__NR_fanotify_init, sys_fanotify_init) 667__SYSCALL(__NR_fanotify_init, sys_fanotify_init)
668#define __NR_fanotify_mark 301 668#define __NR_fanotify_mark 301
669__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) 669__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
670#define __NR_prlimit64 302
671__SYSCALL(__NR_prlimit64, sys_prlimit64)
670 672
671#ifndef __NO_STUBS 673#ifndef __NO_STUBS
672#define __ARCH_WANT_OLD_READDIR 674#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index 07ad5eb7cc5c..4802accb9d8d 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -339,3 +339,4 @@ ENTRY(sys_call_table)
339 .long sys_recvmmsg 339 .long sys_recvmmsg
340 .long sys_fanotify_init 340 .long sys_fanotify_init
341 .long sys_fanotify_mark 341 .long sys_fanotify_mark
342 .long sys_prlimit64
diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h
index c17cebc49952..e1898090f22c 100644
--- a/include/asm-generic/unistd.h
+++ b/include/asm-generic/unistd.h
@@ -640,9 +640,11 @@ __SYSCALL(__NR_recvmmsg, sys_recvmmsg)
640 640
641#define __NR_wait4 260 641#define __NR_wait4 260
642__SYSCALL(__NR_wait4, sys_wait4) 642__SYSCALL(__NR_wait4, sys_wait4)
643#define __NR_prlimit64 261
644__SYSCALL(__NR_prlimit64, sys_prlimit64)
643 645
644#undef __NR_syscalls 646#undef __NR_syscalls
645#define __NR_syscalls 261 647#define __NR_syscalls 262
646 648
647/* 649/*
648 * All syscalls below here should go away really, 650 * All syscalls below here should go away really,
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 4f71bf4e628c..3e23844a6990 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -117,6 +117,6 @@ void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
117 117
118long clock_nanosleep_restart(struct restart_block *restart_block); 118long clock_nanosleep_restart(struct restart_block *restart_block);
119 119
120void update_rlimit_cpu(unsigned long rlim_new); 120void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);
121 121
122#endif 122#endif
diff --git a/include/linux/resource.h b/include/linux/resource.h
index f1e914eefeab..88d36f9145ba 100644
--- a/include/linux/resource.h
+++ b/include/linux/resource.h
@@ -43,6 +43,13 @@ struct rlimit {
43 unsigned long rlim_max; 43 unsigned long rlim_max;
44}; 44};
45 45
46#define RLIM64_INFINITY (~0ULL)
47
48struct rlimit64 {
49 __u64 rlim_cur;
50 __u64 rlim_max;
51};
52
46#define PRIO_MIN (-20) 53#define PRIO_MIN (-20)
47#define PRIO_MAX 20 54#define PRIO_MAX 20
48 55
@@ -73,6 +80,8 @@ struct rlimit {
73struct task_struct; 80struct task_struct;
74 81
75int getrusage(struct task_struct *p, int who, struct rusage __user *ru); 82int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
83int do_prlimit(struct task_struct *tsk, unsigned int resource,
84 struct rlimit *new_rlim, struct rlimit *old_rlim);
76 85
77#endif /* __KERNEL__ */ 86#endif /* __KERNEL__ */
78 87
diff --git a/include/linux/security.h b/include/linux/security.h
index 5bcb395a49d4..a22219afff09 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1499,7 +1499,8 @@ struct security_operations {
1499 int (*task_setnice) (struct task_struct *p, int nice); 1499 int (*task_setnice) (struct task_struct *p, int nice);
1500 int (*task_setioprio) (struct task_struct *p, int ioprio); 1500 int (*task_setioprio) (struct task_struct *p, int ioprio);
1501 int (*task_getioprio) (struct task_struct *p); 1501 int (*task_getioprio) (struct task_struct *p);
1502 int (*task_setrlimit) (unsigned int resource, struct rlimit *new_rlim); 1502 int (*task_setrlimit) (struct task_struct *p, unsigned int resource,
1503 struct rlimit *new_rlim);
1503 int (*task_setscheduler) (struct task_struct *p, int policy, 1504 int (*task_setscheduler) (struct task_struct *p, int policy,
1504 struct sched_param *lp); 1505 struct sched_param *lp);
1505 int (*task_getscheduler) (struct task_struct *p); 1506 int (*task_getscheduler) (struct task_struct *p);
@@ -1749,7 +1750,8 @@ void security_task_getsecid(struct task_struct *p, u32 *secid);
1749int security_task_setnice(struct task_struct *p, int nice); 1750int security_task_setnice(struct task_struct *p, int nice);
1750int security_task_setioprio(struct task_struct *p, int ioprio); 1751int security_task_setioprio(struct task_struct *p, int ioprio);
1751int security_task_getioprio(struct task_struct *p); 1752int security_task_getioprio(struct task_struct *p);
1752int security_task_setrlimit(unsigned int resource, struct rlimit *new_rlim); 1753int security_task_setrlimit(struct task_struct *p, unsigned int resource,
1754 struct rlimit *new_rlim);
1753int security_task_setscheduler(struct task_struct *p, 1755int security_task_setscheduler(struct task_struct *p,
1754 int policy, struct sched_param *lp); 1756 int policy, struct sched_param *lp);
1755int security_task_getscheduler(struct task_struct *p); 1757int security_task_getscheduler(struct task_struct *p);
@@ -2311,7 +2313,8 @@ static inline int security_task_getioprio(struct task_struct *p)
2311 return 0; 2313 return 0;
2312} 2314}
2313 2315
2314static inline int security_task_setrlimit(unsigned int resource, 2316static inline int security_task_setrlimit(struct task_struct *p,
2317 unsigned int resource,
2315 struct rlimit *new_rlim) 2318 struct rlimit *new_rlim)
2316{ 2319{
2317 return 0; 2320 return 0;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 2ab198a1e38d..1b67bd333b5e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -35,6 +35,7 @@ struct oldold_utsname;
35struct old_utsname; 35struct old_utsname;
36struct pollfd; 36struct pollfd;
37struct rlimit; 37struct rlimit;
38struct rlimit64;
38struct rusage; 39struct rusage;
39struct sched_param; 40struct sched_param;
40struct sel_arg_struct; 41struct sel_arg_struct;
@@ -644,6 +645,9 @@ asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *r
644#endif 645#endif
645asmlinkage long sys_setrlimit(unsigned int resource, 646asmlinkage long sys_setrlimit(unsigned int resource,
646 struct rlimit __user *rlim); 647 struct rlimit __user *rlim);
648asmlinkage long sys_prlimit64(pid_t pid, unsigned int resource,
649 const struct rlimit64 __user *new_rlim,
650 struct rlimit64 __user *old_rlim);
647asmlinkage long sys_getrusage(int who, struct rusage __user *ru); 651asmlinkage long sys_getrusage(int who, struct rusage __user *ru);
648asmlinkage long sys_umask(int mask); 652asmlinkage long sys_umask(int mask);
649 653
diff --git a/kernel/compat.c b/kernel/compat.c
index 5adab05a3172..e167efce8423 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -279,11 +279,6 @@ asmlinkage long compat_sys_setrlimit(unsigned int resource,
279 struct compat_rlimit __user *rlim) 279 struct compat_rlimit __user *rlim)
280{ 280{
281 struct rlimit r; 281 struct rlimit r;
282 int ret;
283 mm_segment_t old_fs = get_fs ();
284
285 if (resource >= RLIM_NLIMITS)
286 return -EINVAL;
287 282
288 if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) || 283 if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) ||
289 __get_user(r.rlim_cur, &rlim->rlim_cur) || 284 __get_user(r.rlim_cur, &rlim->rlim_cur) ||
@@ -294,10 +289,7 @@ asmlinkage long compat_sys_setrlimit(unsigned int resource,
294 r.rlim_cur = RLIM_INFINITY; 289 r.rlim_cur = RLIM_INFINITY;
295 if (r.rlim_max == COMPAT_RLIM_INFINITY) 290 if (r.rlim_max == COMPAT_RLIM_INFINITY)
296 r.rlim_max = RLIM_INFINITY; 291 r.rlim_max = RLIM_INFINITY;
297 set_fs(KERNEL_DS); 292 return do_prlimit(current, resource, &r, NULL);
298 ret = sys_setrlimit(resource, (struct rlimit __user *) &r);
299 set_fs(old_fs);
300 return ret;
301} 293}
302 294
303#ifdef COMPAT_RLIM_OLD_INFINITY 295#ifdef COMPAT_RLIM_OLD_INFINITY
@@ -329,16 +321,13 @@ asmlinkage long compat_sys_old_getrlimit(unsigned int resource,
329 321
330#endif 322#endif
331 323
332asmlinkage long compat_sys_getrlimit (unsigned int resource, 324asmlinkage long compat_sys_getrlimit(unsigned int resource,
333 struct compat_rlimit __user *rlim) 325 struct compat_rlimit __user *rlim)
334{ 326{
335 struct rlimit r; 327 struct rlimit r;
336 int ret; 328 int ret;
337 mm_segment_t old_fs = get_fs();
338 329
339 set_fs(KERNEL_DS); 330 ret = do_prlimit(current, resource, NULL, &r);
340 ret = sys_getrlimit(resource, (struct rlimit __user *) &r);
341 set_fs(old_fs);
342 if (!ret) { 331 if (!ret) {
343 if (r.rlim_cur > COMPAT_RLIM_INFINITY) 332 if (r.rlim_cur > COMPAT_RLIM_INFINITY)
344 r.rlim_cur = COMPAT_RLIM_INFINITY; 333 r.rlim_cur = COMPAT_RLIM_INFINITY;
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index f66bdd33a6c6..6842eeba5879 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -16,13 +16,13 @@
16 * siglock protection since other code may update expiration cache as 16 * siglock protection since other code may update expiration cache as
17 * well. 17 * well.
18 */ 18 */
19void update_rlimit_cpu(unsigned long rlim_new) 19void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
20{ 20{
21 cputime_t cputime = secs_to_cputime(rlim_new); 21 cputime_t cputime = secs_to_cputime(rlim_new);
22 22
23 spin_lock_irq(&current->sighand->siglock); 23 spin_lock_irq(&task->sighand->siglock);
24 set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL); 24 set_process_cpu_timer(task, CPUCLOCK_PROF, &cputime, NULL);
25 spin_unlock_irq(&current->sighand->siglock); 25 spin_unlock_irq(&task->sighand->siglock);
26} 26}
27 27
28static int check_clock(const clockid_t which_clock) 28static int check_clock(const clockid_t which_clock)
diff --git a/kernel/sys.c b/kernel/sys.c
index e83ddbbaf89d..e9ad44489828 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1236,15 +1236,14 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
1236 1236
1237SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim) 1237SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim)
1238{ 1238{
1239 if (resource >= RLIM_NLIMITS) 1239 struct rlimit value;
1240 return -EINVAL; 1240 int ret;
1241 else { 1241
1242 struct rlimit value; 1242 ret = do_prlimit(current, resource, NULL, &value);
1243 task_lock(current->group_leader); 1243 if (!ret)
1244 value = current->signal->rlim[resource]; 1244 ret = copy_to_user(rlim, &value, sizeof(*rlim)) ? -EFAULT : 0;
1245 task_unlock(current->group_leader); 1245
1246 return copy_to_user(rlim, &value, sizeof(*rlim)) ? -EFAULT : 0; 1246 return ret;
1247 }
1248} 1247}
1249 1248
1250#ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT 1249#ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
@@ -1272,44 +1271,89 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
1272 1271
1273#endif 1272#endif
1274 1273
1275SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim) 1274static inline bool rlim64_is_infinity(__u64 rlim64)
1276{ 1275{
1277 struct rlimit new_rlim, *old_rlim; 1276#if BITS_PER_LONG < 64
1278 int retval; 1277 return rlim64 >= ULONG_MAX;
1278#else
1279 return rlim64 == RLIM64_INFINITY;
1280#endif
1281}
1282
1283static void rlim_to_rlim64(const struct rlimit *rlim, struct rlimit64 *rlim64)
1284{
1285 if (rlim->rlim_cur == RLIM_INFINITY)
1286 rlim64->rlim_cur = RLIM64_INFINITY;
1287 else
1288 rlim64->rlim_cur = rlim->rlim_cur;
1289 if (rlim->rlim_max == RLIM_INFINITY)
1290 rlim64->rlim_max = RLIM64_INFINITY;
1291 else
1292 rlim64->rlim_max = rlim->rlim_max;
1293}
1294
1295static void rlim64_to_rlim(const struct rlimit64 *rlim64, struct rlimit *rlim)
1296{
1297 if (rlim64_is_infinity(rlim64->rlim_cur))
1298 rlim->rlim_cur = RLIM_INFINITY;
1299 else
1300 rlim->rlim_cur = (unsigned long)rlim64->rlim_cur;
1301 if (rlim64_is_infinity(rlim64->rlim_max))
1302 rlim->rlim_max = RLIM_INFINITY;
1303 else
1304 rlim->rlim_max = (unsigned long)rlim64->rlim_max;
1305}
1306
1307/* make sure you are allowed to change @tsk limits before calling this */
1308int do_prlimit(struct task_struct *tsk, unsigned int resource,
1309 struct rlimit *new_rlim, struct rlimit *old_rlim)
1310{
1311 struct rlimit *rlim;
1312 int retval = 0;
1279 1313
1280 if (resource >= RLIM_NLIMITS) 1314 if (resource >= RLIM_NLIMITS)
1281 return -EINVAL; 1315 return -EINVAL;
1282 if (copy_from_user(&new_rlim, rlim, sizeof(*rlim))) 1316 if (new_rlim) {
1283 return -EFAULT; 1317 if (new_rlim->rlim_cur > new_rlim->rlim_max)
1284 if (new_rlim.rlim_cur > new_rlim.rlim_max) 1318 return -EINVAL;
1285 return -EINVAL; 1319 if (resource == RLIMIT_NOFILE &&
1286 old_rlim = current->signal->rlim + resource; 1320 new_rlim->rlim_max > sysctl_nr_open)
1287 if ((new_rlim.rlim_max > old_rlim->rlim_max) && 1321 return -EPERM;
1288 !capable(CAP_SYS_RESOURCE))
1289 return -EPERM;
1290 if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
1291 return -EPERM;
1292
1293 retval = security_task_setrlimit(resource, &new_rlim);
1294 if (retval)
1295 return retval;
1296
1297 if (resource == RLIMIT_CPU && new_rlim.rlim_cur == 0) {
1298 /*
1299 * The caller is asking for an immediate RLIMIT_CPU
1300 * expiry. But we use the zero value to mean "it was
1301 * never set". So let's cheat and make it one second
1302 * instead
1303 */
1304 new_rlim.rlim_cur = 1;
1305 } 1322 }
1306 1323
1307 task_lock(current->group_leader); 1324 /* protect tsk->signal and tsk->sighand from disappearing */
1308 *old_rlim = new_rlim; 1325 read_lock(&tasklist_lock);
1309 task_unlock(current->group_leader); 1326 if (!tsk->sighand) {
1310 1327 retval = -ESRCH;
1311 if (resource != RLIMIT_CPU)
1312 goto out; 1328 goto out;
1329 }
1330
1331 rlim = tsk->signal->rlim + resource;
1332 task_lock(tsk->group_leader);
1333 if (new_rlim) {
1334 if (new_rlim->rlim_max > rlim->rlim_max &&
1335 !capable(CAP_SYS_RESOURCE))
1336 retval = -EPERM;
1337 if (!retval)
1338 retval = security_task_setrlimit(tsk->group_leader,
1339 resource, new_rlim);
1340 if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
1341 /*
1342 * The caller is asking for an immediate RLIMIT_CPU
1343 * expiry. But we use the zero value to mean "it was
1344 * never set". So let's cheat and make it one second
1345 * instead
1346 */
1347 new_rlim->rlim_cur = 1;
1348 }
1349 }
1350 if (!retval) {
1351 if (old_rlim)
1352 *old_rlim = *rlim;
1353 if (new_rlim)
1354 *rlim = *new_rlim;
1355 }
1356 task_unlock(tsk->group_leader);
1313 1357
1314 /* 1358 /*
1315 * RLIMIT_CPU handling. Note that the kernel fails to return an error 1359 * RLIMIT_CPU handling. Note that the kernel fails to return an error
@@ -1317,14 +1361,84 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
1317 * very long-standing error, and fixing it now risks breakage of 1361 * very long-standing error, and fixing it now risks breakage of
1318 * applications, so we live with it 1362 * applications, so we live with it
1319 */ 1363 */
1320 if (new_rlim.rlim_cur == RLIM_INFINITY) 1364 if (!retval && new_rlim && resource == RLIMIT_CPU &&
1321 goto out; 1365 new_rlim->rlim_cur != RLIM_INFINITY)
1322 1366 update_rlimit_cpu(tsk, new_rlim->rlim_cur);
1323 update_rlimit_cpu(new_rlim.rlim_cur);
1324out: 1367out:
1368 read_unlock(&tasklist_lock);
1369 return retval;
1370}
1371
1372/* rcu lock must be held */
1373static int check_prlimit_permission(struct task_struct *task)
1374{
1375 const struct cred *cred = current_cred(), *tcred;
1376
1377 tcred = __task_cred(task);
1378 if ((cred->uid != tcred->euid ||
1379 cred->uid != tcred->suid ||
1380 cred->uid != tcred->uid ||
1381 cred->gid != tcred->egid ||
1382 cred->gid != tcred->sgid ||
1383 cred->gid != tcred->gid) &&
1384 !capable(CAP_SYS_RESOURCE)) {
1385 return -EPERM;
1386 }
1387
1325 return 0; 1388 return 0;
1326} 1389}
1327 1390
1391SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource,
1392 const struct rlimit64 __user *, new_rlim,
1393 struct rlimit64 __user *, old_rlim)
1394{
1395 struct rlimit64 old64, new64;
1396 struct rlimit old, new;
1397 struct task_struct *tsk;
1398 int ret;
1399
1400 if (new_rlim) {
1401 if (copy_from_user(&new64, new_rlim, sizeof(new64)))
1402 return -EFAULT;
1403 rlim64_to_rlim(&new64, &new);
1404 }
1405
1406 rcu_read_lock();
1407 tsk = pid ? find_task_by_vpid(pid) : current;
1408 if (!tsk) {
1409 rcu_read_unlock();
1410 return -ESRCH;
1411 }
1412 ret = check_prlimit_permission(tsk);
1413 if (ret) {
1414 rcu_read_unlock();
1415 return ret;
1416 }
1417 get_task_struct(tsk);
1418 rcu_read_unlock();
1419
1420 ret = do_prlimit(tsk, resource, new_rlim ? &new : NULL,
1421 old_rlim ? &old : NULL);
1422
1423 if (!ret && old_rlim) {
1424 rlim_to_rlim64(&old, &old64);
1425 if (copy_to_user(old_rlim, &old64, sizeof(old64)))
1426 ret = -EFAULT;
1427 }
1428
1429 put_task_struct(tsk);
1430 return ret;
1431}
1432
1433SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
1434{
1435 struct rlimit new_rlim;
1436
1437 if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
1438 return -EFAULT;
1439 return do_prlimit(current, resource, &new_rlim, NULL);
1440}
1441
1328/* 1442/*
1329 * It would make sense to put struct rusage in the task_struct, 1443 * It would make sense to put struct rusage in the task_struct,
1330 * except that would make the task_struct be *really big*. After 1444 * except that would make the task_struct be *really big*. After
diff --git a/security/capability.c b/security/capability.c
index a0bbf30fb6dc..95a6599a37bb 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -411,7 +411,8 @@ static int cap_task_getioprio(struct task_struct *p)
411 return 0; 411 return 0;
412} 412}
413 413
414static int cap_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) 414static int cap_task_setrlimit(struct task_struct *p, unsigned int resource,
415 struct rlimit *new_rlim)
415{ 416{
416 return 0; 417 return 0;
417} 418}
diff --git a/security/security.c b/security/security.c
index 7461b1bc296c..c53949f17d9e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -780,9 +780,10 @@ int security_task_getioprio(struct task_struct *p)
780 return security_ops->task_getioprio(p); 780 return security_ops->task_getioprio(p);
781} 781}
782 782
783int security_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) 783int security_task_setrlimit(struct task_struct *p, unsigned int resource,
784 struct rlimit *new_rlim)
784{ 785{
785 return security_ops->task_setrlimit(resource, new_rlim); 786 return security_ops->task_setrlimit(p, resource, new_rlim);
786} 787}
787 788
788int security_task_setscheduler(struct task_struct *p, 789int security_task_setscheduler(struct task_struct *p,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9b40f4c0ac70..42043f96e54f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2284,12 +2284,15 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
2284 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, 2284 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2285 PROCESS__RLIMITINH, NULL); 2285 PROCESS__RLIMITINH, NULL);
2286 if (rc) { 2286 if (rc) {
2287 /* protect against do_prlimit() */
2288 task_lock(current);
2287 for (i = 0; i < RLIM_NLIMITS; i++) { 2289 for (i = 0; i < RLIM_NLIMITS; i++) {
2288 rlim = current->signal->rlim + i; 2290 rlim = current->signal->rlim + i;
2289 initrlim = init_task.signal->rlim + i; 2291 initrlim = init_task.signal->rlim + i;
2290 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); 2292 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2291 } 2293 }
2292 update_rlimit_cpu(current->signal->rlim[RLIMIT_CPU].rlim_cur); 2294 task_unlock(current);
2295 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
2293 } 2296 }
2294} 2297}
2295 2298
@@ -3333,16 +3336,17 @@ static int selinux_task_getioprio(struct task_struct *p)
3333 return current_has_perm(p, PROCESS__GETSCHED); 3336 return current_has_perm(p, PROCESS__GETSCHED);
3334} 3337}
3335 3338
3336static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) 3339static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3340 struct rlimit *new_rlim)
3337{ 3341{
3338 struct rlimit *old_rlim = current->signal->rlim + resource; 3342 struct rlimit *old_rlim = p->signal->rlim + resource;
3339 3343
3340 /* Control the ability to change the hard limit (whether 3344 /* Control the ability to change the hard limit (whether
3341 lowering or raising it), so that the hard limit can 3345 lowering or raising it), so that the hard limit can
3342 later be used as a safe reset point for the soft limit 3346 later be used as a safe reset point for the soft limit
3343 upon context transitions. See selinux_bprm_committing_creds. */ 3347 upon context transitions. See selinux_bprm_committing_creds. */
3344 if (old_rlim->rlim_max != new_rlim->rlim_max) 3348 if (old_rlim->rlim_max != new_rlim->rlim_max)
3345 return current_has_perm(current, PROCESS__SETRLIMIT); 3349 return current_has_perm(p, PROCESS__SETRLIMIT);
3346 3350
3347 return 0; 3351 return 0;
3348} 3352}