All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Serge E. Hallyn" <serue@us.ibm.com>
To: Oren Laadan <orenl@cs.columbia.edu>
Cc: Casey Schaufler <casey@schaufler-ca.com>,
	Linux Containers <containers@lists.osdl.org>,
	linux-security-module@vger.kernel.org,
	SELinux <selinux@tycho.nsa.gov>
Subject: [RFC PATCH 2/2] cr: debug security_checkpoint_header and security_may_restart
Date: Thu, 3 Sep 2009 17:28:53 -0500	[thread overview]
Message-ID: <20090903222853.GA27556@us.ibm.com> (raw)
In-Reply-To: <20090903222824.GB27377@us.ibm.com>

This patch, for debugging only, introduces a silly admin-controlled
'policy version' for smack.  By default the version is 1.  An
admin (with CAP_MAC_ADMIN) can change it by echoing a new value
into /smack/version.

It then defines security_checkpoint_header() to add this 'policy
version' into the checkpoint header, and defines security_may_restart()
to refuse restart if both:
	1. the caller asked for RESTART_KEEP_LSM
and
	2. the checkpointed version was different from the current.

This of course is easy enough to test by doing

	echo 1 > /smack/version
	ckpt > out
	mktree < out
		succeed
	mktree -k < out
		succeed
	echo 2 > /smack/version
	mktree < out
		succeed
	mktree -k < out
		fail

Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
---
 security/smack/smack_lsm.c |   46 +++++++++++++++++++++++++++
 security/smack/smackfs.c   |   75 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 279fdce..f0d4a08 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -27,6 +27,7 @@
 #include <linux/udp.h>
 #include <linux/mutex.h>
 #include <linux/pipe_fs_i.h>
+#include <linux/checkpoint.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
 #include <linux/audit.h>
@@ -3111,6 +3112,47 @@ static void smack_release_secctx(char *secdata, u32 seclen)
 {
 }
 
