linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] proc filesystem (1/3): fix mount options
@ 2005-02-01 23:46 rene.scharfe
  2005-02-01 23:48 ` [PATCH] proc filesystem (2/3): add umask option rene.scharfe
  0 siblings, 1 reply; 3+ messages in thread
From: rene.scharfe @ 2005-02-01 23:46 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-kernel

Hello,

while trying to add a umask option to the proc filesystem I stumbled
over a somewhat related problem: the existing mount options uid and
gid were non-functional.  The patch below is an attempt to fix them
and prepares the ground for my evil umask plans. :)

The first half of the reason why the uid and gid options are not
working is that proc has only a single superblock, no matter how many
times it is mounted.  This is achieved with the help of get_single_sb().
Only the first mount calls fill_super(), all following mounts are
like remounts.

The second half is that proc is mounted during boot with kern_mount().
This function passes NULL as mount parameter string to
proc_fill_super().

So the single mount call where we could provide some options provides --
nothing.  I don't know why parse_options() is not called from
proc_remount(), but it looks like this has been done on purpose, to
avoid changing ownership of the root inode while proc is mounted.
Is that observation correct or was it just an accident?

Anyway, the following patch changes proc to not appear like accepting
regular mount options and instead makes it parse kernel parameters.  I
hope this is not too evil.  They provide the semantics which I hope is
correct: changable at boot time and only at boot time.

Patch is against 2.6.11-rc2-bk10 (2.6.10 should be OK, too), compiles,
boots and works for me.

Comments welcome.

Thanks,
Rene


diff -pur linux-2.6.11-rc2-bk10/fs/proc/inode.c ll/fs/proc/inode.c
--- linux-2.6.11-rc2-bk10/fs/proc/inode.c	2005-02-01 04:17:25.000000000 +0100
+++ ll/fs/proc/inode.c	2005-02-01 03:23:51.000000000 +0100
@@ -148,22 +148,24 @@ enum {
 };
 
 static match_table_t tokens = {
-	{Opt_uid, "uid=%u"},
-	{Opt_gid, "gid=%u"},
+	{Opt_uid, "proc.uid=%u"},
+	{Opt_gid, "proc.gid=%u"},
 	{Opt_err, NULL}
 };
 
+/*
+ * This parse_options function is different.  It parses kernel parameters
+ * instead of filesystem mount options.
+ */ 
 static int parse_options(char *options,uid_t *uid,gid_t *gid)
 {
 	char *p;
 	int option;
 
-	*uid = current->uid;
-	*gid = current->gid;
 	if (!options)
 		return 1;
 
-	while ((p = strsep(&options, ",")) != NULL) {
+	while ((p = strsep(&options, " \t")) != NULL) {
 		substring_t args[MAX_OPT_ARGS];
 		int token;
 		if (!*p)
@@ -173,16 +175,14 @@ static int parse_options(char *options,u
 		switch (token) {
 		case Opt_uid:
 			if (match_int(args, &option))
-				return 0;
+				continue;
 			*uid = option;
 			break;
 		case Opt_gid:
 			if (match_int(args, &option))
-				return 0;
+				continue;
 			*gid = option;
 			break;
-		default:
-			return 0;
 		}
 	}
 	return 1;
@@ -231,6 +231,11 @@ out_fail:
 	goto out;
 }			
 
+/*
+ * Because proc is a single-superblock filesystem, proc_fill_super() is
+ * only called at boot time and never during sys_mount().  That means
+ * filesystem options can only be specified as kernel parameters.
+ */
 int proc_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * root_inode;
@@ -249,6 +254,8 @@ int proc_fill_super(struct super_block *
 	 * Fixup the root inode's nlink value
 	 */
 	root_inode->i_nlink += nr_processes();
+	root_inode->i_uid = 0;
+	root_inode->i_gid = 0;
 	s->s_root = d_alloc_root(root_inode);
 	if (!s->s_root)
 		goto out_no_root;
diff -pur linux-2.6.11-rc2-bk10/fs/proc/root.c ll/fs/proc/root.c
--- linux-2.6.11-rc2-bk10/fs/proc/root.c	2004-12-24 22:35:24.000000000 +0100
+++ ll/fs/proc/root.c	2005-02-01 02:25:04.000000000 +0100
@@ -7,6 +7,7 @@
  */
 
 #include <asm/uaccess.h>
+#include <asm/setup.h>
 
 #include <linux/errno.h>
 #include <linux/time.h>
@@ -17,6 +18,8 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/smp_lock.h>
+#include <linux/string.h>
+#include <linux/mount.h>
 
 struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
 
@@ -39,13 +42,15 @@ static struct file_system_type proc_fs_t
 extern int __init proc_init_inodecache(void);
 void __init proc_root_init(void)
 {
+	char tmp_cmdline[COMMAND_LINE_SIZE];
 	int err = proc_init_inodecache();
 	if (err)
 		return;
 	err = register_filesystem(&proc_fs_type);
 	if (err)
 		return;
-	proc_mnt = kern_mount(&proc_fs_type);
+	strlcpy(tmp_cmdline, saved_command_line, COMMAND_LINE_SIZE);
+	proc_mnt = do_kern_mount("proc", 0, "proc", tmp_cmdline);
 	err = PTR_ERR(proc_mnt);
 	if (IS_ERR(proc_mnt)) {
 		unregister_filesystem(&proc_fs_type);

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] proc filesystem (2/3): add umask option
  2005-02-01 23:46 [PATCH] proc filesystem (1/3): fix mount options rene.scharfe
@ 2005-02-01 23:48 ` rene.scharfe
  2005-02-01 23:50   ` [PATCH] proc filesystem (3/3): add proc_show_options() rene.scharfe
  0 siblings, 1 reply; 3+ messages in thread
From: rene.scharfe @ 2005-02-01 23:48 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-kernel

This patch adds the umask option to the proc filesystem.  It's
essentially unchanged from the previous version, except that the mount
option has to be specified as a kernel parameter now.  This way we avoid
dealing with pre-existing inodes.

The umask can be used to restrict the permissions of process information
in /proc (the numerical directories and the files within them).  No other
file or directory should be affected.

Al, there was a big IF in your comment regarding the previous version.  
Do you have general objections against the umask feature or its
usefulness?

Thanks,
Rene


diff -pur l1/fs/proc/base.c l2/fs/proc/base.c
--- l1/fs/proc/base.c	2005-02-01 04:17:25.000000000 +0100
+++ l2/fs/proc/base.c	2005-02-01 04:26:03.000000000 +0100
@@ -180,6 +180,8 @@ static struct pid_entry tid_attr_stuff[]
 
 #undef E
 
+umode_t proc_umask;
+
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
 	struct task_struct *task = proc_task(inode);
@@ -1222,7 +1224,7 @@ static struct dentry *proc_pident_lookup
 		goto out;
 
 	ei = PROC_I(inode);
-	inode->i_mode = p->mode;
+	inode->i_mode = p->mode & ~proc_umask;
 	/*
 	 * Yes, it does not scale. And it should not. Don't add
 	 * new entries into /proc/<tgid>/ without very good reasons.
@@ -1537,7 +1539,7 @@ struct dentry *proc_pid_lookup(struct in
 		put_task_struct(task);
 		goto out;
 	}
-	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+	inode->i_mode = (S_IFDIR|S_IRUGO|S_IXUGO) & ~proc_umask;
 	inode->i_op = &proc_tgid_base_inode_operations;
 	inode->i_fop = &proc_tgid_base_operations;
 	inode->i_nlink = 3;
@@ -1592,7 +1594,7 @@ static struct dentry *proc_task_lookup(s
 
 	if (!inode)
 		goto out_drop_task;
-	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+	inode->i_mode = (S_IFDIR|S_IRUGO|S_IXUGO) & ~proc_umask;
 	inode->i_op = &proc_tid_base_inode_operations;
 	inode->i_fop = &proc_tid_base_operations;
 	inode->i_nlink = 3;
diff -pur l1/fs/proc/inode.c l2/fs/proc/inode.c
--- l1/fs/proc/inode.c	2005-02-01 04:29:33.000000000 +0100
+++ l2/fs/proc/inode.c	2005-02-01 04:24:08.000000000 +0100
@@ -20,6 +20,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+extern umode_t proc_umask;
 extern void free_proc_entry(struct proc_dir_entry *);
 
 static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de)
@@ -144,12 +145,13 @@ static struct super_operations proc_sops
 };
 
 enum {
-	Opt_uid, Opt_gid, Opt_err
+	Opt_uid, Opt_gid, Opt_umask, Opt_err
 };
 
 static match_table_t tokens = {
 	{Opt_uid, "proc.uid=%u"},
 	{Opt_gid, "proc.gid=%u"},
+	{Opt_umask, "proc.umask=%o"},
 	{Opt_err, NULL}
 };
 
@@ -183,6 +185,11 @@ static int parse_options(char *options,u
 				continue;
 			*gid = option;
 			break;
+		case Opt_umask:
+			if (match_octal(args, &option))
+				continue;
+			proc_umask = option & 0777;
+			break;
 		}
 	}
 	return 1;
@@ -240,6 +247,7 @@ int proc_fill_super(struct super_block *
 {
 	struct inode * root_inode;
 
+	proc_umask = 0;
 	s->s_flags |= MS_NODIRATIME;
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] proc filesystem (3/3): add proc_show_options()
  2005-02-01 23:48 ` [PATCH] proc filesystem (2/3): add umask option rene.scharfe
