[Devel] [PATCH 10/10] cr: lsm: restore file->f_security
Serge E. Hallyn
serue at us.ibm.com
Tue Jun 9 18:47:04 PDT 2009
file->f_cred is the cred of the task which opened it. file->f_security
can be separately set by the LSM. Checkpoint the file->f_security,
and at restart ask the LSM, using security_file_restore, based on the current
task's context and the checkpointed f_security, which f_security to apply (or
whether to refuse the restart altogether).
For Smack, accept the checkpointed label if the restarting task has
CAP_MAC_ADMIN.
For SELinux, I currently ignore the checkpointed label and call
file_alloc_security(). Do we want to have 'restore' permission for
class file?
Signed-off-by: Serge E. Hallyn <serue at us.ibm.com>
---
checkpoint/files.c | 33 +++++++++++++++++++++++++++++++++
include/linux/checkpoint_hdr.h | 1 +
include/linux/security.h | 13 +++++++++++++
security/capability.c | 6 ++++++
security/security.c | 5 +++++
security/selinux/hooks.c | 11 +++++++++++
security/smack/smack_lsm.c | 26 +++++++++++++++++++++++++-
7 files changed, 94 insertions(+), 1 deletions(-)
diff --git a/checkpoint/files.c b/checkpoint/files.c
index 5be7d1b..36c7f35 100644
--- a/checkpoint/files.c
+++ b/checkpoint/files.c
@@ -19,6 +19,7 @@
#include <linux/fsnotify.h>
#include <linux/pipe_fs_i.h>
#include <linux/syscalls.h>
+#include <linux/security.h>
#include <linux/checkpoint.h>
#include <linux/checkpoint_hdr.h>
@@ -155,6 +156,14 @@ int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file,
if (h->f_credref < 0)
return h->f_credref;
+#ifdef CONFIG_SECURITY
+ if (file->f_security) {
+ h->f_secref = checkpoint_obj(ctx, file->f_security, CKPT_OBJ_SEC);
+ if (h->f_secref < 0)
+ return h->f_secref;
+ } else
+ h->f_secref = -1;
+#endif
/* FIX: need also file->f_owner, etc */
return 0;
@@ -437,6 +446,26 @@ static int attach_file(struct file *file)
return fd;
}
+#ifdef CONFIG_SECURITY
+int restore_file_security(struct ckpt_ctx *ctx, struct file *file,
+ struct ckpt_hdr_file *h)
+{
+ void *security = NULL;
+
+ if (h->f_secref != -1)
+ security = ckpt_obj_fetch(ctx, h->f_secref, CKPT_OBJ_SEC);
+ if (IS_ERR(security))
+ return PTR_ERR(security);
+ return security_file_restore(file, security);
+}
+#else
+static inline int restore_file_security(struct ckpt_ctx *ctx,
+ struct file *file, struct ckpt_hdr_file *h)
+{
+ return 0;
+}
+#endif
+
#define CKPT_SETFL_MASK \
(O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME)
@@ -455,6 +484,10 @@ int restore_file_common(struct ckpt_ctx *ctx, struct file *file,
put_cred(file->f_cred);
file->f_cred = get_cred(cred);
+ ret = restore_file_security(ctx, file, h);
+ if (ret < 0)
+ goto out;
+
/* safe to set 1st arg (fd) to 0, as command is F_SETFL */
ret = vfs_fcntl(0, F_SETFL, h->f_flags & CKPT_SETFL_MASK, file);
if (ret < 0)
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index a447b5a..1722826 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -320,6 +320,7 @@ struct ckpt_hdr_file {
__s32 f_credref;
__u64 f_pos;
__u64 f_version;
+ __s32 f_secref;
} __attribute__((aligned(8)));
struct ckpt_hdr_file_generic {
diff --git a/include/linux/security.h b/include/linux/security.h
index 5625553..936a2a1 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -554,6 +554,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* created.
* @file contains the file structure to secure.
* Return 0 if the hook is successful and permission is granted.
+ * @file_restore_security:
+ * Allocate and attach a security structure to the file->f_security field
+ * during sys_restart().
+ * @file contains the file structure to secure.
+ * @stored contains the checkpointed context.
+ * Return 0 if the hook is successful and permission is granted.
* @file_free_security:
* Deallocate and free any security structures stored in file->f_security.
* @file contains the file structure being modified.
@@ -1494,6 +1500,7 @@ struct security_operations {
int (*file_permission) (struct file *file, int mask);
int (*file_alloc_security) (struct file *file);
+ int (*file_restore_security) (struct file *file, void *stored);
void (*file_free_security) (struct file *file);
int (*file_ioctl) (struct file *file, unsigned int cmd,
unsigned long arg);
@@ -1761,6 +1768,7 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
void security_inode_getsecid(const struct inode *inode, u32 *secid);
int security_file_permission(struct file *file, int mask);
int security_file_alloc(struct file *file);
+int security_file_restore(struct file *file, void *stored);
void security_file_free(struct file *file);
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
int security_file_mmap(struct file *file, unsigned long reqprot,
@@ -2250,6 +2258,11 @@ static inline int security_file_alloc(struct file *file)
return 0;
}
+static inline int security_file_restore(struct file *file, void *stored)
+{
+ return 0;
+}
+
static inline void security_file_free(struct file *file)
{ }
diff --git a/security/capability.c b/security/capability.c
index 4e586a7..f0a3c65 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -320,6 +320,11 @@ static int cap_file_alloc_security(struct file *file)
return 0;
}
+static int cap_file_restore_security(struct file *file, void *stored)
+{
+ return 0;
+}
+
static void cap_file_free_security(struct file *file)
{
}
@@ -976,6 +981,7 @@ void security_fixup_ops(struct security_operations *ops)
#endif
set_to_cap_if_null(ops, file_permission);
set_to_cap_if_null(ops, file_alloc_security);
+ set_to_cap_if_null(ops, file_restore_security);
set_to_cap_if_null(ops, file_free_security);
set_to_cap_if_null(ops, file_ioctl);
set_to_cap_if_null(ops, file_mmap);
diff --git a/security/security.c b/security/security.c
index 26e7989..0006e9c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -628,6 +628,11 @@ int security_file_alloc(struct file *file)
return security_ops->file_alloc_security(file);
}
+int security_file_restore(struct file *file, void *stored)
+{
+ return security_ops->file_restore_security(file, stored);
+}
+
void security_file_free(struct file *file)
{
security_ops->file_free_security(file);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ba24808..4b8c636 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2973,6 +2973,16 @@ static int selinux_file_alloc_security(struct file *file)
return file_alloc_security(file);
}
+static int selinux_file_restore_security(struct file *file,
+ void *stored)
+{
+ /*
+ * TODO - actually restore from 'stored' subject to authorization
+ */
+ kfree(stored);
+ return file_alloc_security(file);
+}
+
static void selinux_file_free_security(struct file *file)
{
file_free_security(file);
@@ -5566,6 +5576,7 @@ static struct security_operations selinux_ops = {
.file_permission = selinux_file_permission,
.file_alloc_security = selinux_file_alloc_security,
+ .file_restore_security = selinux_file_restore_security,
.file_free_security = selinux_file_free_security,
.file_ioctl = selinux_file_ioctl,
.file_mmap = selinux_file_mmap,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index dfc0f7a..7bcdfde 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -831,6 +831,30 @@ static int smack_file_alloc_security(struct file *file)
}
/**
+ * smack_file_restore_security - assign a file security blob
+ * @file: the object
+ * @stored: the label stored in the checkpoint file
+ *
+ * Returns 0
+ */
+static int smack_file_restore_security(struct file *file, void *stored)
+{
+ char *str = smk_import(stored, 0);
+
+ if (str == NULL)
+ return -EINVAL;
+
+ file->f_security = current_security();
+ if (current_security() != str) {
+ if (!capable(CAP_MAC_ADMIN))
+ return -EPERM;
+ file->f_security = str;
+ }
+
+ return 0;
+}
+
+/**
* smack_file_free_security - clear a file security blob
* @file: the object
*
@@ -1630,7 +1654,6 @@ static int smack_msg_msg_restore_security(struct msg_msg *msg,
msg->security = str;
}
return 0;
- return 0;
}
/**
@@ -2996,6 +3019,7 @@ struct security_operations smack_ops = {
.file_permission = smack_file_permission,
.file_alloc_security = smack_file_alloc_security,
+ .file_restore_security = smack_file_restore_security,
.file_free_security = smack_file_free_security,
.file_ioctl = smack_file_ioctl,
.file_lock = smack_file_lock,
--
1.6.1
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
More information about the Devel
mailing list