Skip to contentSkip to conversation

SELinux: display mount options in /proc/mounts

RFC In review Eric Paris 3 participants 5 messages Mar 31, 2008 – Apr 1, 2008

Subsystems (3)
lore
Share & tools
lore

Eric Paris

author
#0 lore raw

RFC 1/1 SELinux: display mount options in /proc/mounts

This patch will display selinux mount options in /proc/mounts. It does so by building a complete string and then writing it to the seq_file. I could cut a fair bit of this patch out by just writing things piecemeal to the seq_file but when I did that none of the code looked like it could ever be used again. Do we think we'll ever have another need to turn a superblock back into an option string? Should I just make this patch as small as possible?

Anyway, lightly tested and never looked at since I wrote it so it could very likely have bad error handling or memory leaks or major flaws....

comments?

-Eric

---

 fs/namespace.c                      |    4 +
 include/linux/security.h            |    9 +++
 security/dummy.c                    |    6 ++
 security/security.c                 |    5 ++
 security/selinux/hooks.c            |  121 ++++++++++++++++++++++++++++++++---
 security/selinux/include/security.h |    5 ++
 6 files changed, 141 insertions(+), 9 deletions(-)
fs/namespace.c +4 -0
index 94f026e..a9748d3 100644
@@ -426,8 +426,12 @@ static int show_vfsmnt(struct seq_file *m, void *v)
 		if (mnt->mnt_flags & fs_infop->flag)
 			seq_puts(m, fs_infop->str);
 	}
+	err = security_sb_show_options(m, mnt->mnt_sb);
+	if (err)
+		goto out;
 	if (mnt->mnt_sb->s_op->show_options)
 		err = mnt->mnt_sb->s_op->show_options(m, mnt);
+out:
 	seq_puts(m, " 0 0\n");
 	return err;
 }
include/linux/security.h +9 -0
index c673dfd..2743bf2 100644
@@ -74,6 +74,7 @@ struct xfrm_selector;
 struct xfrm_policy;
 struct xfrm_state;
 struct xfrm_user_sec_ctx;
+struct seq_file;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -1259,6 +1260,7 @@ struct security_operations {
 	void (*sb_free_security) (struct super_block * sb);
 	int (*sb_copy_data)(char *orig, char *copy);
 	int (*sb_kern_mount) (struct super_block *sb, void *data);
+	int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
 	int (*sb_statfs) (struct dentry *dentry);
 	int (*sb_mount) (char *dev_name, struct nameidata * nd,
 			 char *type, unsigned long flags, void *data);
@@ -1527,6 +1529,7 @@ int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
 int security_sb_kern_mount(struct super_block *sb, void *data);
+int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
 int security_sb_mount(char *dev_name, struct nameidata *nd,
                        char *type, unsigned long flags, void *data);
@@ -1800,6 +1803,12 @@ static inline int security_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static inline int security_sb_show_options (struct seq_file *m,
+					    struct super_block *sb)
+{
+	return 0;
+}
+
 static inline int security_sb_statfs (struct dentry *dentry)
 {
 	return 0;
security/dummy.c +6 -0
index 78d8f92..7f8ac13 100644
@@ -191,6 +191,11 @@ static int dummy_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static int dummy_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return 0;
+}
+
 static int dummy_sb_statfs (struct dentry *dentry)
 {
 	return 0;
@@ -1017,6 +1022,7 @@ void security_fixup_ops (struct security_operations *ops)
 	set_to_dummy_if_null(ops, sb_free_security);
 	set_to_dummy_if_null(ops, sb_copy_data);
 	set_to_dummy_if_null(ops, sb_kern_mount);
+	set_to_dummy_if_null(ops, sb_show_options);
 	set_to_dummy_if_null(ops, sb_statfs);
 	set_to_dummy_if_null(ops, sb_mount);
 	set_to_dummy_if_null(ops, sb_check_sb);
security/security.c +5 -0
index b1387a6..93e6309 100644
@@ -255,6 +255,11 @@ int security_sb_kern_mount(struct super_block *sb, void *data)
 	return security_ops->sb_kern_mount(sb, data);
 }
 
+int security_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return security_ops->sb_show_options(m, sb);
+}
+
 int security_sb_statfs(struct dentry *dentry)
 {
 	return security_ops->sb_statfs(dentry);
security/selinux/hooks.c +112 -9

154 lines not on this page · raw message

security/selinux/include/security.h +5 -0
index f7d2f03..63e0171 100644
@@ -40,6 +40,11 @@
 #define ROOTCONTEXT_MNT	0x04
 #define DEFCONTEXT_MNT	0x08
 
+#define CONTEXT_STR	"context="
+#define FSCONTEXT_STR	"fscontext="
+#define ROOTCONTEXT_STR	"rootcontext="
+#define DEFCONTEXT_STR	"defcontext="
+
 struct netlbl_lsm_secattr;
 
 extern int selinux_enabled;

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#1 lore raw
Quoted 7 lines · Eric Paris

This patch will display selinux mount options in /proc/mounts. It does so by building a complete string and then writing it to the seq_file. I could cut a fair bit of this patch out by just writing things piecemeal to the seq_file but when I did that none of the code looked like it could ever be used again. Do we think we'll ever have another need to turn a superblock back into an option string? Should I just make this patch as small as possible?

Isn't that the point of using seq_file in the first place? Offhand, I'd vote for simplifying the implementation even if it makes the usage specialized.

Quoted 296 lines

Anyway, lightly tested and never looked at since I wrote it so it could very likely have bad error handling or memory leaks or major flaws....

comments?

(quoted diff) +0 -2
-Eric
 
---
 
 fs/namespace.c                      |    4 +
 include/linux/security.h            |    9 +++
 security/dummy.c                    |    6 ++
 security/security.c                 |    5 ++
 security/selinux/hooks.c            |  121 ++++++++++++++++++++++++++++++++---
 security/selinux/include/security.h |    5 ++
 6 files changed, 141 insertions(+), 9 deletions(-)
fs/namespace.c +4 -0
index 94f026e..a9748d3 100644
@@ -426,8 +426,12 @@ static int show_vfsmnt(struct seq_file *m, void *v)
 		if (mnt->mnt_flags & fs_infop->flag)
 			seq_puts(m, fs_infop->str);
 	}