@ 2005-02-01 23:50   ` rene.scharfe
  0 siblings, 0 replies; 3+ messages in thread
From: rene.scharfe @ 2005-02-01 23:50 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-kernel

This patch adds a show_options function to the proc filesystem.

diff -pur l2/fs/proc/inode.c l3/fs/proc/inode.c
--- l2/fs/proc/inode.c	2005-02-01 04:51:23.000000000 +0100
+++ l3/fs/proc/inode.c	2005-02-01 04:51:07.000000000 +0100
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/parser.h>
 #include <linux/smp_lock.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -23,6 +24,9 @@
 extern umode_t proc_umask;
 extern void free_proc_entry(struct proc_dir_entry *);
 
+static int proc_root_inode_uid;
+static int proc_root_inode_gid;
+
 static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de)
 {
 	if (de)
@@ -134,6 +138,17 @@ static int proc_remount(struct super_blo
 	return 0;
 }
 
+static int proc_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+	if (proc_root_inode_uid != 0)
+		seq_printf(m, ",uid=%i", proc_root_inode_uid);
+	if (proc_root_inode_gid != 0)
+		seq_printf(m, ",gid=%i", proc_root_inode_gid);
+	if (proc_umask != 0)
+		seq_printf(m, ",umask=%04o", proc_umask);
+	return 0;
+}
+
 static struct super_operations proc_sops = { 
 	.alloc_inode	= proc_alloc_inode,
 	.destroy_inode	= proc_destroy_inode,
@@ -142,6 +157,7 @@ static struct super_operations proc_sops
 	.delete_inode	= proc_delete_inode,
 	.statfs		= simple_statfs,
 	.remount_fs	= proc_remount,
+	.show_options	= proc_show_options,
 };
 
 enum {
@@ -248,6 +264,8 @@ int proc_fill_super(struct super_block *
 	struct inode * root_inode;
 
 	proc_umask = 0;
+	proc_root_inode_uid = 0;
+	proc_root_inode_gid = 0;
 	s->s_flags |= MS_NODIRATIME;
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;
@@ -262,12 +280,12 @@ int proc_fill_super(struct super_block *
 	 * Fixup the root inode's nlink value
 	 */
 	root_inode->i_nlink += nr_processes();
-	root_inode->i_uid = 0;
-	root_inode->i_gid = 0;
 	s->s_root = d_alloc_root(root_inode);
 	if (!s->s_root)
 		goto out_no_root;
-	parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
+	parse_options(data, &proc_root_inode_uid, &proc_root_inode_gid);
+	root_inode->i_uid = proc_root_inode_uid;
+	root_inode->i_gid = proc_root_inode_gid;
 	return 0;
 
 out_no_root:

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2005-02-01 23:53 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-02-01 23:46 [PATCH] proc filesystem (1/3): fix mount options rene.scharfe
2005-02-01 23:48 ` [PATCH] proc filesystem (2/3): add umask option rene.scharfe
2005-02-01 23:50   ` [PATCH] proc filesystem (3/3): add proc_show_options() rene.scharfe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).