All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anders Johansson <ajohansson@suse.de>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] making /proc/<pid>/limits writable
Date: Wed, 30 Jul 2008 21:57:45 +0200	[thread overview]
Message-ID: <200807302157.46261.ajohansson@suse.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 778 bytes --]

(For any replies, please cc. me, because I'm not subscribed)

Attached is a patch making the limits for a process writable, so it is 
possible to change the limits of a task other than current.

There are many reasons why this is desirable. The core limit is to me the most 
important. If a process hangs, because of some sort of race condition that 
happens once in a blue moon, and ulimit -c is set to 0, it might take forever 
to reproduce. It would be nice to be able to change that limit dynamically, to 
be able to get a core dump.

Other limits should also be settable, but for now I've only done core size.

The patch is against 2.6.27-rc1

btw, in case it isn't painfully obvious: this is my very first kernel patch 
that isn't a simple one-or-two-line bug fix

Anders

[-- Attachment #2: pid_limits.diff --]
[-- Type: text/x-patch, Size: 3600 bytes --]

diff -ur a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	2008-07-30 21:44:44.000000000 +0200
+++ b/fs/proc/base.c	2008-07-30 21:53:07.000000000 +0200
@@ -423,6 +423,76 @@
 
 #endif
 
+static ssize_t pid_limits_write(struct file *file, const char __user *buf,
+				size_t count, loff_t *offs)
+{
+	int ret = 0;
+	struct task_struct *task;
+
+	if (!count)
+		goto out_no_task;
+	char c;
+	char *s = buf, *tmp;
+	char buffer[256];
+	unsigned long softlim, hardlim;
+	char hardlim_set = 0;
+
+	task = get_proc_task(file->f_dentry->d_inode);
+	if (!task) {
+		ret = -ESRCH;
+		goto out_no_task;
+	}
+	if (get_user(c, s)) {
+		ret = -EFAULT;
+		goto out;
+	}
+	s += 2;
+	switch (c) {
+		case 'c': {
+			if (copy_from_user(buffer, s, 255)) {
+				ret = -EFAULT;
+				goto out;
+			}
+			if (strncmp(buffer, "unlimited", 9) == 0)
+				softlim = RLIM_INFINITY;
+			else {
+				softlim = strict_strtoul(buffer, &tmp, 10);
+				if (tmp == buffer) {
+					ret = -EFAULT;
+					goto out;
+				}
+				softlim *= 1024;
+			}
+			if ((tmp - buffer) < count) {
+				s = tmp+1;
+				if (strncmp(s, "unlimited", 9) == 0) {
+					hardlim = RLIM_INFINITY;
+					hardlim_set = 1;
+				} else {
+					hardlim = strict_strtoul(s, &tmp, 10);
+					if (s != tmp) {
+						hardlim *= 1024;
+						hardlim_set = 1;
+					}
+				}
+			}
+			task_lock(task->group_leader);
+			task->signal->rlim[RLIMIT_CORE].rlim_cur = softlim;
+			if (hardlim_set) {
+				if ((hardlim <= task->signal->rlim[RLIMIT_CORE].rlim_max) ||
+					capable(CAP_SYS_ADMIN))
+					task->signal->rlim[RLIMIT_CORE].rlim_max = hardlim;
+			}
+			task_unlock(task->group_leader);
+		}
+	}
+	ret = count;
+out:
+	put_task_struct(task);
+out_no_task:
+	return ret;
+}
+
 /* The badness from the OOM killer */
 unsigned long badness(struct task_struct *p, unsigned long uptime);
 static int proc_oom_score(struct task_struct *task, char *buffer)
@@ -462,19 +532,28 @@
 };
 
 /* Display limits for a process */
-static int proc_pid_limits(struct task_struct *task, char *buffer)
+static int pid_limits_read(struct file *file, char __user *buf,
+				size_t cnt, loff_t *ppos)
 {
 	unsigned int i;
 	int count = 0;
 	unsigned long flags;
-	char *bufptr = buffer;
+	char *bufptr = buf;
+	int ret = -ESRCH;
 
 	struct rlimit rlim[RLIM_NLIMITS];
+	struct task_struct *task;
 
+	if (*ppos > 0)
+		return 0;
+
+	task = get_proc_task(file->f_dentry->d_inode);
+	if (!task)
+		goto out_no_task;
 	rcu_read_lock();
 	if (!lock_task_sighand(task,&flags)) {
 		rcu_read_unlock();
-		return 0;
+		goto out;
 	}
 	memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS);
 	unlock_task_sighand(task, &flags);
@@ -506,8 +585,13 @@
 		else
 			count += sprintf(&bufptr[count], "\n");
 	}
-
-	return count;
+	
+	ret = count;
+	*ppos = count;
+out:
+	put_task_struct(task);
+out_no_task:
+	return ret;
 }
 
 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
@@ -2456,7 +2540,7 @@
 	REG("environ",    S_IRUSR, environ),
 	INF("auxv",       S_IRUSR, pid_auxv),
 	ONE("status",     S_IRUGO, pid_status),
-	INF("limits",	  S_IRUSR, pid_limits),
+	REG("limits",	  S_IRUSR|S_IWUSR, pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
 	REG("sched",      S_IRUGO|S_IWUSR, pid_sched),
 #endif
@@ -2791,7 +2875,7 @@
 	REG("environ",   S_IRUSR, environ),
 	INF("auxv",      S_IRUSR, pid_auxv),
 	ONE("status",    S_IRUGO, pid_status),
-	INF("limits",	 S_IRUSR, pid_limits),
+	REG("limits",	 S_IRUSR|S_IWUSR, pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
 	REG("sched",     S_IRUGO|S_IWUSR, pid_sched),
 #endif
Only in b/fs/proc: base.c.orig
Only in b/fs/proc: base.c.rej
Only in b/fs/proc: .base.c.rej.swp

             reply	other threads:[~2008-07-30 19:58 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-30 19:57 Anders Johansson [this message]
2008-07-30 20:53 ` [PATCH] making /proc/<pid>/limits writable KOSAKI Motohiro
2008-07-30 21:43 ` Jiri Slaby

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=200807302157.46261.ajohansson@suse.de \
    --to=ajohansson@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    /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.