add lsm name and lsm_info (policy header) to container info
PATCH 1/1 add lsm name and lsm_info (policy header) to container info
The LSM name is 'selinux', 'smack', 'tomoyo', or 'dummy'. We add that to the container configuration section. We also add a LSM policy configuration section. That is placed after the LSM name. It is written by the LSM in security_checkpoint_header(), called during checkpoint container(), and read by the LSM during security_may_restart(), which is called from restore_lsm() in restore_container().
--- checkpoint/checkpoint.c | 13 ++++++++- checkpoint/restart.c | 41 ++++++++++++++++++++++++++ checkpoint/sys.c | 21 +++++++++++++ include/linux/checkpoint.h | 7 ++++- include/linux/checkpoint_hdr.h | 16 ++++++++++ include/linux/checkpoint_types.h | 2 + include/linux/security.h | 58 ++++++++++++++++++++++++++++++++++++++ security/capability.c | 24 +++++++++++++++ security/security.c | 26 +++++++++++++++++ 9 files changed, 206 insertions(+), 2 deletions(-)
checkpoint/checkpoint.c +12 -1
@@ -366,7 +366,18 @@ static int checkpoint_container(struct ckpt_ctx *ctx) ret =ckpt_write_obj (ctx, &h->h);ckpt_hdr_put (ctx, h); -return ret; +if (ret <0 ) +return ret; + +memset (ctx->lsm_name,0 ,CHECKPOINT_LSM_NAME_MAX +1 ); +strlcpy (ctx->lsm_name,security_get_lsm_name (), +CHECKPOINT_LSM_NAME_MAX +1 ); + ret =ckpt_write_buffer (ctx, ctx->lsm_name, +CHECKPOINT_LSM_NAME_MAX +1 ); +if (ret <0 ) +return ret; + +return security_checkpoint_header (ctx); }/* write the checkpoint trailer */
checkpoint/restart.c +41 -0
53 lines not on this page · raw message
checkpoint/sys.c +21 -0
@@ -169,6 +169,27 @@ void *ckpt_hdr_get_type(struct ckpt_ctx *ctx, int len, int type)return h; } +#define DUMMY_LSM_INFO "dummy" + +int ckpt_write_dummy_lsm_info (struct ckpt_ctx *ctx) +{ +return ckpt_write_obj_type (ctx,DUMMY_LSM_INFO , +strlen (DUMMY_LSM_INFO ),CKPT_HDR_LSM_INFO ); +} + +/* +* ckpt_snarf_lsm_info +* If there is a CKPT_HDR_LSM_INFO field, toss it. +* Used when the current LSM doesn't care about this field. +*/ +void ckpt_snarf_lsm_info (struct ckpt_ctx *ctx) +{ +struct ckpt_hdr *h; + + h =ckpt_read_buf_type (ctx,CKPT_LSM_INFO_LEN ,CKPT_HDR_LSM_INFO ); +if (!IS_ERR (h)) +ckpt_hdr_put (ctx, h); +}/* * Helpers to manage c/r contexts: allocated for each checkpoint and/or
include/linux/checkpoint.h +6 -1
@@ -10,7 +10,7 @@* distribution for more details. */ -#define CHECKPOINT_VERSION 3 +#define CHECKPOINT_VERSION 4/* checkpoint user flags */ #define CHECKPOINT_SUBTREE 0x1
@@ -19,6 +19,7 @@#define RESTART_TASKSELF 0x1#define RESTART_FROZEN 0x2#define RESTART_GHOST 0x4 +#define RESTART_KEEP_LSM 0x8#ifdef __KERNEL__#ifdef CONFIG_CHECKPOINT
@@ -48,7 +49,9 @@#define RESTART_USER_FLAGS \ (RESTART_TASKSELF | \ RESTART_FROZEN | \ + RESTART_KEEP_LSM | \ RESTART_GHOST) +#define CKPT_LSM_INFO_LEN 200 extern int walk_task_subtree(struct task_struct *task, int (*func)(struct task_struct *, void *),
@@ -62,6 +65,8 @@ extern void _ckpt_hdr_put(struct ckpt_ctx *ctx, void *ptr, int n);extern void ckpt_hdr_put (struct ckpt_ctx *ctx,void *ptr);extern void *ckpt_hdr_get (struct ckpt_ctx *ctx,int n);extern void *ckpt_hdr_get_type (struct ckpt_ctx *ctx,int n,int type); +extern int ckpt_write_dummy_lsm_info (struct ckpt_ctx *ctx); +extern void ckpt_snarf_lsm_info (struct ckpt_ctx *ctx);extern int ckpt_write_obj (struct ckpt_ctx *ctx,struct ckpt_hdr *h); extern int ckpt_write_obj_type(struct ckpt_ctx *ctx,
include/linux/checkpoint_hdr.h +16 -0
@@ -27,6 +27,15 @@#endif /* +* /usr/include/linux/security.h is not exported to userspace, so +* we need this value here for userspace restart.c to read. +* +* CHECKPOINT_LSM_NAME_MAX should be SECURITY_NAME_MAX +* security_may_restart() has a BUILD_BUG_ON to enforce that. +*/ +#define CHECKPOINT_LSM_NAME_MAX 10 + +/* * To maintain compatibility between 32-bit and 64-bit architecture flavors, * keep data 64-bit aligned: use padding for structure members, and use * __attribute__((aligned (8))) for the entire structure.
@@ -71,6 +80,8 @@ enum {#define CKPT_HDR_STRING CKPT_HDR_STRING CKPT_HDR_OBJREF,#define CKPT_HDR_OBJREF CKPT_HDR_OBJREF + CKPT_HDR_LSM_INFO, +#define CKPT_HDR_LSM_INFO CKPT_HDR_LSM_INFO CKPT_HDR_TREE = 101,#define CKPT_HDR_TREE CKPT_HDR_TREE
@@ -252,6 +263,11 @@ struct ckpt_const {/* container configuration section header */ struct ckpt_hdr_container {struct ckpt_hdr h; +/* +* the header is followed by the string: +* char lsm_name[SECURITY_NAME_MAX + 1] +* plus the CKPT_HDR_LSM_INFO section +*/ };/* checkpoint image header */
include/linux/checkpoint_types.h +2 -0
@@ -21,6 +21,7 @@#include <linux/fs.h> #include <linux/ktime.h> #include <linux/wait.h> +#include <linux/security.h> struct ckpt_stats {int uts_ns;
@@ -42,6 +43,7 @@ struct ckpt_ctx {struct task_struct *root_task;/* [container] root task */ struct nsproxy *root_nsproxy;/* [container] root nsproxy */ struct task_struct *root_freezer;/* [container] root task */ +char lsm_name[SECURITY_NAME_MAX +1 ];/* security module at ckpt */ unsigned long kflags;/* kerenl flags */ unsigned long uflags;/* user flags */
include/linux/security.h +58 -0
94 lines not on this page · raw message
security/capability.c +24 -0
@@ -792,6 +792,26 @@ static void cap_release_secctx(char *secdata, u32 seclen) { } +#ifdef CONFIG_CHECKPOINT +static int cap_may_restart (struct ckpt_ctx *ctx) +{ +/* +* Note that all construction of kernel resources, credentials, +* etc is already authorized per the caller's credentials. This +* hook is intended for the LSM to make further decisions about +* a task not being allowed to restart at all, for instance if +* the policy has changed since checkpoint. +*/ +ckpt_snarf_lsm_info (ctx); +return 0 ; +} + +static int cap_checkpoint_header (struct ckpt_ctx *ctx) +{ +return ckpt_write_dummy_lsm_info (ctx); +} +#endif +#ifdef CONFIG_KEYS static int cap_key_alloc (struct key *key,const struct cred *cred,unsigned long flags)
@@ -992,6 +1012,10 @@ void security_fixup_ops(struct security_operations *ops)set_to_cap_if_null (ops, secid_to_secctx);set_to_cap_if_null (ops, secctx_to_secid);set_to_cap_if_null (ops, release_secctx); +#ifdef CONFIG_CHECKPOINT +set_to_cap_if_null (ops, may_restart); +set_to_cap_if_null (ops, checkpoint_header); +#endif #ifdef CONFIG_SECURITY_NETWORK set_to_cap_if_null (ops, unix_stream_connect);set_to_cap_if_null (ops, unix_may_send);
security/security.c +26 -0
@@ -16,6 +16,9 @@#include <linux/init.h> #include <linux/kernel.h> #include <linux/security.h> +#ifdef CONFIG_CHECKPOINT +#include <linux/checkpoint.h> +#endif /* Boot-time LSM user choice */ static __initdata char chosen_lsm[SECURITY_NAME_MAX +1 ];
@@ -122,6 +125,11 @@ int register_security(struct security_operations *ops)return 0 ; } +char *security_get_lsm_name (void ) +{ +return security_ops->name; +} +/* Security operations */ int security_ptrace_may_access (struct task_struct *child,unsigned int mode)
@@ -959,6 +967,24 @@ void security_release_secctx(char *secdata, u32 seclen) }EXPORT_SYMBOL (security_release_secctx); +#ifdef CONFIG_CHECKPOINT +int security_may_restart (struct ckpt_ctx *ctx) +{ +/* +* SECURITY_NAME_MAX is defined in linux/security.h, +* CHECKPOINT_LSM_NAME_MAX in linux/checkpoint_hdr.h +*/ +BUILD_BUG_ON (CHECKPOINT_LSM_NAME_MAX !=SECURITY_NAME_MAX ); + +return security_ops->may_restart (ctx); +} + +int security_checkpoint_header (struct ckpt_ctx *ctx) +{ +return security_ops->checkpoint_header (ctx); +} +#endif +#ifdef CONFIG_SECURITY_NETWORK int security_unix_stream_connect(struct socket *sock, struct socket *other,
Signature · 1 line
1.6.1
A message that is not in the archive (sent off-list or not yet received): 20091015203721.GA5030-r/[email protected]
PATCH 1/1 restart: accept the lsm_name field in header and add -k flag (v2)
The checkpoint file header now has an 11-character string containing the name of the active LSM, following the uts info, and a variable length buffer type conaining LSM-specific version information (for instance a sha1sum of policy). Handle these.
Also add a -k (--keeplsm) flag to tell restart to set the RESTART_KEEP_LSM flag to sys_restart().
Changelog:
oct 15: separate out from container config section patch oct 05: 1. move keep_lsm into arg struct
2. read a separate container config section
3. use CHECKPOINT_LSM_NAME_MAX
--- restart.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 files changed, 37 insertions(+), 2 deletions(-)
restart.c +37 -2
@@ -68,6 +68,7 @@ static char usage_str[] =" --signal=SIG send SIG to root task on SIGINT (default: SIGKILL\n" " to container root, SIGINT otherwise)\n" " -w,--wait wait for root task to termiate (default)\n" +" -k,--keeplsm Try to recreate original LSM labels on all objects\n" " --show-status show exit status of root task (implies -w)\n" " --copy-status imitate exit status of root task (implies -w)\n" " -W,--no-wait do not wait for root task to terminate\n"
@@ -350,6 +351,7 @@ struct args {int copy_status;char *freezer;char *input; +int keep_lsm; };static void usage (char *str)
@@ -380,6 +382,7 @@ static void parse_args(struct args *args, int argc, char *argv[]) { "self", no_argument, NULL, 6}, { "signal", required_argument, NULL, 4 }, { "inspect", no_argument, NULL, 5 }, + { "keeplsm", no_argument, NULL, 'k' }, { "input", required_argument, NULL, 'i' }, { "root", required_argument, NULL, 'r' }, { "wait", no_argument, NULL, 'w' },
@@ -391,7 +394,7 @@ static void parse_args(struct args *args, int argc, char *argv[]) { "debug", no_argument, NULL, 'd' }, { NULL, 0, NULL, 0 } }; -static char optc[] ="hdvpPwWF:r:i:" ; +static char optc[] ="hdvpkPwWF:r:i:" ;int sig;
@@ -446,6 +449,9 @@ static void parse_args(struct args *args, int argc, char *argv[])case 'w' : args->wait =1 ;break ; +case 'k' : + args->keep_lsm =RESTART_KEEP_LSM ; +break ;case 'W' : args->wait =0 ;break ;
@@ -936,6 +942,7 @@ static int ckpt_coordinator(struct ckpt_ctx *ctx)if (ctx->args->freezer) flags |=RESTART_FROZEN ; + flags |= ctx->args->keep_lsm; ret =restart (root_pid,STDIN_FILENO , flags);if (ret <0 ) {
@@ -1584,6 +1591,8 @@ static int ckpt_make_tree(struct ckpt_ctx *ctx, struct task *task)if (task->flags & (TASK_GHOST |TASK_DEAD )) flags |=RESTART_GHOST ; + flags |= ctx->args->keep_lsm; +/* on success this doesn't return */ ckpt_dbg ("about to call sys_restart(), flags %#lx\n" , flags); ret =restart (0 ,STDIN_FILENO , flags);
@@ -2116,10 +2125,23 @@ static int ckpt_read_header_arch(struct ckpt_ctx *ctx)static int ckpt_read_container (struct ckpt_ctx *ctx) { +int ret;struct ckpt_hdr_container *h; +char *ptr; h = (struct ckpt_hdr_container *) ctx->container; -return ckpt_read_obj_type (ctx, h,sizeof (*h),CKPT_HDR_CONTAINER ); + ret =ckpt_read_obj_type (ctx, h,sizeof (*h),CKPT_HDR_CONTAINER ); +if (ret <0 ) +return ret; + + ptr = (char *) h; + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_read_obj_buffer (ctx, ptr,CHECKPOINT_LSM_NAME_MAX +1 ); +if (ret <0 ) +return ret; + + ptr += ((struct ckpt_hdr *) ptr)->len; +return ckpt_read_obj_type (ctx, ptr,200 ,CKPT_HDR_LSM_INFO ); }static int ckpt_read_tree (struct ckpt_ctx *ctx)
@@ -2197,9 +2219,22 @@ static int ckpt_write_header_arch(struct ckpt_ctx *ctx)static int ckpt_write_container (struct ckpt_ctx *ctx) {char *ptr; +int ret; ptr = (char *) ctx->container;/* write the container info section */ + ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); +if (ret <0 ) +return ret; + +/* write the lsm name buffer */ + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); +if (ret <0 ) +return ret; + +/* write the lsm policy section */ + ptr += ((struct ckpt_hdr *) ptr)->len;return ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); }
Signature · 1 line
1.6.1.1