+	err = security_sb_show_options(m, mnt->mnt_sb);
+	if (err)
+		goto out;
 	if (mnt->mnt_sb->s_op->show_options)
 		err = mnt->mnt_sb->s_op->show_options(m, mnt);
+out:
 	seq_puts(m, " 0 0\n");
 	return err;
 }
include/linux/security.h +9 -0
index c673dfd..2743bf2 100644
@@ -74,6 +74,7 @@ struct xfrm_selector;
 struct xfrm_policy;
 struct xfrm_state;
 struct xfrm_user_sec_ctx;
+struct seq_file;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -1259,6 +1260,7 @@ struct security_operations {
 	void (*sb_free_security) (struct super_block * sb);
 	int (*sb_copy_data)(char *orig, char *copy);
 	int (*sb_kern_mount) (struct super_block *sb, void *data);
+	int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
 	int (*sb_statfs) (struct dentry *dentry);
 	int (*sb_mount) (char *dev_name, struct nameidata * nd,
 			 char *type, unsigned long flags, void *data);
@@ -1527,6 +1529,7 @@ int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
 int security_sb_kern_mount(struct super_block *sb, void *data);
+int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
 int security_sb_mount(char *dev_name, struct nameidata *nd,
                        char *type, unsigned long flags, void *data);
@@ -1800,6 +1803,12 @@ static inline int security_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static inline int security_sb_show_options (struct seq_file *m,
+					    struct super_block *sb)
+{
+	return 0;
+}
+
 static inline int security_sb_statfs (struct dentry *dentry)
 {
 	return 0;
security/dummy.c +6 -0
index 78d8f92..7f8ac13 100644
@@ -191,6 +191,11 @@ static int dummy_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static int dummy_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return 0;
+}
+
 static int dummy_sb_statfs (struct dentry *dentry)
 {
 	return 0;
@@ -1017,6 +1022,7 @@ void security_fixup_ops (struct security_operations *ops)
 	set_to_dummy_if_null(ops, sb_free_security);
 	set_to_dummy_if_null(ops, sb_copy_data);
 	set_to_dummy_if_null(ops, sb_kern_mount);
+	set_to_dummy_if_null(ops, sb_show_options);
 	set_to_dummy_if_null(ops, sb_statfs);
 	set_to_dummy_if_null(ops, sb_mount);
 	set_to_dummy_if_null(ops, sb_check_sb);
security/security.c +5 -0
index b1387a6..93e6309 100644
@@ -255,6 +255,11 @@ int security_sb_kern_mount(struct super_block *sb, void *data)
 	return security_ops->sb_kern_mount(sb, data);
 }
 
+int security_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return security_ops->sb_show_options(m, sb);
+}
+
 int security_sb_statfs(struct dentry *dentry)
 {
 	return security_ops->sb_statfs(dentry);
security/selinux/hooks.c +112 -9
index 41a049f..1bdc7b7 100644
@@ -16,10 +16,11 @@
  *                Paul Moore <[email protected]>
  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
  *                     Yuichi Nakamura <[email protected]>
+ *  Copyright (C) 2006-2008 Red Hat, Inc., Eric Paris <[email protected]>
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License version 2,
- *      as published by the Free Software Foundation.
+ *	as published by the Free Software Foundation.
  */
 
 #include <linux/init.h>
@@ -324,10 +325,10 @@ enum {
 };
 
 static match_table_t tokens = {
-	{Opt_context, "context=%s"},
-	{Opt_fscontext, "fscontext=%s"},
-	{Opt_defcontext, "defcontext=%s"},
-	{Opt_rootcontext, "rootcontext=%s"},
+	{Opt_context, CONTEXT_STR "%s"},
+	{Opt_fscontext, FSCONTEXT_STR "%s"},
+	{Opt_defcontext, DEFCONTEXT_STR "%s"},
+	{Opt_rootcontext, ROOTCONTEXT_STR "%s"},
 	{Opt_error, NULL},
 };
 
@@ -947,6 +948,107 @@ out_err:
 	return rc;
 }
 
