From 8e75daf5abec2e008b7d2e21876bc60cf0f95ece Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 27 Nov 2009 15:25:03 +0100 Subject: FS: proc, switch limits reading to fops Use fops instead of proc_info_read. We will need fops for limits writing and the code would look ugly if we used NOD("limits", S_IFREG|S_IRUSR|S_IWUSR, NULL, &proc_pid_limits_operations, { .proc_read = proc_pid_limits }), We will just use REG("limits", S_IRUSR|S_IWUSR, proc_pid_limits_operations), Signed-off-by: Jiri Slaby --- fs/proc/base.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index 18d5cc62d8ed..9814ba18add1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -477,19 +477,30 @@ static const struct limit_names lnames[RLIM_NLIMITS] = { }; /* Display limits for a process */ -static int proc_pid_limits(struct task_struct *task, char *buffer) +static ssize_t limits_read(struct file *file, char __user *buf, size_t rcount, + loff_t *ppos) { - unsigned int i; - int count = 0; - unsigned long flags; - char *bufptr = buffer; - struct rlimit rlim[RLIM_NLIMITS]; + struct task_struct *task; + unsigned long flags; + unsigned int i; + ssize_t count = 0; + char *bufptr; - if (!lock_task_sighand(task, &flags)) + task = get_proc_task(file->f_path.dentry->d_inode); + if (!task) + return -ESRCH; + if (!lock_task_sighand(task, &flags)) { + put_task_struct(task); return 0; + } memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS); unlock_task_sighand(task, &flags); + put_task_struct(task); + + bufptr = (char *)__get_free_page(GFP_TEMPORARY); + if (!bufptr) + return -ENOMEM; /* * print the file header @@ -518,9 +529,17 @@ static int proc_pid_limits(struct task_struct *task, char *buffer) count += sprintf(&bufptr[count], "\n"); } + count = simple_read_from_buffer(buf, rcount, ppos, bufptr, count); + + free_page((unsigned long)bufptr); + return count; } +static const struct file_operations proc_pid_limits_operations = { + .read = limits_read, +}; + #ifdef CONFIG_HAVE_ARCH_TRACEHOOK static int proc_pid_syscall(struct task_struct *task, char *buffer) { @@ -2566,7 +2585,7 @@ static const struct pid_entry tgid_base_stuff[] = { INF("auxv", S_IRUSR, proc_pid_auxv), ONE("status", S_IRUGO, proc_pid_status), ONE("personality", S_IRUSR, proc_pid_personality), - INF("limits", S_IRUSR, proc_pid_limits), + REG("limits", S_IRUSR, proc_pid_limits_operations), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif @@ -2901,7 +2920,7 @@ static const struct pid_entry tid_base_stuff[] = { INF("auxv", S_IRUSR, proc_pid_auxv), ONE("status", S_IRUGO, proc_pid_status), ONE("personality", S_IRUSR, proc_pid_personality), - INF("limits", S_IRUSR, proc_pid_limits), + REG("limits", S_IRUSR, proc_pid_limits_operations), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif -- cgit v1.2.3 From db3d91905e245c7495df8991a9c054b6d4e0dc98 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 26 Aug 2009 21:24:30 +0200 Subject: FS: proc, make limits writable Allow writing strings such as Max core file size=0:unlimited to /proc//limits to change limits. Signed-off-by: Jiri Slaby --- fs/proc/base.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index 9814ba18add1..8fbcc84c268f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -536,8 +536,72 @@ static ssize_t limits_read(struct file *file, char __user *buf, size_t rcount, return count; } +static ssize_t limits_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); + char str[32 + 1 + 16 + 1 + 16 + 1], *delim, *next; + struct rlimit new_rlimit; + unsigned int i; + int ret; + + if (!task) { + count = -ESRCH; + goto out; + } + if (copy_from_user(str, buf, min(count, sizeof(str) - 1))) { + count = -EFAULT; + goto put_task; + } + + str[min(count, sizeof(str) - 1)] = 0; + + delim = strchr(str, '='); + if (!delim) { + count = -EINVAL; + goto put_task; + } + *delim++ = 0; /* for easy 'str' usage */ + new_rlimit.rlim_cur = simple_strtoul(delim, &next, 0); + if (*next != ':') { + if (strncmp(delim, "unlimited:", 10)) { + count = -EINVAL; + goto put_task; + } + new_rlimit.rlim_cur = RLIM_INFINITY; + next = delim + 9; /* move to ':' */ + } + delim = next + 1; + new_rlimit.rlim_max = simple_strtoul(delim, &next, 0); + if (*next != 0) { + if (strcmp(delim, "unlimited")) { + count = -EINVAL; + goto put_task; + } + new_rlimit.rlim_max = RLIM_INFINITY; + } + + for (i = 0; i < RLIM_NLIMITS; i++) + if (!strcmp(str, lnames[i].name)) + break; + if (i >= RLIM_NLIMITS) { + count = -EINVAL; + goto put_task; + } + + ret = do_setrlimit(task, i, &new_rlimit); + if (ret) + count = ret; + +put_task: + put_task_struct(task); +out: + return count; +} + static const struct file_operations proc_pid_limits_operations = { .read = limits_read, + .write = limits_write, }; #ifdef CONFIG_HAVE_ARCH_TRACEHOOK @@ -2585,7 +2649,7 @@ static const struct pid_entry tgid_base_stuff[] = { INF("auxv", S_IRUSR, proc_pid_auxv), ONE("status", S_IRUGO, proc_pid_status), ONE("personality", S_IRUSR, proc_pid_personality), - REG("limits", S_IRUSR, proc_pid_limits_operations), + REG("limits", S_IRUSR|S_IWUSR, proc_pid_limits_operations), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif @@ -2920,7 +2984,7 @@ static const struct pid_entry tid_base_stuff[] = { INF("auxv", S_IRUSR, proc_pid_auxv), ONE("status", S_IRUGO, proc_pid_status), ONE("personality", S_IRUSR, proc_pid_personality), - REG("limits", S_IRUSR, proc_pid_limits_operations), + REG("limits", S_IRUSR|S_IWUSR, proc_pid_limits_operations), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif -- cgit v1.2.3