aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 7ff6d1b10cec..196c7134bee6 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1432,25 +1432,26 @@ out:
1432} 1432}
1433 1433
1434/* rcu lock must be held */ 1434/* rcu lock must be held */
1435static int check_prlimit_permission(struct task_struct *task) 1435static int check_prlimit_permission(struct task_struct *task,
1436 unsigned int flags)
1436{ 1437{
1437 const struct cred *cred = current_cred(), *tcred; 1438 const struct cred *cred = current_cred(), *tcred;
1439 bool id_match;
1438 1440
1439 if (current == task) 1441 if (current == task)
1440 return 0; 1442 return 0;
1441 1443
1442 tcred = __task_cred(task); 1444 tcred = __task_cred(task);
1443 if (uid_eq(cred->uid, tcred->euid) && 1445 id_match = (uid_eq(cred->uid, tcred->euid) &&
1444 uid_eq(cred->uid, tcred->suid) && 1446 uid_eq(cred->uid, tcred->suid) &&
1445 uid_eq(cred->uid, tcred->uid) && 1447 uid_eq(cred->uid, tcred->uid) &&
1446 gid_eq(cred->gid, tcred->egid) && 1448 gid_eq(cred->gid, tcred->egid) &&
1447 gid_eq(cred->gid, tcred->sgid) && 1449 gid_eq(cred->gid, tcred->sgid) &&
1448 gid_eq(cred->gid, tcred->gid)) 1450 gid_eq(cred->gid, tcred->gid));
1449 return 0; 1451 if (!id_match && !ns_capable(tcred->user_ns, CAP_SYS_RESOURCE))
1450 if (ns_capable(tcred->user_ns, CAP_SYS_RESOURCE)) 1452 return -EPERM;
1451 return 0;
1452 1453
1453 return -EPERM; 1454 return security_task_prlimit(cred, tcred, flags);
1454} 1455}
1455 1456
1456SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource, 1457SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource,
@@ -1460,12 +1461,17 @@ SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource,
1460 struct rlimit64 old64, new64; 1461 struct rlimit64 old64, new64;
1461 struct rlimit old, new; 1462 struct rlimit old, new;
1462 struct task_struct *tsk; 1463 struct task_struct *tsk;
1464 unsigned int checkflags = 0;
1463 int ret; 1465 int ret;
1464 1466
1467 if (old_rlim)
1468 checkflags |= LSM_PRLIMIT_READ;
1469
1465 if (new_rlim) { 1470 if (new_rlim) {
1466 if (copy_from_user(&new64, new_rlim, sizeof(new64))) 1471 if (copy_from_user(&new64, new_rlim, sizeof(new64)))
1467 return -EFAULT; 1472 return -EFAULT;
1468 rlim64_to_rlim(&new64, &new); 1473 rlim64_to_rlim(&new64, &new);
1474 checkflags |= LSM_PRLIMIT_WRITE;
1469 } 1475 }
1470 1476
1471 rcu_read_lock(); 1477 rcu_read_lock();
@@ -1474,7 +1480,7 @@ SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource,
1474 rcu_read_unlock(); 1480 rcu_read_unlock();
1475 return -ESRCH; 1481 return -ESRCH;
1476 } 1482 }
1477 ret = check_prlimit_permission(tsk); 1483 ret = check_prlimit_permission(tsk, checkflags);
1478 if (ret) { 1484 if (ret) {
1479 rcu_read_unlock(); 1485 rcu_read_unlock();
1480 return ret; 1486 return ret;