+int selinux_get_opts_str(char **ret_str, struct security_mnt_opts *opts)
+{
+	size_t total_len = 0;
+	char *new_string;
+	int i;
+
+	if (opts->num_mnt_opts == 0) {
+		*ret_str = NULL;
+		return 0;
+	}
+
+	/* determine size of the new string */
+	for(i = 0; i < opts->num_mnt_opts; i++) {
+		total_len += strlen(opts->mnt_opts[i]);
+		switch (opts->mnt_opts_flags[i]) {
+		case CONTEXT_MNT:
+			total_len += strlen(CONTEXT_STR);
+			break;
+		case FSCONTEXT_MNT:
+			total_len += strlen(FSCONTEXT_STR);
+			break;
+		case ROOTCONTEXT_MNT:
+			total_len += strlen(ROOTCONTEXT_STR);
+			break;
+		case DEFCONTEXT_MNT:
+			total_len += strlen(DEFCONTEXT_STR);
+			break;
+		default:
+			BUG();
+		};
+		/* comma between options */
+		total_len += 1;
+	}
+
+	*ret_str = new_string = kmalloc((total_len + 1) * sizeof(char), GFP_KERNEL);
+	if (!new_string)
+		return -ENOMEM;
+
+	/* build new string */
+	new_string[0] = '\0';
+	for(i = 0; i < opts->num_mnt_opts; i++) {
+		/* we need a comma before each option */
+		strcat(new_string, ",");
+		switch (opts->mnt_opts_flags[i]) {
+		case CONTEXT_MNT:
+			strcat(new_string, CONTEXT_STR);
+			break;
+		case FSCONTEXT_MNT:
+			strcat(new_string, FSCONTEXT_STR);
+			break;
+		case ROOTCONTEXT_MNT:
+			strcat(new_string, ROOTCONTEXT_STR);
+			break;
+		case DEFCONTEXT_MNT:
+			strcat(new_string, DEFCONTEXT_STR);
+			break;
+		default:
+			BUG();
+		};
+		strcat(new_string, opts->mnt_opts[i]);
+	}
+	return 0;
+}
+
+static char *selinux_sb_to_opts_str(struct super_block *sb)
+{
+	struct security_mnt_opts opts;
+	char *opts_str = NULL;
+
+	int rc;
+
+	rc = selinux_get_mnt_opts(sb, &opts);
+	if (rc)
+		return ERR_PTR(rc);
+
+	rc = selinux_get_opts_str(&opts_str, &opts);
+	if (rc)
+		return ERR_PTR(rc);
+
+	security_free_mnt_opts(&opts);
+
+	return opts_str;
+}
+
+
+static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
+{
+	char *opts_str;
+	int rc = 0;
+
+	opts_str = selinux_sb_to_opts_str(sb);
+
+	if (IS_ERR(opts_str))
+		return PTR_ERR(opts_str);
+
+	rc = seq_puts(m, opts_str);
+
+	kfree(opts_str);
+	return rc;
+}
+
 static inline u16 inode_mode_to_security_class(umode_t mode)
 {
 	switch (mode & S_IFMT) {
@@ -2232,10 +2334,10 @@ static inline int match_prefix(char *prefix, int plen, char *option, int olen)
 
 static inline int selinux_option(char *option, int len)
 {
-	return (match_prefix("context=", sizeof("context=")-1, option, len) ||
-	        match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
-	        match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
-		match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
+	return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
+	        match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
+	        match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
+		match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
 }
 
 static inline void take_option(char **to, char *from, int *first, int len)
@@ -5257,6 +5359,7 @@ static struct security_operations selinux_ops = {
 	.sb_free_security =		selinux_sb_free_security,
 	.sb_copy_data =			selinux_sb_copy_data,
 	.sb_kern_mount =	        selinux_sb_kern_mount,
+	.sb_show_options =		selinux_sb_show_options,
 	.sb_statfs =			selinux_sb_statfs,
 	.sb_mount =			selinux_mount,
 	.sb_umount =			selinux_umount,
security/selinux/include/security.h +5 -0
index f7d2f03..63e0171 100644
@@ -40,6 +40,11 @@
 #define ROOTCONTEXT_MNT	0x04
 #define DEFCONTEXT_MNT	0x08
 
+#define CONTEXT_STR	"context="
+#define FSCONTEXT_STR	"fscontext="
+#define ROOTCONTEXT_STR	"rootcontext="
+#define DEFCONTEXT_STR	"defcontext="
+
 struct netlbl_lsm_secattr;
 
 extern int selinux_enabled;
Signature · 8 lines
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
author
#2 lore raw
Quoted 9 lines · Stephen Smalley
Quoted 7 lines · Eric Paris

This patch will display selinux mount options in /proc/mounts. It does so by building a complete string and then writing it to the seq_file. I could cut a fair bit of this patch out by just writing things piecemeal to the seq_file but when I did that none of the code looked like it could ever be used again. Do we think we'll ever have another need to turn a superblock back into an option string? Should I just make this patch as small as possible?

Quoted 3 lines

Isn't that the point of using seq_file in the first place? Offhand, I'd vote for simplifying the implementation even if it makes the usage specialized.

How about something this then? I can (should?) break this down into a
separate #define changes and new functionality change... But I'll take
comments on this patch...

-Eric

---

 fs/namespace.c                      |    4 ++
 include/linux/security.h            |    9 +++++
 security/dummy.c                    |    6 +++
 security/security.c                 |    5 +++
 security/selinux/hooks.c            |   69 ++++++++++++++++++++++++++++++-----
 security/selinux/include/security.h |    5 +++
 6 files changed, 89 insertions(+), 9 deletions(-)
fs/namespace.c +4 -0
index 94f026e..a9748d3 100644
@@ -426,8 +426,12 @@ static int show_vfsmnt(struct seq_file *m, void *v)
 		if (mnt->mnt_flags & fs_infop->flag)
 			seq_puts(m, fs_infop->str);
 	}
+	err = security_sb_show_options(m, mnt->mnt_sb);
+	if (err)
+		goto out;
 	if (mnt->mnt_sb->s_op->show_options)
 		err = mnt->mnt_sb->s_op->show_options(m, mnt);
+out:
 	seq_puts(m, " 0 0\n");
 	return err;
 }
include/linux/security.h +9 -0
index c673dfd..2743bf2 100644
@@ -74,6 +74,7 @@ struct xfrm_selector;
 struct xfrm_policy;
 struct xfrm_state;
 struct xfrm_user_sec_ctx;
+struct seq_file;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -1259,6 +1260,7 @@ struct security_operations {
 	void (*sb_free_security) (struct super_block * sb);
 	int (*sb_copy_data)(char *orig, char *copy);
 	int (*sb_kern_mount) (struct super_block *sb, void *data);
+	int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
 	int (*sb_statfs) (struct dentry *dentry);
 	int (*sb_mount) (char *dev_name, struct nameidata * nd,
 			 char *type, unsigned long flags, void *data);
@@ -1527,6 +1529,7 @@ int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
 int security_sb_kern_mount(struct super_block *sb, void *data);
+int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
 int security_sb_mount(char *dev_name, struct nameidata *nd,
                        char *type, unsigned long flags, void *data);
@@ -1800,6 +1803,12 @@ static inline int security_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static inline int security_sb_show_options (struct seq_file *m,
+					    struct super_block *sb)
+{
+	return 0;
+}
+
 static inline int security_sb_statfs (struct dentry *dentry)
 {
 	return 0;
security/dummy.c +6 -0
index 78d8f92..7f8ac13 100644
@@ -191,6 +191,11 @@ static int dummy_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static int dummy_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return 0;
+}
+
 static int dummy_sb_statfs (struct dentry *dentry)
 {
 	return 0;
@@ -1017,6 +1022,7 @@ void security_fixup_ops (struct security_operations *ops)
 	set_to_dummy_if_null(ops, sb_free_security);
 	set_to_dummy_if_null(ops, sb_copy_data);
 	set_to_dummy_if_null(ops, sb_kern_mount);
+	set_to_dummy_if_null(ops, sb_show_options);
 	set_to_dummy_if_null(ops, sb_statfs);
 	set_to_dummy_if_null(ops, sb_mount);
 	set_to_dummy_if_null(ops, sb_check_sb);
security/security.c +5 -0
index b1387a6..93e6309 100644
@@ -255,6 +255,11 @@ int security_sb_kern_mount(struct super_block *sb, void *data)
 	return security_ops->sb_kern_mount(sb, data);
 }
 
+int security_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return security_ops->sb_show_options(m, sb);
+}
+
 int security_sb_statfs(struct dentry *dentry)
 {
 	return security_ops->sb_statfs(dentry);
security/selinux/hooks.c +60 -9

102 lines not on this page · raw message

security/selinux/include/security.h +5 -0
index f7d2f03..63e0171 100644
@@ -40,6 +40,11 @@
 #define ROOTCONTEXT_MNT	0x04
 #define DEFCONTEXT_MNT	0x08
 
+#define CONTEXT_STR	"context="
+#define FSCONTEXT_STR	"fscontext="
+#define ROOTCONTEXT_STR	"rootcontext="
+#define DEFCONTEXT_STR	"defcontext="
+
 struct netlbl_lsm_secattr;
 
 extern int selinux_enabled;

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

maintainer
#3 lore raw
Quoted 10 lines · Eric Paris
Quoted 9 lines · Stephen Smalley
Quoted 7 lines · Eric Paris

This patch will display selinux mount options in /proc/mounts. It does so by building a complete string and then writing it to the seq_file. I could cut a fair bit of this patch out by just writing things piecemeal to the seq_file but when I did that none of the code looked like it could ever be used again. Do we think we'll ever have another need to turn a superblock back into an option string? Should I just make this patch as small as possible?

Quoted 7 lines
Quoted 3 lines

Isn't that the point of using seq_file in the first place? Offhand, I'd vote for simplifying the implementation even if it makes the usage specialized.

How about something this then? I can (should?) break this down into a
separate #define changes and new functionality change... But I'll take
comments on this patch...

Seems like a good approach, please post it to lsm and fsdevel.

Quoted 240 lines
(quoted diff) +0 -2
-Eric
 
---
 
 fs/namespace.c                      |    4 ++
 include/linux/security.h            |    9 +++++
 security/dummy.c                    |    6 +++
 security/security.c                 |    5 +++
 security/selinux/hooks.c            |   69 ++++++++++++++++++++++++++++++-----
 security/selinux/include/security.h |    5 +++
 6 files changed, 89 insertions(+), 9 deletions(-)
fs/namespace.c +4 -0
index 94f026e..a9748d3 100644
@@ -426,8 +426,12 @@ static int show_vfsmnt(struct seq_file *m, void *v)
 		if (mnt->mnt_flags & fs_infop->flag)
 			seq_puts(m, fs_infop->str);
 	}
+	err = security_sb_show_options(m, mnt->mnt_sb);
+	if (err)
+		goto out;
 	if (mnt->mnt_sb->s_op->show_options)
 		err = mnt->mnt_sb->s_op->show_options(m, mnt);
+out:
 	seq_puts(m, " 0 0\n");
 	return err;
 }
include/linux/security.h +9 -0
index c673dfd..2743bf2 100644
@@ -74,6 +74,7 @@ struct xfrm_selector;
 struct xfrm_policy;
 struct xfrm_state;
 struct xfrm_user_sec_ctx;
+struct seq_file;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -1259,6 +1260,7 @@ struct security_operations {
 	void (*sb_free_security) (struct super_block * sb);
 	int (*sb_copy_data)(char *orig, char *copy);
 	int (*sb_kern_mount) (struct super_block *sb, void *data);
+	int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
 	int (*sb_statfs) (struct dentry *dentry);
 	int (*sb_mount) (char *dev_name, struct nameidata * nd,
 			 char *type, unsigned long flags, void *data);
@@ -1527,6 +1529,7 @@ int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
 int security_sb_kern_mount(struct super_block *sb, void *data);
+int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
 int security_sb_mount(char *dev_name, struct nameidata *nd,
                        char *type, unsigned long flags, void *data);
@@ -1800,6 +1803,12 @@ static inline int security_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static inline int security_sb_show_options (struct seq_file *m,
+					    struct super_block *sb)
+{
+	return 0;
+}
+
 static inline int security_sb_statfs (struct dentry *dentry)
 {
 	return 0;
security/dummy.c +6 -0
index 78d8f92..7f8ac13 100644
@@ -191,6 +191,11 @@ static int dummy_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static int dummy_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return 0;
+}
+
 static int dummy_sb_statfs (struct dentry *dentry)
 {
 	return 0;
@@ -1017,6 +1022,7 @@ void security_fixup_ops (struct security_operations *ops)
 	set_to_dummy_if_null(ops, sb_free_security);
 	set_to_dummy_if_null(ops, sb_copy_data);
 	set_to_dummy_if_null(ops, sb_kern_mount);
+	set_to_dummy_if_null(ops, sb_show_options);
 	set_to_dummy_if_null(ops, sb_statfs);
 	set_to_dummy_if_null(ops, sb_mount);
 	set_to_dummy_if_null(ops, sb_check_sb);
security/security.c +5 -0
index b1387a6..93e6309 100644
@@ -255,6 +255,11 @@ int security_sb_kern_mount(struct super_block *sb, void *data)
 	return security_ops->sb_kern_mount(sb, data);
 }
 
+int security_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return security_ops->sb_show_options(m, sb);
+}
+
 int security_sb_statfs(struct dentry *dentry)
 {
 	return security_ops->sb_statfs(dentry);
security/selinux/hooks.c +60 -9
index 41a049f..d18a674 100644
@@ -16,10 +16,11 @@
  *                Paul Moore <[email protected]>
  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
  *                     Yuichi Nakamura <[email protected]>
+ *  Copyright (C) 2006-2008 Red Hat, Inc., Eric Paris <[email protected]>
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License version 2,
- *      as published by the Free Software Foundation.
+ *	as published by the Free Software Foundation.
  */
 
 #include <linux/init.h>
@@ -324,10 +325,10 @@ enum {
 };
 
 static match_table_t tokens = {
-	{Opt_context, "context=%s"},
-	{Opt_fscontext, "fscontext=%s"},
-	{Opt_defcontext, "defcontext=%s"},
-	{Opt_rootcontext, "rootcontext=%s"},
+	{Opt_context, CONTEXT_STR "%s"},
+	{Opt_fscontext, FSCONTEXT_STR "%s"},
+	{Opt_defcontext, DEFCONTEXT_STR "%s"},
+	{Opt_rootcontext, ROOTCONTEXT_STR "%s"},
 	{Opt_error, NULL},
 };
 
@@ -947,6 +948,55 @@ out_err:
 	return rc;
 }
 
+int selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts)
+{
+	int i, rc;
+	char *prefix;
+
+	for(i = 0; i < opts->num_mnt_opts; i++) {
+		/* we need a comma before each option */
+		rc = seq_putc(m, ',');
+		if (rc)
+			return rc;
+
+		switch (opts->mnt_opts_flags[i]) {
+		case CONTEXT_MNT:
+			prefix = CONTEXT_STR;
+			break;
+		case FSCONTEXT_MNT:
+			prefix = FSCONTEXT_STR;
+			break;
+		case ROOTCONTEXT_MNT:
+			prefix = ROOTCONTEXT_STR;
+			break;
+		case DEFCONTEXT_MNT:
+			prefix = DEFCONTEXT_STR;
+			break;
+		default:
+			BUG();
+		};
+		seq_puts(m, prefix);
+		seq_puts(m, opts->mnt_opts[i]);
+	}
+	return 0;
+}
+
+static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
+{
+	struct security_mnt_opts opts;
+	int rc;
+
+	rc = selinux_get_mnt_opts(sb, &opts);
+	if (rc)
+		return rc;
+
+	rc = selinux_write_opts(m, &opts);
+
+	security_free_mnt_opts(&opts);
+
+	return rc;
+}
+
 static inline u16 inode_mode_to_security_class(umode_t mode)
 {
 	switch (mode & S_IFMT) {
@@ -2232,10 +2282,10 @@ static inline int match_prefix(char *prefix, int plen, char *option, int olen)
 
 static inline int selinux_option(char *option, int len)
 {
-	return (match_prefix("context=", sizeof("context=")-1, option, len) ||
-	        match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
-	        match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
-		match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
+	return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
+	        match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
+	        match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
+		match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
 }
 
 static inline void take_option(char **to, char *from, int *first, int len)
@@ -5257,6 +5307,7 @@ static struct security_operations selinux_ops = {
 	.sb_free_security =		selinux_sb_free_security,
 	.sb_copy_data =			selinux_sb_copy_data,
 	.sb_kern_mount =	        selinux_sb_kern_mount,
+	.sb_show_options =		selinux_sb_show_options,
 	.sb_statfs =			selinux_sb_statfs,
 	.sb_mount =			selinux_mount,
 	.sb_umount =			selinux_umount,
security/selinux/include/security.h +5 -0
index f7d2f03..63e0171 100644
@@ -40,6 +40,11 @@
 #define ROOTCONTEXT_MNT	0x04
 #define DEFCONTEXT_MNT	0x08
 
+#define CONTEXT_STR	"context="
+#define FSCONTEXT_STR	"fscontext="
+#define ROOTCONTEXT_STR	"rootcontext="
+#define DEFCONTEXT_STR	"defcontext="
+
 struct netlbl_lsm_secattr;
 
 extern int selinux_enabled;
Signature · 7 lines
James Morris
<[email protected]>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
#4 lore raw
In reply to Eric Paris
Quoted 133 lines · Eric Paris
Quoted 9 lines · Stephen Smalley
Quoted 7 lines · Eric Paris

This patch will display selinux mount options in /proc/mounts. It does so by building a complete string and then writing it to the seq_file. I could cut a fair bit of this patch out by just writing things piecemeal to the seq_file but when I did that none of the code looked like it could ever be used again. Do we think we'll ever have another need to turn a superblock back into an option string? Should I just make this patch as small as possible?

Quoted 3 lines

Isn't that the point of using seq_file in the first place? Offhand, I'd vote for simplifying the implementation even if it makes the usage specialized.

How about something this then? I can (should?) break this down into a
separate #define changes and new functionality change... But I'll take
comments on this patch...

(quoted diff) +0 -2
-Eric
 
---
 
 fs/namespace.c                      |    4 ++
 include/linux/security.h            |    9 +++++
 security/dummy.c                    |    6 +++
 security/security.c                 |    5 +++
 security/selinux/hooks.c            |   69 ++++++++++++++++++++++++++++++-----
 security/selinux/include/security.h |    5 +++
 6 files changed, 89 insertions(+), 9 deletions(-)
fs/namespace.c +4 -0
index 94f026e..a9748d3 100644
@@ -426,8 +426,12 @@ static int show_vfsmnt(struct seq_file *m, void *v)
 		if (mnt->mnt_flags & fs_infop->flag)
 			seq_puts(m, fs_infop->str);
 	}
+	err = security_sb_show_options(m, mnt->mnt_sb);
+	if (err)
+		goto out;
 	if (mnt->mnt_sb->s_op->show_options)
 		err = mnt->mnt_sb->s_op->show_options(m, mnt);
+out:
 	seq_puts(m, " 0 0\n");
 	return err;
 }
include/linux/security.h +9 -0
index c673dfd..2743bf2 100644
@@ -74,6 +74,7 @@ struct xfrm_selector;
 struct xfrm_policy;
 struct xfrm_state;
 struct xfrm_user_sec_ctx;
+struct seq_file;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -1259,6 +1260,7 @@ struct security_operations {
 	void (*sb_free_security) (struct super_block * sb);
 	int (*sb_copy_data)(char *orig, char *copy);
 	int (*sb_kern_mount) (struct super_block *sb, void *data);
+	int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
 	int (*sb_statfs) (struct dentry *dentry);
 	int (*sb_mount) (char *dev_name, struct nameidata * nd,
 			 char *type, unsigned long flags, void *data);
@@ -1527,6 +1529,7 @@ int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
 int security_sb_kern_mount(struct super_block *sb, void *data);
+int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
 int security_sb_mount(char *dev_name, struct nameidata *nd,
                        char *type, unsigned long flags, void *data);
@@ -1800,6 +1803,12 @@ static inline int security_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static inline int security_sb_show_options (struct seq_file *m,
+					    struct super_block *sb)
+{
+	return 0;
+}
+
 static inline int security_sb_statfs (struct dentry *dentry)
 {
 	return 0;
security/dummy.c +6 -0
index 78d8f92..7f8ac13 100644
@@ -191,6 +191,11 @@ static int dummy_sb_kern_mount (struct super_block *sb, void *data)
 	return 0;
 }
 
+static int dummy_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return 0;
+}
+
 static int dummy_sb_statfs (struct dentry *dentry)
 {
 	return 0;
@@ -1017,6 +1022,7 @@ void security_fixup_ops (struct security_operations *ops)
 	set_to_dummy_if_null(ops, sb_free_security);
 	set_to_dummy_if_null(ops, sb_copy_data);
 	set_to_dummy_if_null(ops, sb_kern_mount);
+	set_to_dummy_if_null(ops, sb_show_options);
 	set_to_dummy_if_null(ops, sb_statfs);
 	set_to_dummy_if_null(ops, sb_mount);
 	set_to_dummy_if_null(ops, sb_check_sb);
security/security.c +5 -0
index b1387a6..93e6309 100644
@@ -255,6 +255,11 @@ int security_sb_kern_mount(struct super_block *sb, void *data)
 	return security_ops->sb_kern_mount(sb, data);
 }
 
+int security_sb_show_options (struct seq_file *m, struct super_block *sb)
+{
+	return security_ops->sb_show_options(m, sb);
+}
+
 int security_sb_statfs(struct dentry *dentry)
 {
 	return security_ops->sb_statfs(dentry);
security/selinux/hooks.c +0 -0
index 41a049f..d18a674 100644

security/selinux/hooks.c line 19

Quoted 4 lines
security/selinux/hooks.c +1 -0
@@ -16,10 +16,11 @@
  *                Paul Moore <[email protected]>
  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
  *                     Yuichi Nakamura <[email protected]>
+ *  Copyright (C) 2006-2008 Red Hat, Inc., Eric Paris <[email protected]>

You could just extend the existing Red Hat copyright from 2003 if you wanted.

Quoted 24 lines
security/selinux/hooks.c +5 -5
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License version 2,
- *      as published by the Free Software Foundation.
+ *	as published by the Free Software Foundation.
  */
 
 #include <linux/init.h>
@@ -324,10 +325,10 @@ enum {
 };
 
 static match_table_t tokens = {
-	{Opt_context, "context=%s"},
-	{Opt_fscontext, "fscontext=%s"},
-	{Opt_defcontext, "defcontext=%s"},
-	{Opt_rootcontext, "rootcontext=%s"},
+	{Opt_context, CONTEXT_STR "%s"},
+	{Opt_fscontext, FSCONTEXT_STR "%s"},
+	{Opt_defcontext, DEFCONTEXT_STR "%s"},
+	{Opt_rootcontext, ROOTCONTEXT_STR "%s"},
 	{Opt_error, NULL},
 };
 

security/selinux/hooks.c out_err: · line 956

Quoted 9 lines
security/selinux/hooks.c +6 -0
@@ -947,6 +948,55 @@ out_err:
 	return rc;
 }
 
+int selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts)
+{
+	int i, rc;
+	char *prefix;
+
+	for(i = 0; i < opts->num_mnt_opts; i++) {

nit: I like having a space between "for" and the open parens.

security/selinux/hooks.c out_err: · line 960

Quoted 4 lines
security/selinux/hooks.c +4 -0
+		/* we need a comma before each option */
+		rc = seq_putc(m, ',');
+		if (rc)
+			return rc;

So seq_putc can fail.

Quoted 9 lines
security/selinux/hooks.c +9 -0
+
+		switch (opts->mnt_opts_flags[i]) {
+		case CONTEXT_MNT:
+			prefix = CONTEXT_STR;
+			break;
+		case FSCONTEXT_MNT:
+			prefix = FSCONTEXT_STR;
+			break;
+		case ROOTCONTEXT_MNT:

security/selinux/hooks.c out_err: · line 979

Quoted 10 lines
security/selinux/hooks.c +10 -0
+			prefix = ROOTCONTEXT_STR;
+			break;
+		case DEFCONTEXT_MNT:
+			prefix = DEFCONTEXT_STR;
+			break;
+		default:
+			BUG();
+		};
+		seq_puts(m, prefix);
+		seq_puts(m, opts->mnt_opts[i]);

But seq_puts cannot?

Quoted 63 lines
security/selinux/hooks.c +25 -4
+	}
+	return 0;
+}
+
+static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
+{
+	struct security_mnt_opts opts;
+	int rc;
+
+	rc = selinux_get_mnt_opts(sb, &opts);
+	if (rc)
+		return rc;
+
+	rc = selinux_write_opts(m, &opts);
+
+	security_free_mnt_opts(&opts);
+
+	return rc;
+}
+
 static inline u16 inode_mode_to_security_class(umode_t mode)
 {
 	switch (mode & S_IFMT) {
@@ -2232,10 +2282,10 @@ static inline int match_prefix(char *prefix, int plen, char *option, int olen)
 
 static inline int selinux_option(char *option, int len)
 {
-	return (match_prefix("context=", sizeof("context=")-1, option, len) ||
-	        match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
-	        match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
-		match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
+	return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
+	        match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
+	        match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
+		match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
 }
 
 static inline void take_option(char **to, char *from, int *first, int len)
@@ -5257,6 +5307,7 @@ static struct security_operations selinux_ops = {
 	.sb_free_security =		selinux_sb_free_security,
 	.sb_copy_data =			selinux_sb_copy_data,
 	.sb_kern_mount =	        selinux_sb_kern_mount,
+	.sb_show_options =		selinux_sb_show_options,
 	.sb_statfs =			selinux_sb_statfs,
 	.sb_mount =			selinux_mount,
 	.sb_umount =			selinux_umount,
security/selinux/include/security.h +5 -0
index f7d2f03..63e0171 100644
@@ -40,6 +40,11 @@
 #define ROOTCONTEXT_MNT	0x04
 #define DEFCONTEXT_MNT	0x08
 
+#define CONTEXT_STR	"context="
+#define FSCONTEXT_STR	"fscontext="
+#define ROOTCONTEXT_STR	"rootcontext="
+#define DEFCONTEXT_STR	"defcontext="
+
 struct netlbl_lsm_secattr;
 
 extern int selinux_enabled;
Signature · 8 lines
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.