From: Wieland Gmeiner <e8607062@student.tuwien.ac.at>
To: linux-kernel <linux-kernel@vger.kernel.org>
Cc: Elliot Lee <sopwith@redhat.com>
Subject: Re: [PATCH 2.6.13 1/2] New Syscall: get/set rlimits of any process (udate)
Date: Wed, 31 Aug 2005 14:51:06 +0200 [thread overview]
Message-ID: <1125492666.5810.8.camel@w2> (raw)
In-Reply-To: <1125492405.5810.5.camel@w2>
The patch for the getprlimit() syscall:
Signed-off-by: Wieland Gmeiner <e8607062@student.tuwien.ac.at>
---
arch/i386/kernel/syscall_table.S | 1
include/asm-i386/unistd.h | 3 -
include/linux/security.h | 25 ++++++-----
kernel/sys.c | 85 +++++++++++++++++++++++++++++++++------
security/dummy.c | 5 +-
security/selinux/hooks.c | 17 +++++--
6 files changed, 107 insertions(+), 29 deletions(-)
diff -puN arch/i386/kernel/syscall_table.S~getprlimit arch/i386/kernel/syscall_table.S
--- linux-2.6.13/arch/i386/kernel/syscall_table.S~getprlimit 2005-08-31 02:09:48.000000000 +0200
+++ linux-2.6.13-wieland/arch/i386/kernel/syscall_table.S 2005-08-31 02:29:57.000000000 +0200
@@ -294,3 +294,4 @@ ENTRY(sys_call_table)
.long sys_inotify_init
.long sys_inotify_add_watch
.long sys_inotify_rm_watch
+ .long sys_getprlimit
diff -puN include/asm-i386/unistd.h~getprlimit include/asm-i386/unistd.h
--- linux-2.6.13/include/asm-i386/unistd.h~getprlimit 2005-08-31 02:09:48.000000000 +0200
+++ linux-2.6.13-wieland/include/asm-i386/unistd.h 2005-08-31 02:30:43.000000000 +0200
@@ -299,8 +299,9 @@
#define __NR_inotify_init 291
#define __NR_inotify_add_watch 292
#define __NR_inotify_rm_watch 293
+#define __NR_getprlimit 294
-#define NR_syscalls 294
+#define NR_syscalls 295
/*
* user-visible error numbers are in the range -1 - -128: see
diff -puN include/linux/security.h~getprlimit include/linux/security.h
--- linux-2.6.13/include/linux/security.h~getprlimit 2005-08-31 02:09:48.000000000 +0200
+++ linux-2.6.13-wieland/include/linux/security.h 2005-08-31 02:37:52.000000000 +0200
@@ -584,10 +584,12 @@ struct swap_info_struct;
* @p contains the task_struct of process.
* @nice contains the new nice value.
* Return 0 if permission is granted.
- * @task_setrlimit:
- * Check permission before setting the resource limits of the current
- * process for @resource to @new_rlim. The old resource limit values can
- * be examined by dereferencing (current->signal->rlim + resource).
+ * @task_rlimit:
+ * Check permission before reading the resource limits of the process @p
+ * for @resource or setting the limits to @new_rlim. The old resource
+ * limit values can be examined by dereferencing
+ * (p->signal->rlim + resource).
+ * @p contains the task_struct for the process.
* @resource contains the resource whose limit is being set.
* @new_rlim contains the new limits for @resource.
* Return 0 if permission is granted.
@@ -1156,7 +1158,8 @@ struct security_operations {
int (*task_getsid) (struct task_struct * p);
int (*task_setgroups) (struct group_info *group_info);
int (*task_setnice) (struct task_struct * p, int nice);
- int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim);
+ int (*task_rlimit) (struct task_struct * p, unsigned int resource,
+ struct rlimit * new_rlim);
int (*task_setscheduler) (struct task_struct * p, int policy,
struct sched_param * lp);
int (*task_getscheduler) (struct task_struct * p);
@@ -1798,10 +1801,11 @@ static inline int security_task_setnice
return security_ops->task_setnice (p, nice);
}
-static inline int security_task_setrlimit (unsigned int resource,
- struct rlimit *new_rlim)
+static inline int security_task_rlimit (struct task_struct *p,
+ unsigned int resource,
+ struct rlimit *new_rlim)
{
- return security_ops->task_setrlimit (resource, new_rlim);
+ return security_ops->task_rlimit (p, resource, new_rlim);
}
static inline int security_task_setscheduler (struct task_struct *p,
@@ -2447,8 +2451,9 @@ static inline int security_task_setnice
return 0;
}
-static inline int security_task_setrlimit (unsigned int resource,
- struct rlimit *new_rlim)
+static inline int security_task_rlimit (struct task_struct *p,
+ unsigned int resource,
+ struct rlimit *new_rlim)
{
return 0;
}
diff -puN kernel/sys.c~getprlimit kernel/sys.c
--- linux-2.6.13/kernel/sys.c~getprlimit 2005-08-31 02:09:48.000000000 +0200
+++ linux-2.6.13-wieland/kernel/sys.c 2005-08-31 02:42:12.000000000 +0200
@@ -1524,17 +1524,80 @@ asmlinkage long sys_setdomainname(char _
return errno;
}
-asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit __user *rlim)
+/*
+ * get/setprlimit()
+ *
+ * As ptrace implies the ability to execute arbitrary code in the given
+ * process, which means that the calling process could obtain and set
+ * rlimits for that process without getprlimit/setprlimit anyways,
+ * we use the same permission checks as ptrace.
+ */
+static inline int prlim_check_perm(task_t *task)
{
- if (resource >= RLIM_NLIMITS)
- return -EINVAL;
- else {
- struct rlimit value;
- task_lock(current->group_leader);
- value = current->signal->rlim[resource];
- task_unlock(current->group_leader);
- return copy_to_user(rlim, &value, sizeof(*rlim)) ? -EFAULT : 0;
+ return ((current->uid == task->euid) &&
+ (current->uid == task->suid) &&
+ (current->uid == task->uid) &&
+ (current->gid == task->egid) &&
+ (current->gid == task->sgid) &&
+ (current->gid == task->gid)) || capable(CAP_SYS_PTRACE);
+}
+
+static inline long rlim_do_getprlimit(pid_t pid, unsigned int resource,
+ struct rlimit __user *rlim)
+{
+ struct rlimit value;
+ task_t *p;
+ int retval = -EINVAL;
+
+ if (resource >= RLIM_NLIMITS)
+ goto out;
+
+ if (pid < 0)
+ goto out;
+
+ retval = -ESRCH;
+ read_lock(&tasklist_lock);
+ if (!pid) {
+ p = current;
+ } else {
+ p = find_task_by_pid(pid);
}
+ if (p) {
+ retval = -EPERM;
+ if (pid && !prlim_check_perm(p))
+ goto unlock_out;
+ if (pid) {
+ retval = security_task_rlimit(p, resource, 0);
+ if (retval)
+ goto unlock_out;
+ }
+ task_lock(p->group_leader);
+ value = p->signal->rlim[resource];
+ task_unlock(p->group_leader);
+ } else
+ goto unlock_out;
+
+ read_unlock(&tasklist_lock);
+
+ retval = copy_to_user(rlim, &value, sizeof(*rlim)) ? -EFAULT : 0;
+
+out:
+ return retval;
+
+unlock_out:
+ read_unlock(&tasklist_lock);
+ return retval;
+}
+
+asmlinkage long sys_getprlimit(pid_t pid, unsigned int resource,
+ struct rlimit __user *rlim)
+{
+ return rlim_do_getprlimit(pid, resource, rlim);
+}
+
+asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit __user *rlim)
+{
+ return rlim_do_getprlimit(0, resource, rlim);
}
#ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
@@ -1542,7 +1605,7 @@ asmlinkage long sys_getrlimit(unsigned i
/*
* Back compatibility for getrlimit. Needed for some apps.
*/
-
+
asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim)
{
struct rlimit x;
@@ -1579,7 +1642,7 @@ asmlinkage long sys_setrlimit(unsigned i
if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > NR_OPEN)
return -EPERM;
- retval = security_task_setrlimit(resource, &new_rlim);
+ retval = security_task_rlimit(0, resource, &new_rlim);
if (retval)
return retval;
diff -puN security/dummy.c~getprlimit security/dummy.c
--- linux-2.6.13/security/dummy.c~getprlimit 2005-08-31 02:09:48.000000000 +0200
+++ linux-2.6.13-wieland/security/dummy.c 2005-08-31 02:44:06.000000000 +0200
@@ -543,7 +543,8 @@ static int dummy_task_setnice (struct ta
return 0;
}
-static int dummy_task_setrlimit (unsigned int resource, struct rlimit *new_rlim)
+static int dummy_task_rlimit (struct task_struct *p, unsigned int resource,
+ struct rlimit *new_rlim)
{
return 0;
}
@@ -936,7 +937,7 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, task_getsid);
set_to_dummy_if_null(ops, task_setgroups);
set_to_dummy_if_null(ops, task_setnice);
- set_to_dummy_if_null(ops, task_setrlimit);
+ set_to_dummy_if_null(ops, task_rlimit);
set_to_dummy_if_null(ops, task_setscheduler);
set_to_dummy_if_null(ops, task_getscheduler);
set_to_dummy_if_null(ops, task_wait);
diff -puN security/selinux/hooks.c~getprlimit security/selinux/hooks.c
--- linux-2.6.13/security/selinux/hooks.c~getprlimit 2005-08-31 02:09:48.000000000 +0200
+++ linux-2.6.13-wieland/security/selinux/hooks.c 2005-08-31 02:47:10.000000000 +0200
@@ -2703,20 +2703,27 @@ static int selinux_task_setnice(struct t
return task_has_perm(current,p, PROCESS__SETSCHED);
}
-static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
+static int selinux_task_rlimit(struct task_struct *p,
+ unsigned int resource,
+ struct rlimit *new_rlim)
{
- struct rlimit *old_rlim = current->signal->rlim + resource;
+ struct rlimit *old_rlim = p->signal->rlim + resource;
int rc;
- rc = secondary_ops->task_setrlimit(resource, new_rlim);
+ if (!new_rlim)
+ rc = secondary_ops->task_rlimit(p, resource, 0);
+ else
+ rc = secondary_ops->task_rlimit(0, resource, new_rlim);
if (rc)
return rc;
+ if (!new_rlim)
+ return task_has_perm(current, p, PROCESS__PTRACE);
/* Control the ability to change the hard limit (whether
lowering or raising it), so that the hard limit can
later be used as a safe reset point for the soft limit
upon context transitions. See selinux_bprm_apply_creds. */
- if (old_rlim->rlim_max != new_rlim->rlim_max)
+ else if (p == current && old_rlim->rlim_max != new_rlim->rlim_max)
return task_has_perm(current, current, PROCESS__SETRLIMIT);
return 0;
@@ -4349,7 +4356,7 @@ static struct security_operations selinu
.task_getsid = selinux_task_getsid,
.task_setgroups = selinux_task_setgroups,
.task_setnice = selinux_task_setnice,
- .task_setrlimit = selinux_task_setrlimit,
+ .task_rlimit = selinux_task_rlimit,
.task_setscheduler = selinux_task_setscheduler,
.task_getscheduler = selinux_task_getscheduler,
.task_kill = selinux_task_kill,
_
next prev parent reply other threads:[~2005-08-31 12:51 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-08-26 3:34 [PATCH 2.6.13-rc7 1/2] New Syscall: get rlimits of any process (reworked) Wieland Gmeiner
2005-08-26 3:39 ` [PATCH 2.6.13-rc7 2/2] New Syscall: set " Wieland Gmeiner
2005-08-26 15:34 ` Alan Cox
2005-08-28 21:39 ` Wieland Gmeiner
2005-08-31 12:46 ` [PATCH 2.6.13 0/2] New Syscall: get/set rlimits of any process (udate) Wieland Gmeiner
2005-08-31 12:51 ` Wieland Gmeiner [this message]
2005-08-31 12:52 ` [PATCH 2.6.13 2/2] " Wieland Gmeiner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1125492666.5810.8.camel@w2 \
--to=e8607062@student.tuwien.ac.at \
--cc=linux-kernel@vger.kernel.org \
--cc=sopwith@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.