+#ifdef CONFIG_CHECKPOINT
+extern int smack_version;
+
+static int smack_may_restart(struct ckpt_ctx *ctx)
+{
+	struct ckpt_hdr *h;
+	char *smackv;
+	int v = 0, slen, ret;
+
+	h = ckpt_read_buf_type(ctx, CKPT_LSM_INFO_LEN, CKPT_HDR_LSM_INFO);
+	if (IS_ERR(h))
+		return PTR_ERR(h);
+
+	if (strcmp(ctx->lsm_name, "smack") != 0)
+		return 0;
+
+	smackv = (char *) (h + 1);
+	slen = h->len - sizeof(*h);
+	if (smackv[slen-1] != '\0')
+		smackv[slen-1] = '\0';
+	ret = sscanf(smackv, "%d", &v);
+	ckpt_hdr_put(ctx, h);
+	if (!(ctx->uflags & RESTART_KEEP_LSM))
+		return 0;
+	if (ret != 1 || v != smack_version) {
+		ckpt_debug("Smack version at checkpoint was %d, now is %d\n",
+			v, smack_version);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int smack_checkpoint_header(struct ckpt_ctx *ctx)
+{
+	char smackv[10];
+	sprintf(smackv, "%d", smack_version);
+	return ckpt_write_obj_type(ctx, smackv, strlen(smackv)+1,
+				  CKPT_HDR_LSM_INFO);
+}
+#endif
+
 struct security_operations smack_ops = {
 	.name =				"smack",
 
@@ -3245,6 +3287,10 @@ struct security_operations smack_ops = {
 	.secid_to_secctx = 		smack_secid_to_secctx,
 	.secctx_to_secid = 		smack_secctx_to_secid,
 	.release_secctx = 		smack_release_secctx,
+#ifdef CONFIG_CHECKPOINT
+	.may_restart =			smack_may_restart,
+	.checkpoint_header =		smack_checkpoint_header,
+#endif
 };
 
 
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index f83a809..7b20ad9 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -42,6 +42,7 @@ enum smk_inos {
 	SMK_NETLBLADDR	= 8,	/* single label hosts */
 	SMK_ONLYCAP	= 9,	/* the only "capable" label */
 	SMK_LOGGING	= 10,	/* logging */
+	SMK_VERSION	= 11,	/* logging */
 };
 
 /*
@@ -51,6 +52,7 @@ static DEFINE_MUTEX(smack_list_lock);
 static DEFINE_MUTEX(smack_cipso_lock);
 static DEFINE_MUTEX(smack_ambient_lock);
 static DEFINE_MUTEX(smk_netlbladdr_lock);
+static DEFINE_MUTEX(smack_version_lock);
 
 /*
  * This is the "ambient" label for network traffic.
@@ -60,6 +62,11 @@ static DEFINE_MUTEX(smk_netlbladdr_lock);
 char *smack_net_ambient = smack_known_floor.smk_known;
 
 /*
+ * this is the policy version, a simple integer
+ */
+int smack_version = 1;
+
+/*
  * This is the level in a CIPSO header that indicates a
  * smack label is contained directly in the category set.
  * It can be reset via smackfs/direct
@@ -1255,6 +1262,72 @@ static const struct file_operations smk_logging_ops = {
 	.read		= smk_read_logging,
 	.write		= smk_write_logging,
 };
+
+#define SMK_VERSIONLEN 12
+/**
+ * smk_read_version - read() for /smack/version
+ * @filp: file pointer, not actually used
+ * @buf: where to put the result
+ * @cn: maximum to send along
+ * @ppos: where to start
+ *
+ * Returns number of bytes read or error code, as appropriate
+ */
+static ssize_t smk_read_version(struct file *filp, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	char temp[SMK_VERSIONLEN];
+
+	if (*ppos != 0)
+		return 0;
+
+	mutex_lock(&smack_version_lock);
+	sprintf(temp, "%d\n", smack_version);
+	mutex_unlock(&smack_version_lock);
+
+	return simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
+}
+
+/**
+ * smk_write_version - write() for /smack/version
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_version(struct file *file, const char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	char in[SMK_VERSIONLEN];
+	int tmp, ret;
+
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	if (count >= SMK_VERSIONLEN)
+		return -EINVAL;
+
+	if (copy_from_user(in, buf, count) != 0)
+		return -EFAULT;
+
+	in[count-1] = '\0';
+	ret = sscanf(in, "%d", &tmp);
+	if (ret != 1)
+		return -EINVAL;
+	mutex_lock(&smack_version_lock);
+	smack_version = tmp;
+	mutex_unlock(&smack_version_lock);
+
+	return count;
+}
+
+static const struct file_operations smk_version_ops = {
+	.read		= smk_read_version,
+	.write		= smk_write_version,
+};
+
 /**
  * smk_fill_super - fill the /smackfs superblock
  * @sb: the empty superblock
@@ -1287,6 +1360,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
 			{"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
 		[SMK_LOGGING]	=
 			{"logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
+		[SMK_VERSION]	=
+			{"version", &smk_version_ops, S_IRUGO|S_IWUSR},
 		/* last one */ {""}
 	};
 
-- 
1.6.1


WARNING: multiple messages have this Message-ID (diff)
From: "Serge E. Hallyn" <serue@us.ibm.com>
To: Oren Laadan <orenl@cs.columbia.edu>
Cc: Casey Schaufler <casey@schaufler-ca.com>,
	Linux Containers <containers@lists.osdl.org>,
	linux-security-module@vger.kernel.org,
	SELinux <selinux@tycho.nsa.gov>
Subject: [RFC PATCH 2/2] cr: debug security_checkpoint_header and security_may_restart
Date: Thu, 3 Sep 2009 17:28:53 -0500	[thread overview]
Message-ID: <20090903222853.GA27556@us.ibm.com> (raw)
In-Reply-To: <20090903222824.GB27377@us.ibm.com>

This patch, for debugging only, introduces a silly admin-controlled
'policy version' for smack.  By default the version is 1.  An
admin (with CAP_MAC_ADMIN) can change it by echoing a new value
into /smack/version.

It then defines security_checkpoint_header() to add this 'policy
version' into the checkpoint header, and defines security_may_restart()
to refuse restart if both:
	1. the caller asked for RESTART_KEEP_LSM
and
	2. the checkpointed version was different from the current.

This of course is easy enough to test by doing

	echo 1 > /smack/version
	ckpt > out
	mktree < out
		succeed
	mktree -k < out
		succeed
	echo 2 > /smack/version
	mktree < out
		succeed
	mktree -k < out
		fail

Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
---
 security/smack/smack_lsm.c |   46 +++++++++++++++++++++++++++
 security/smack/smackfs.c   |   75 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 279fdce..f0d4a08 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -27,6 +27,7 @@
 #include <linux/udp.h>
 #include <linux/mutex.h>
 #include <linux/pipe_fs_i.h>
+#include <linux/checkpoint.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
 #include <linux/audit.h>
@@ -3111,6 +3112,47 @@ static void smack_release_secctx(char *secdata, u32 seclen)
 {
 }
 
+#ifdef CONFIG_CHECKPOINT
+extern int smack_version;
+
+static int smack_may_restart(struct ckpt_ctx *ctx)
+{
+	struct ckpt_hdr *h;
+	char *smackv;
+	int v = 0, slen, ret;
+
+	h = ckpt_read_buf_type(ctx, CKPT_LSM_INFO_LEN, CKPT_HDR_LSM_INFO);
+	if (IS_ERR(h))
+		return PTR_ERR(h);
+
+	if (strcmp(ctx->lsm_name, "smack") != 0)
+		return 0;
+
+	smackv = (char *) (h + 1);
+	slen = h->len - sizeof(*h);
+	if (smackv[slen-1] != '\0')
+		smackv[slen-1] = '\0';
+	ret = sscanf(smackv, "%d", &v);
+	ckpt_hdr_put(ctx, h);
+	if (!(ctx->uflags & RESTART_KEEP_LSM))
+		return 0;
+	if (ret != 1 || v != smack_version) {
+		ckpt_debug("Smack version at checkpoint was %d, now is %d\n",
+			v, smack_version);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int smack_checkpoint_header(struct ckpt_ctx *ctx)
+{
+	char smackv[10];
+	sprintf(smackv, "%d", smack_version);
+	return ckpt_write_obj_type(ctx, smackv, strlen(smackv)+1,
+				  CKPT_HDR_LSM_INFO);
+}
+#endif
+
 struct security_operations smack_ops = {
 	.name =				"smack",
 
@@ -3245,6 +3287,10 @@ struct security_operations smack_ops = {
 	.secid_to_secctx = 		smack_secid_to_secctx,
 	.secctx_to_secid = 		smack_secctx_to_secid,
 	.release_secctx = 		smack_release_secctx,
+#ifdef CONFIG_CHECKPOINT
+	.may_restart =			smack_may_restart,
+	.checkpoint_header =		smack_checkpoint_header,
+#endif
 };
 
 
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index f83a809..7b20ad9 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -42,6 +42,7 @@ enum smk_inos {
 	SMK_NETLBLADDR	= 8,	/* single label hosts */
 	SMK_ONLYCAP	= 9,	/* the only "capable" label */
 	SMK_LOGGING	= 10,	/* logging */
+	SMK_VERSION	= 11,	/* logging */
 };
 
 /*
@@ -51,6 +52,7 @@ static DEFINE_MUTEX(smack_list_lock);
 static DEFINE_MUTEX(smack_cipso_lock);
 static DEFINE_MUTEX(smack_ambient_lock);
 static DEFINE_MUTEX(smk_netlbladdr_lock);
+static DEFINE_MUTEX(smack_version_lock);
 
 /*
  * This is the "ambient" label for network traffic.
@@ -60,6 +62,11 @@ static DEFINE_MUTEX(smk_netlbladdr_lock);
 char *smack_net_ambient = smack_known_floor.smk_known;
 
 /*
+ * this is the policy version, a simple integer
+ */
+int smack_version = 1;
+
+/*
  * This is the level in a CIPSO header that indicates a
  * smack label is contained directly in the category set.
  * It can be reset via smackfs/direct
@@ -1255,6 +1262,72 @@ static const struct file_operations smk_logging_ops = {
 	.read		= smk_read_logging,
 	.write		= smk_write_logging,
 };
+
+#define SMK_VERSIONLEN 12
+/**
+ * smk_read_version - read() for /smack/version
+ * @filp: file pointer, not actually used
+ * @buf: where to put the result
+ * @cn: maximum to send along
+ * @ppos: where to start
+ *
+ * Returns number of bytes read or error code, as appropriate
+ */
+static ssize_t smk_read_version(struct file *filp, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	char temp[SMK_VERSIONLEN];
+
+	if (*ppos != 0)
+		return 0;
+
+	mutex_lock(&smack_version_lock);
+	sprintf(temp, "%d\n", smack_version);
+	mutex_unlock(&smack_version_lock);
+
+	return simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
+}
+
+/**
+ * smk_write_version - write() for /smack/version
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_version(struct file *file, const char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	char in[SMK_VERSIONLEN];
+	int tmp, ret;
+
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	if (count >= SMK_VERSIONLEN)
+		return -EINVAL;
+
+	if (copy_from_user(in, buf, count) != 0)
+		return -EFAULT;
+
+	in[count-1] = '\0';
+	ret = sscanf(in, "%d", &tmp);
+	if (ret != 1)
+		return -EINVAL;
+	mutex_lock(&smack_version_lock);
+	smack_version = tmp;
+	mutex_unlock(&smack_version_lock);
+
+	return count;
+}
+
+static const struct file_operations smk_version_ops = {
+	.read		= smk_read_version,
+	.write		= smk_write_version,
+};
+
 /**
  * smk_fill_super - fill the /smackfs superblock
  * @sb: the empty superblock
@@ -1287,6 +1360,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
 			{"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
 		[SMK_LOGGING]	=
 			{"logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
+		[SMK_VERSION]	=
+			{"version", &smk_version_ops, S_IRUGO|S_IWUSR},
 		/* last one */ {""}
 	};
 
-- 
1.6.1


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

  reply	other threads:[~2009-09-03 22:28 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-03 22:28 [RFC PATCH 1/2] cr: lsm: provide hooks for an LSM to track policy changes Serge E. Hallyn
2009-09-03 22:28 ` Serge E. Hallyn
2009-09-03 22:28 ` Serge E. Hallyn [this message]
2009-09-03 22:28   ` [RFC PATCH 2/2] cr: debug security_checkpoint_header and security_may_restart Serge E. Hallyn
2009-09-04  5:20   ` Casey Schaufler
2009-09-04  5:20     ` Casey Schaufler
2009-09-04 13:46     ` Serge E. Hallyn
2009-09-04 13:46       ` Serge E. Hallyn
2009-09-07 18:31       ` Casey Schaufler
2009-09-07 18:31         ` Casey Schaufler
2009-09-08  4:12         ` Serge E. Hallyn
2009-09-08  4:12           ` Serge E. Hallyn
2009-09-09  4:43           ` Casey Schaufler
2009-09-09  4:43             ` Casey Schaufler
2009-09-09 14:35             ` Serge E. Hallyn
2009-09-09 14:35               ` Serge E. Hallyn
2009-09-09 14:52               ` Casey Schaufler
2009-09-09 14:52                 ` Casey Schaufler
2009-09-09 19:46                 ` Serge E. Hallyn
2009-09-09 19:46                   ` Serge E. Hallyn

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=20090903222853.GA27556@us.ibm.com \
    --to=serue@us.ibm.com \
    --cc=casey@schaufler-ca.com \
    --cc=containers@lists.osdl.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=orenl@cs.columbia.edu \
    --cc=selinux@tycho.nsa.gov \
    /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.