From: Daniel Reichelt <debian@nachtgeist.net>
To: linux-kernel@vger.kernel.org
Subject: procfs: boot- and runtime configurable access mode for /proc/<pid> dirs
Date: Thu, 24 Mar 2011 05:09:44 +0100 [thread overview]
Message-ID: <4D8AC408.9000503@nachtgeist.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 661 bytes --]
Hi all,
the attached patch enhances the procfs code to allow for modification of
/proc/<pid> dir access modes. It does so
- by hard-wiring (.config) a boot-time default mode (555, 550 or 500)
- which can be overriden by a boot parameter piddir_mode
- and also introduces an inode /proc/piddirs (644) which enables
runtime-configuration (already existing pid-dirs will be updated on next
access)
I started this quite a while back [1] and it worked fine ever since on
my servers. Now I finally enhanced that code by run-time configurability.
Let me know what you think and please CC me on replying.
Thanks,
Daniel
[1] http://lkml.org/lkml/2007/11/20/136
[-- Attachment #2: configurable-piddir-modes-2.6.38.patch --]
[-- Type: text/x-patch, Size: 9049 bytes --]
Index: linux-2.6.38/fs/proc/piddirs.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.38/fs/proc/piddirs.c 2011-03-24 04:53:33.596331008 +0100
@@ -0,0 +1,87 @@
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pid_namespace.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/seqlock.h>
+#include <linux/time.h>
+#include "internal.h"
+
+/* prototypes */
+static int __init param_piddir_mode(char *buf);
+static int __init proc_piddirs_init(void);
+static int piddirs_proc_open(struct inode *inode, struct file *file);
+static int piddirs_proc_show(struct seq_file *m, void *v);
+static ssize_t piddirs_proc_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos);
+
+/* variables */
+static const struct file_operations piddirs_proc_fops = {
+ .open = piddirs_proc_open,
+ .read = seq_read,
+ .write = piddirs_proc_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/* This char only stores the module parameter.
+ The actual piddir_creation_mode is stored in base.c */
+static char *piddir_mode;
+
+/* module config */
+module_param(piddir_mode, charp, 0);
+MODULE_PARM_DESC(piddir_mode, "Default creation mode");
+module_init(proc_piddirs_init);
+__setup("piddir_mode=", param_piddir_mode);
+
+
+
+
+static int __init param_piddir_mode(char *buf)
+{
+ if (strlen(buf))
+ set_piddir_creation_mode(buf[0]);
+ return 1;
+}
+
+static int __init proc_piddirs_init(void)
+{
+ proc_create(
+ "piddirs",
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
+ NULL,
+ &piddirs_proc_fops
+ );
+ return 0;
+}
+
+static int piddirs_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, piddirs_proc_show, NULL);
+}
+
+static int piddirs_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%c\n", get_piddir_creation_mode());
+ return 0;
+}
+
+static ssize_t piddirs_proc_write(struct file *file,
+ const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char tmp;
+
+ if (
+ (count == 2) &&
+ !copy_from_user(&tmp, buf, 1) &&
+ (set_piddir_creation_mode(tmp) == 0)
+ ) {
+ return count;
+ } else {
+ return -EFAULT;
+ }
+}
Index: linux-2.6.38/fs/proc/internal.h
===================================================================
--- linux-2.6.38.orig/fs/proc/internal.h 2011-03-22 10:00:09.717152492 +0100
+++ linux-2.6.38/fs/proc/internal.h 2011-03-22 11:28:42.205497133 +0100
@@ -94,6 +94,10 @@
extern spinlock_t proc_subdir_lock;
struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
+#ifndef CONFIG_PROC_PIDDIRS_UNRESTRICTED
+char get_piddir_creation_mode(void);
+int set_piddir_creation_mode(char mode);
+#endif
int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
unsigned long task_vsize(struct mm_struct *);
unsigned long task_statm(struct mm_struct *,
Index: linux-2.6.38/fs/proc/base.c
===================================================================
--- linux-2.6.38.orig/fs/proc/base.c 2011-03-22 10:00:09.797214588 +0100
+++ linux-2.6.38/fs/proc/base.c 2011-03-24 04:54:51.292565614 +0100
@@ -104,6 +104,14 @@
union proc_op op;
};
+#if defined CONFIG_PROC_PIDDIRS_MODE_U
+ char piddir_creation_mode = 'u';
+#elif defined CONFIG_PROC_PIDDIRS_MODE_UG
+ char piddir_creation_mode = 'g';
+#elif defined CONFIG_PROC_PIDDIRS_MODE_UGO
+ char piddir_creation_mode = 'o';
+#endif
+
#define NOD(NAME, MODE, IOP, FOP, OP) { \
.name = (NAME), \
.len = sizeof(NAME) - 1, \
@@ -1779,8 +1787,15 @@
task = get_proc_task(inode);
if (task) {
- if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
- task_dumpable(task)) {
+ if (
+ #ifndef CONFIG_PROC_PIDDIRS_UNRESTRICTED
+ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IXUSR)) ||
+ (inode->i_mode ==
+ (S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP)) ||
+ #endif
+ (inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
+ task_dumpable(task)
+ ) {
rcu_read_lock();
cred = __task_cred(task);
inode->i_uid = cred->euid;
@@ -1791,6 +1806,21 @@
inode->i_gid = 0;
}
inode->i_mode &= ~(S_ISUID | S_ISGID);
+ #ifndef CONFIG_PROC_PIDDIRS_UNRESTRICTED
+ switch (piddir_creation_mode) {
+ case 'u':
+ inode->i_mode &= ~(S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+ break;
+ case 'g':
+ inode->i_mode |= S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP;
+ inode->i_mode &= ~(S_IROTH|S_IXOTH);
+ break;
+ case 'o':
+ inode->i_mode |= S_IRUGO|S_IXUGO;
+ break;
+ }
+ #endif
+
security_task_to_inode(task, inode);
put_task_struct(task);
return 1;
@@ -2950,6 +2980,35 @@
pid_ns_release_proc(upid->ns);
}
+#ifndef CONFIG_PROC_PIDDIRS_UNRESTRICTED
+char get_piddir_creation_mode(void)
+{
+ return piddir_creation_mode;
+}
+
+int set_piddir_creation_mode(char mode)
+{
+ switch (mode) {
+ case 'u':
+ printk(KERN_INFO "procfs: Setting /proc/<pid>-dir creation"
+ " mode to 500\n");
+ break;
+ case 'g':
+ printk(KERN_INFO "procfs: Setting /proc/<pid>-dir creation"
+ " mode to 550\n");
+ break;
+ case 'o':
+ printk(KERN_INFO "procfs: Setting /proc/<pid>-dir creation"
+ " mode to 555\n");
+ break;
+ default:
+ return -EINVAL;
+ }
+ piddir_creation_mode = mode;
+ return 0;
+}
+#endif
+
static struct dentry *proc_pid_instantiate(struct inode *dir,
struct dentry * dentry,
struct task_struct *task, const void *ptr)
@@ -2961,7 +3020,22 @@
if (!inode)
goto out;
+ #ifndef CONFIG_PROC_PIDDIRS_UNRESTRICTED
+ switch (piddir_creation_mode) {
+ case 'u':
+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR;
+ break;
+ case 'g':
+ inode->i_mode = S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP;
+ break;
+ case 'o':
+ inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+ break;
+ }
+ #else
inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+ #endif
+
inode->i_op = &proc_tgid_base_inode_operations;
inode->i_fop = &proc_tgid_base_operations;
inode->i_flags|=S_IMMUTABLE;
Index: linux-2.6.38/fs/proc/Makefile
===================================================================
--- linux-2.6.38.orig/fs/proc/Makefile 2011-03-22 10:00:09.853177027 +0100
+++ linux-2.6.38/fs/proc/Makefile 2011-03-24 03:48:01.520964812 +0100
@@ -27,3 +27,6 @@
proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o
proc-$(CONFIG_PRINTK) += kmsg.o
proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o
+proc-$(CONFIG_PROC_PIDDIRS_MODE_UGO) += piddirs.o
+proc-$(CONFIG_PROC_PIDDIRS_MODE_UG) += piddirs.o
+proc-$(CONFIG_PROC_PIDDIRS_MODE_U) += piddirs.o
Index: linux-2.6.38/fs/proc/Kconfig
===================================================================
--- linux-2.6.38.orig/fs/proc/Kconfig 2011-03-22 10:00:09.757199278 +0100
+++ linux-2.6.38/fs/proc/Kconfig 2011-03-24 03:46:28.488680884 +0100
@@ -67,3 +67,73 @@
/proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap,
/proc/kpagecount, and /proc/kpageflags. Disabling these
interfaces will reduce the size of the kernel by approximately 4kb.
+
+choice PROC_PIDDIRS
+ prompt "Restrict access to /proc/<pid>-dirs"
+ default PROC_PIDDIRS_MODE_UGO
+ help
+ When set to "no restriction", the access mode for /proc/<pid>-dirs is
+ 555 (r-xr-xr-x) which is the traditional behaviour.
+
+
+ Enabling one of the other options has three impacts:
+
+ 1) set the default access mode to the respective value
+
+ 2) enable a boot parameter called piddir_mode; possible values are
+ - 'u': limit to user
+ - 'g': limit to user and group
+ - 'o': no limits (other may read)
+
+ e.g. piddir_mode=u
+
+ 3) enable runtime-configuration of the access modes by issuing e.g.
+ echo g > /proc/piddirs
+ Again, the possible values are 'u', 'g', 'o'.
+
+config PROC_PIDDIRS_UNRESTRICTED
+ bool "no restriction"
+ depends on PROC_FS
+ help
+ Don't restrict access to /proc/<pid>-dirs, i.e. leave mode at 555
+ respectively r-xr-xr-x . Runtime manipulation of access mode is
+ disabled. This is the traditional mode of operation.
+
+ If unsure, say Y.
+
+config PROC_PIDDIRS_MODE_UGO
+ bool "unrestricted by default"
+ depends on PROC_FS
+ help
+ Don't restrict access to /proc/<pid>-dirs, i.e. leave mode at 555
+ (r-xr-xr-x). The default access mode can be changed to 555 during
+ runtime e.g. by issuing
+
+ echo o > /proc/piddirs
+
+ If unsure, say N.
+
+config PROC_PIDDIRS_MODE_UG
+ bool "restrict to user and group by default"
+ depends on PROC_FS
+ help
+ Restrict access to /proc/<pid>-dirs to user and group, i.e. set mode
+ to 550 (r-xr-x---). The default access mode can be changed to 550
+ during runtime e.g. by issuing
+
+ echo g > /proc/piddirs
+
+ If unsure, say N.
+
+config PROC_PIDDIRS_MODE_U
+ bool "restrict to user by default"
+ depends on PROC_FS
+ help
+ Restrict access to /proc/<pid>-dirs to user only, i.e. set mode to
+ 500 (r-x------). The default access mode can be changed to 500 during
+ runtime e.g. by issuing
+
+ echo u > /proc/piddirs
+
+ If unsure, say N.
+endchoice
next reply other threads:[~2011-03-24 4:19 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-24 4:09 Daniel Reichelt [this message]
2011-03-24 7:32 ` procfs: boot- and runtime configurable access mode for /proc/<pid> dirs Alexey Dobriyan
2011-03-24 8:41 ` Daniel Reichelt
2011-03-24 18:22 ` Alexey Dobriyan
2011-03-24 18:44 ` Al Viro
2011-03-24 18:49 ` Daniel Reichelt
2011-03-24 19:18 ` Daniel Reichelt
2011-03-24 20:37 ` Al Viro
2011-03-25 21:24 ` Christian Kujau
2011-05-26 10:56 ` Al Viro
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=4D8AC408.9000503@nachtgeist.net \
--to=debian@nachtgeist.net \
--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.