cr: add generic LSM c/r support (v4)
Subsystems (5)
PATCH 1/3 cr: add generic LSM c/r support (v4)
(wasn't versioning the patchsets before, so randomly pick 4 as the version for this patchset...)
Documentation/checkpoint/readme.txt begins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""
This patch adds generic support for c/r of LSM credentials. Support for Smack and SELinux (and TOMOYO if appropriate) will be added later. Capabilities is already supported through generic creds code.
This patch supports ipc_perm, msg_msg, cred (task) and file ->security fields. Inodes, superblocks, netif, and xfrm currently are restored not through sys_restart() but through container creation, and so the security fields should be done then as well. Network should be added when network c/r is added.
Briefly, all security fields must be exported by the LSM as a simple null-terminated string. They are checkpointed through the security_checkpoint_obj() helper, because we must pass it an extra sectype field. Splitting SECURITY_OBJ_SEC into one type per object type would not work because, in Smack, one void* security is used for all object types. But we must pass the sectype field because in SELinux a different type of structure is stashed in each object type.
The RESTART_KEEP_LSM flag indicates that the LSM should attempt to reuse checkpointed security labels. It is always invalid when the LSM at restart differs from that at checkpoint. It is currently only usable for capabilities.
(For capabilities, restart without RESTART_KEEP_LSM is technically not implemented. There actually might be a use case for that, but the safety of it is dubious so for now we always re-create checkpointed capability sets whether RESTART_KEEP_LSM is specified or not)
The result of applying this patchset can be seen at
http://git.kernel.org/gitweb.cgi?p=linux/kernel/git/sergeh/linux-cr.git;a=shortlog;h=ckpt-v18-hallyn.lsm3
Changelog:
sep 3: fix memory leak on LSM restore error path
Sep 3: provide 2 hooks, may_restart and checkpoint_header, to facilitate
an LSM tracking policy changes.
sep 10: merge RESTART_KEEP_LSM patch with basic LSM c/r
support patches.
sep 10: rename security_xyz_get_ctx() to security_xyz_checkpoint(),
in order to avoid confusing with the various other 'context' helpers in the security_ namespace, relating to secids and sysfs xattrs.
sep 10: pass context file to security_cred_restore. SELinux will
want the file's security context to authorize it as an entrypoint for the new process context.
oct 01: roll up some generic c/r debug hunks from selinux patch.
--- Documentation/checkpoint/readme.txt | 25 +++++ checkpoint/checkpoint.c | 11 ++ checkpoint/files.c | 34 +++++++ checkpoint/objhash.c | 93 +++++++++++++++++ checkpoint/process.c | 20 +++- checkpoint/restart.c | 25 +++++ checkpoint/sys.c | 22 ++++ include/linux/checkpoint.h | 7 +- include/linux/checkpoint_hdr.h | 24 +++++- include/linux/checkpoint_types.h | 9 ++ include/linux/security.h | 188 +++++++++++++++++++++++++++++++++++ ipc/checkpoint.c | 34 +++++-- ipc/checkpoint_msg.c | 26 +++++- ipc/checkpoint_sem.c | 4 +- ipc/checkpoint_shm.c | 4 +- ipc/util.h | 6 +- kernel/cred.c | 20 ++++- security/capability.c | 74 ++++++++++++++ security/security.c | 131 ++++++++++++++++++++++++ 19 files changed, 731 insertions(+), 26 deletions(-)
Documentation/checkpoint/readme.txt +25 -0
@@ -333,6 +333,31 @@ So that's why we don't want CAP_SYS_ADMIN required up-front. That way we will be forced to more carefully review each of those features. However, this can be controlled with a sysctl-variable. +LSM +=== + +Security modules use custom labels on subjects and objects to +further mediate access decisions beyond DAC controls. When +checkpoint applications, these labels are [ work in progress ] +checkpointed along with the objects. At restart, the +RESTART_KEEP_LSM flag tells the kernel whether re-created objects +whould keep their checkpointed labels, or get automatically +recalculated labels. Since checkpointed labels will only make +sense to the same LSM which was active at checkpoint time, +sys_restart() with the RESTART_KEEP_LSM flag will fail with +-EINVAL if the LSM active at restart is not the same as that +active at checkpoint. If RESTART_KEEP_LSM is not specified, +then objects will be given whatever default labels the LSM and +their optional policy decide. Of course, when RESTART_KEEP_LSM +is specified, the LSM may choose a different label than the +checkpointed one, or fail the entire restart if the caller +does not have permission to create objects with the checkpointed +label. + +It should always be safe to take a checkpoint of an application +under LSM_1, and restart it without the RESTART_KEEP_LSM flag +under LSM_2. + Kernel interfaces =================
checkpoint/checkpoint.c +11 -0
@@ -25,6 +25,7 @@#include <linux/magic.h> #include <linux/hrtimer.h> #include <linux/deferqueue.h> +#include <linux/security.h> #include <linux/checkpoint.h> #include <linux/checkpoint_hdr.h>
@@ -351,6 +352,16 @@ static int checkpoint_write_header(struct ckpt_ctx *ctx)if (ret <0 )return ret; +memset (ctx->lsm_name,0 ,SECURITY_NAME_MAX +1 ); +strlcpy (ctx->lsm_name,security_get_lsm_name (),SECURITY_NAME_MAX +1 ); + ret =ckpt_write_buffer (ctx, ctx->lsm_name,SECURITY_NAME_MAX +1 ); +if (ret <0 ) +return ret; + + ret =security_checkpoint_header (ctx); +if (ret <0 ) +return ret; +return checkpoint_write_header_arch (ctx); }
checkpoint/files.c +34 -0
@@ -145,6 +145,19 @@ static int scan_fds(struct files_struct *files, int **fdtable)return n; } +#ifdef CONFIG_SECURITY +int checkpoint_file_security (struct ckpt_ctx *ctx,struct file *file) +{ +return security_checkpoint_obj (ctx, file->f_security, +CKPT_SECURITY_FILE ); +} +#else +int checkpoint_file_security (struct ckpt_ctx *ctx,struct file *file) +{ +return -EOPNOTSUPP ; +} +#endif +int checkpoint_file_common (struct ckpt_ctx *ctx,struct file *file,struct ckpt_hdr_file *h) {
@@ -159,6 +172,16 @@ int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file,if (h->f_credref <0 )return h->f_credref; + h->f_secref =checkpoint_file_security (ctx, file); +if (h->f_secref == -EOPNOTSUPP ) + h->f_secref =-1 ; +else if (h->f_secref <0 ) +return h->f_secref; + +ckpt_debug ("file %s credref %d secref %d" , + file->f_dentry->d_name.name, h->f_credref, + h->f_secref); +/* FIX: need also file->f_owner, etc */ return 0 ;
@@ -507,6 +530,17 @@ int restore_file_common(struct ckpt_ctx *ctx, struct file *file,put_cred (file->f_cred); file->f_cred =get_cred (cred); +if ((ctx->uflags &RESTART_KEEP_LSM ) && (h->f_secref !=-1 )) { +struct ckpt_stored_lsm *l =ckpt_obj_fetch (ctx, h->f_secref, +CKPT_OBJ_SEC ); +if (IS_ERR (l)) +return PTR_ERR (l); + + ret =security_file_restore (file, l->string); +if (ret) +return ret; + } +/* 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 )
checkpoint/objhash.c +93 -0
111 lines not on this page · raw message
checkpoint/process.c +16 -4
@@ -581,11 +581,15 @@ static int restore_task_creds(struct ckpt_ctx *ctx) realcred =ckpt_obj_fetch (ctx, h->cred_ref,CKPT_OBJ_CRED );if (IS_ERR (realcred)) { +ckpt_debug ("Error %ld fetching readlcred (ref %d)" , +PTR_ERR (realcred), h->cred_ref); ret =PTR_ERR (realcred); goto out; } ecred =ckpt_obj_fetch (ctx, h->ecred_ref,CKPT_OBJ_CRED );if (IS_ERR (ecred)) { +ckpt_debug ("Error %ld fetching ecred (ref %d)" , +PTR_ERR (ecred), h->ecred_ref); ret =PTR_ERR (ecred); goto out; }
@@ -593,6 +597,7 @@ static int restore_task_creds(struct ckpt_ctx *ctx) ctx->ecred = ecred; out: +ckpt_debug ("Returning %d." , ret);ckpt_hdr_put (ctx, h);return ret; }
@@ -608,14 +613,21 @@ static int restore_task_objs(struct ckpt_ctx *ctx)* referenced. See comment in checkpoint_task_objs. */ ret =restore_task_creds (ctx); -if (!ret) - ret =restore_task_ns (ctx); -if (ret <0 ) +if (ret) { +ckpt_debug ("restore_task_creds returned %d" , ret); +return ret; + } + ret =restore_task_ns (ctx); +if (ret) { +ckpt_debug ("restore_task_ns returned %d" , ret);return ret; + } h =ckpt_read_obj_type (ctx,sizeof (*h),CKPT_HDR_TASK_OBJS ); -if (IS_ERR (h)) +if (IS_ERR (h)) { +ckpt_debug ("Error fetching task obj" );return PTR_ERR (h); + } ret =restore_obj_file_table (ctx, h->files_objref);ckpt_debug ("file_table: ret %d (%p)\n" , ret, current->files);
checkpoint/restart.c +25 -0
@@ -457,6 +457,31 @@ static int restore_read_header(struct ckpt_ctx *ctx)if (ret <0 ) goto out; + ret =_ckpt_read_buffer (ctx, ctx->lsm_name,SECURITY_NAME_MAX +1 ); +if (ret <0 ) + goto out; +if (ctx->uflags &RESTART_KEEP_LSM ) { +char *cur =security_get_lsm_name (); +if (strncmp (cur, ctx->lsm_name,SECURITY_NAME_MAX +1 ) !=0 ) { +pr_warning ("c/r: checkpointed LSM %s, current is %s.\n" , + ctx->lsm_name, cur); + ret = -EINVAL ; + goto out; + } +/* to be implemented later, per-lsm */ +if (strcmp (ctx->lsm_name,"lsm_none" ) !=0 && +strcmp (ctx->lsm_name,"default" ) !=0 ) { +pr_warning ("c/r: RESTART_KEEP_LSM unsupported for %s\n" , + ctx->lsm_name); + ret = -ENOSYS ; + goto out; + } + } + + ret =security_may_restart (ctx); +if (ret <0 ) + goto out; + ret =restore_read_header_arch (ctx); out:kfree (uts);
checkpoint/sys.c +22 -0
@@ -169,6 +169,28 @@ 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 2 +#define CHECKPOINT_VERSION 3/* 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 +23 -1
@@ -58,6 +58,8 @@ enum {CKPT_HDR_BUFFER ,CKPT_HDR_STRING ,CKPT_HDR_OBJREF , +CKPT_HDR_SEC , +CKPT_HDR_LSM_INFO ,CKPT_HDR_TREE =101 , CKPT_HDR_TASK,
@@ -146,6 +148,7 @@ enum obj_type {CKPT_OBJ_GROUPINFO ,CKPT_OBJ_SOCK ,CKPT_OBJ_TTY , +CKPT_OBJ_SEC , CKPT_OBJ_MAX };
@@ -189,10 +192,11 @@ struct ckpt_hdr_header {__u64 uflags;/* uflags from checkpoint */ /* -* the header is followed by three strings: +* the header is followed by four strings: * char release[const.uts_release_len]; * char version[const.uts_version_len]; * char machine[const.uts_machine_len]; +* char lsm_name[SECURITY_NAME_MAX + 1] */ } __attribute__((aligned(8)));
@@ -265,6 +269,8 @@ struct ckpt_hdr_cred {__u32 gid, sgid, egid, fsgid;__s32 user_ref;__s32 groupinfo_ref; +__s32 sec_ref; +__u32 padding;struct ckpt_capabilities cap_s; } __attribute__((aligned(8)));
@@ -277,6 +283,16 @@ struct ckpt_hdr_groupinfo {__u32 groups[0 ]; } __attribute__((aligned(8))); +struct ckpt_hdr_lsm { +struct ckpt_hdr h; +__u8 sectype; +__u16 len; +/* +* This is followed by a string of size len+1, +* null-terminated +*/ +__u8 string[0 ]; +} __attribute__((aligned (8 )));/* * todo - keyrings and LSM * These may be better done with userspace help though
@@ -392,6 +408,8 @@ struct ckpt_hdr_file {__s32 f_credref;__u64 f_pos;__u64 f_version; +__s32 f_secref; +__u32 f_padding; } __attribute__((aligned(8)));struct ckpt_hdr_file_generic {
@@ -634,6 +652,8 @@ struct ckpt_hdr_ipc_perms {__u32 mode;__u32 _padding;__u64 seq; +__s32 sec_ref; +__u32 padding; } __attribute__((aligned(8)));struct ckpt_hdr_ipc_shm {
@@ -667,6 +687,8 @@ struct ckpt_hdr_ipc_msg_msg {struct ckpt_hdr h;__s32 m_type;__u32 m_ts; +__s32 sec_ref; +__u32 padding; } __attribute__((aligned(8)));struct ckpt_hdr_ipc_sem {
include/linux/checkpoint_types.h +9 -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 */
@@ -82,6 +84,13 @@ struct ckpt_ctx {struct ckpt_stats stats;/* statistics */ }; +/* stored on hashtable */ +struct ckpt_stored_lsm { +struct kref kref; +int sectype; +char *string; +}; +#endif /* __KERNEL__ */ #endif /* _LINUX_CHECKPOINT_TYPES_H_ */
include/linux/security.h +188 -0
315 lines not on this page · raw message
ipc/checkpoint.c +24 -10
@@ -31,7 +31,8 @@ static char *ipc_ind_to_str[] = { "sem", "msg", "shm" };* Checkpoint */ -int checkpoint_fill_ipc_perms (struct ckpt_hdr_ipc_perms *h, +int checkpoint_fill_ipc_perms (struct ckpt_ctx *ctx, +struct ckpt_hdr_ipc_perms *h,struct kern_ipc_perm *perm) {if (ipcperms (perm,S_IROTH ))
@@ -45,6 +46,15 @@ int checkpoint_fill_ipc_perms(struct ckpt_hdr_ipc_perms *h, h->cgid = perm->cgid; h->mode = perm->mode &S_IRWXUGO ; h->seq = perm->seq; +if (perm->security) { + h->sec_ref =security_checkpoint_obj (ctx, perm->security, +CKPT_SECURITY_IPC ); +if (h->sec_ref == -EOPNOTSUPP ) + h->sec_ref =-1 ; +else if (h->sec_ref <0 ) +return h->sec_ref; + }else + h->sec_ref =-1 ;return 0 ; }
@@ -176,7 +186,8 @@ static int validate_created_perms(struct ckpt_hdr_ipc_perms *h)return 1 ; } -int restore_load_ipc_perms (struct ckpt_hdr_ipc_perms *h, +int restore_load_ipc_perms (struct ckpt_ctx *ctx, +struct ckpt_hdr_ipc_perms *h,struct kern_ipc_perm *perm) {if (h->id <0 )
@@ -205,14 +216,17 @@ int restore_load_ipc_perms(struct ckpt_hdr_ipc_perms *h, perm->cgid = h->cgid; perm->mode = h->mode; perm->seq = h->seq; -/* -* Todo: restore perm->security. -* At the moment it gets set by security_x_alloc() called through -* ipcget()->ipcget_public()->ops-.getnew (->nequeue for instance) -* We will want to ask the LSM to consider resetting the -* checkpointed ->security, based on current_security(), -* the checkpointed ->security, and the checkpoint file context. -*/ + +if ((ctx->uflags &RESTART_KEEP_LSM ) && (h->sec_ref !=-1 )) { +int ret; +struct ckpt_stored_lsm *l =ckpt_obj_fetch (ctx, h->sec_ref, +CKPT_OBJ_SEC ); +if (IS_ERR (l)) +return PTR_ERR (l); + ret =security_ipc_restore (perm, l->string); +if (ret) +return ret; + }return 0 ; }
ipc/checkpoint_msg.c +23 -3
@@ -37,7 +37,7 @@ static int fill_ipc_msg_hdr(struct ckpt_ctx *ctx,ipc_lock_by_ptr (&msq->q_perm); - ret =checkpoint_fill_ipc_perms (&h->perms, &msq->q_perm); + ret =checkpoint_fill_ipc_perms (ctx, &h->perms, &msq->q_perm);if (ret <0 ) goto unlock;
@@ -64,13 +64,23 @@ static int checkpoint_msg_contents(struct ckpt_ctx *ctx, struct msg_msg *msg)struct msg_msgseg *seg;int total, len;int ret; - +int sec_ref =-1 ; + +if (msg->security) { + sec_ref =security_checkpoint_obj (ctx, msg->security, +CKPT_SECURITY_MSG_MSG ); +if (sec_ref == -EOPNOTSUPP ) + sec_ref =-1 ; +else if (sec_ref <0 ) +return sec_ref; + } h =ckpt_hdr_get_type (ctx,sizeof (*h),CKPT_HDR_IPC_MSG_MSG );if (!h)return -ENOMEM ; h->m_type = msg->m_type; h->m_ts = msg->m_ts; + h->sec_ref = sec_ref; ret =ckpt_write_obj (ctx, &h->h);ckpt_hdr_put (ctx, h);
@@ -177,7 +187,7 @@ static int load_ipc_msg_hdr(struct ckpt_ctx *ctx, {int ret =0 ; - ret =restore_load_ipc_perms (&h->perms, &msq->q_perm); + ret =restore_load_ipc_perms (ctx, &h->perms, &msq->q_perm);if (ret <0 )return ret;
@@ -224,6 +234,16 @@ static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen) msg->next =NULL ; pseg = &msg->next; +if ((ctx->uflags &RESTART_KEEP_LSM ) && (h->sec_ref !=-1 )) { +struct ckpt_stored_lsm *l =ckpt_obj_fetch (ctx, h->sec_ref, +CKPT_OBJ_SEC ); +if (IS_ERR (l)) +return (struct msg_msg *)l; + ret =security_msg_msg_restore (msg, l->string); +if (ret) +return ERR_PTR (ret); + } + ret =_ckpt_read_buffer (ctx, (msg +1 ), len);if (ret <0 ) goto out;
ipc/checkpoint_sem.c +2 -2
@@ -37,7 +37,7 @@ static int fill_ipc_sem_hdr(struct ckpt_ctx *ctx,ipc_lock_by_ptr (&sem->sem_perm); - ret =checkpoint_fill_ipc_perms (&h->perms, &sem->sem_perm); + ret =checkpoint_fill_ipc_perms (ctx, &h->perms, &sem->sem_perm);if (ret <0 ) goto unlock;
@@ -113,7 +113,7 @@ static int load_ipc_sem_hdr(struct ckpt_ctx *ctx, {int ret =0 ; - ret =restore_load_ipc_perms (&h->perms, &sem->sem_perm); + ret =restore_load_ipc_perms (ctx, &h->perms, &sem->sem_perm);if (ret <0 )return ret;
ipc/checkpoint_shm.c +2 -2
@@ -41,7 +41,7 @@ static int fill_ipc_shm_hdr(struct ckpt_ctx *ctx,ipc_lock_by_ptr (&shp->shm_perm); - ret =checkpoint_fill_ipc_perms (&h->perms, &shp->shm_perm); + ret =checkpoint_fill_ipc_perms (ctx, &h->perms, &shp->shm_perm);if (ret <0 ) goto unlock;
@@ -165,7 +165,7 @@ static int load_ipc_shm_hdr(struct ckpt_ctx *ctx, {int ret; - ret =restore_load_ipc_perms (&h->perms, &shp->shm_perm); + ret =restore_load_ipc_perms (ctx, &h->perms, &shp->shm_perm);if (ret <0 )return ret;
ipc/util.h +4 -2
@@ -199,9 +199,11 @@ void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp);#ifdef CONFIG_CHECKPOINT -extern int checkpoint_fill_ipc_perms (struct ckpt_hdr_ipc_perms *h, +extern int checkpoint_fill_ipc_perms (struct ckpt_ctx *ctx, +struct ckpt_hdr_ipc_perms *h,struct kern_ipc_perm *perm); -extern int restore_load_ipc_perms (struct ckpt_hdr_ipc_perms *h, +extern int restore_load_ipc_perms (struct ckpt_ctx *ctx, +struct ckpt_hdr_ipc_perms *h,struct kern_ipc_perm *perm);extern int ckpt_collect_ipc_shm (int id,void *p,void *data);
kernel/cred.c +19 -1
@@ -709,7 +709,7 @@ int cred_setfsgid(struct cred *new, gid_t gid, gid_t *old_fsgid)static int do_checkpoint_cred (struct ckpt_ctx *ctx,struct cred *cred) {int ret; -int groupinfo_ref, user_ref; +int groupinfo_ref, user_ref, sec_ref =-1 ;struct ckpt_hdr_cred *h; groupinfo_ref = checkpoint_obj(ctx, cred->group_info,
@@ -719,6 +719,14 @@ static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred) user_ref =checkpoint_obj (ctx, cred->user,CKPT_OBJ_USER );if (user_ref <0 )return user_ref; +#ifdef CONFIG_SECURITY + sec_ref =security_checkpoint_obj (ctx, cred->security, +CKPT_SECURITY_CRED ); +if (sec_ref == -EOPNOTSUPP ) + sec_ref =-1 ; +else if (sec_ref <0 ) +return sec_ref; +#endif /* else cred->security doesn't exist and sec_ref = -1 */ h =ckpt_hdr_get_type (ctx,sizeof (*h),CKPT_HDR_CRED );if (!h)
@@ -733,6 +741,7 @@ static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred) h->sgid = cred->sgid; h->egid = cred->egid; h->fsgid = cred->fsgid; + h->sec_ref = sec_ref;checkpoint_capabilities (&h->cap_s, cred);
@@ -806,6 +815,15 @@ static struct cred *do_restore_cred(struct ckpt_ctx *ctx) ret =cred_setfsgid (cred, h->fsgid, &oldgid);if (oldgid != h->fsgid && ret <0 ) goto err_putcred; +if ((ctx->uflags &RESTART_KEEP_LSM ) && (h->sec_ref !=-1 )) { +struct ckpt_stored_lsm *l =ckpt_obj_fetch (ctx, h->sec_ref, +CKPT_OBJ_SEC ); +if (IS_ERR (l)) +return (struct cred *)l; + ret =security_cred_restore (ctx->file, cred, l->string); +if (ret) + goto err_putcred; + } ret =restore_capabilities (&h->cap_s, cred);if (ret) goto err_putcred;
security/capability.c +74 -0
128 lines not on this page · raw message
security/security.c +131 -0
169 lines not on this page · raw message
Signature · 1 line
1.6.1
A message that is not in the archive (sent off-list or not yet received): 20091002034916.GA16871-r/[email protected]
PATCH 1/1 restart: accept the lsm_name field in header and add -k flag
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().
--- restart.c | 32 +++++++++++++++++++++++++++++++- 1 files changed, 31 insertions(+), 1 deletions(-)
restart.c +31 -1
@@ -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"
@@ -349,6 +350,8 @@ struct args {char *input; }; +int keep_lsm; +static void usage (char *str) {fprintf (stderr,"%s" , str);
@@ -377,6 +380,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' },
@@ -388,7 +392,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;
@@ -443,6 +447,9 @@ static void parse_args(struct args *args, int argc, char *argv[])case 'w' : args->wait =1 ;break ; +case 'k' : + keep_lsm =RESTART_KEEP_LSM ; +break ;case 'W' : args->wait =0 ;break ;
@@ -927,6 +934,7 @@ static int ckpt_coordinator(struct ckpt_ctx *ctx)if (ctx->args->freezer) flags |=RESTART_FROZEN ; + flags |= keep_lsm; ret =restart (root_pid,STDIN_FILENO , flags);if (ret <0 ) {
@@ -1581,6 +1589,7 @@ static int ckpt_make_tree(struct ckpt_ctx *ctx, struct task *task)if (task->flags & (TASK_GHOST |TASK_DEAD )) flags |=RESTART_GHOST ; + flags |= 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);
@@ -2057,6 +2066,7 @@ static int ckpt_read_obj_buffer(struct ckpt_ctx *ctx, void *buf, int n)* read/write the checkpoint image: similar to in-kernel code */ +#define SECURITY_NAME_MAX 20static int ckpt_read_header (struct ckpt_ctx *ctx) {struct ckpt_hdr_header *h;
@@ -2090,6 +2100,16 @@ static int ckpt_read_header(struct ckpt_ctx *ctx)if (ret <0 )return ret; + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_read_obj_buffer (ctx, ptr,SECURITY_NAME_MAX +1 ); +if (ret <0 ) +return ret; + + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_read_obj_type (ctx, ptr,200 ,CKPT_HDR_LSM_INFO ); +if (ret <0 ) +return ret; +/* FIXME: skip version validation for now */ return 0 ;
@@ -2169,6 +2189,16 @@ static int ckpt_write_header(struct ckpt_ctx *ctx) ptr += ((struct ckpt_hdr *) ptr)->len; ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); +if (ret <0 ) +return ret; + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); +if (ret <0 ) +return ret; + + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); +return ret; }
Signature · 1 line
1.6.1.1
A message that is not in the archive (sent off-list or not yet received): 20091002035157.GA16920-r/[email protected]
Oren Laadan
Acked-byRe: [PATCH 1/1] restart: accept the lsm_name field in header and add -k flag
Quoted 10 lines · Serge E. Hallyn
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_LSMflag tosys_restart().Signed-off-by Serge E. Hallyn <serue-r/[email protected]>
A couple of comments below. Otherwise:
Quoted 17 lines
--- restart.c | 32 +++++++++++++++++++++++++++++++- 1 files changed, 31 insertions(+), 1 deletions(-)restart.c +1
-0@@ -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"
restart.c struct args { · line 353
Quoted 4 lines
restart.c +1
-0@@ -349,6 +350,8 @@ struct args {char *input; }; +int keep_lsm;
Can you please use 'struct args' for this ?
Quoted 48 lines
restart.c +8
-1+static void usage (char *str) {fprintf (stderr,"%s" , str);@@ -377,6 +380,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' },@@ -388,7 +392,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;@@ -443,6 +447,9 @@ static void parse_args(struct args *args, int argc, char *argv[])case 'w' : args->wait =1 ;break ; +case 'k' : + keep_lsm =RESTART_KEEP_LSM ; +break ;case 'W' : args->wait =0 ;break ;@@ -927,6 +934,7 @@ static int ckpt_coordinator(struct ckpt_ctx *ctx)if (ctx->args->freezer) flags |=RESTART_FROZEN ; + flags |= keep_lsm; ret =restart (root_pid,STDIN_FILENO , flags);if (ret <0 ) {@@ -1581,6 +1589,7 @@ static int ckpt_make_tree(struct ckpt_ctx *ctx, struct task *task)if (task->flags & (TASK_GHOST |TASK_DEAD )) flags |=RESTART_GHOST ; + flags |= 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);
restart.c static int ckpt_read_obj_buffer(struct ckpt_ctx *ctx, void *buf, int n) · line 2069
Quoted 4 lines
restart.c +1
-0@@ -2057,6 +2066,7 @@ static int ckpt_read_obj_buffer(struct ckpt_ctx *ctx, void *buf, int n)* read/write the checkpoint image: similar to in-kernel code */ +#define SECURITY_NAME_MAX 20
Why is this ? if it's kernel ABI then define in checkpoint_hdr.h, or include suitable header.
Quoted 37 lines
restart.c +20
-0static int ckpt_read_header (struct ckpt_ctx *ctx) {struct ckpt_hdr_header *h;@@ -2090,6 +2100,16 @@ static int ckpt_read_header(struct ckpt_ctx *ctx)if (ret <0 )return ret; + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_read_obj_buffer (ctx, ptr,SECURITY_NAME_MAX +1 ); +if (ret <0 ) +return ret; + + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_read_obj_type (ctx, ptr,200 ,CKPT_HDR_LSM_INFO ); +if (ret <0 ) +return ret; +/* FIXME: skip version validation for now */ return 0 ;@@ -2169,6 +2189,16 @@ static int ckpt_write_header(struct ckpt_ctx *ctx) ptr += ((struct ckpt_hdr *) ptr)->len; ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); +if (ret <0 ) +return ret; + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); +if (ret <0 ) +return ret; + + ptr += ((struct ckpt_hdr *) ptr)->len; + ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) ptr); +return ret; }
Quoted 10 lines · Serge E. Hallyn
(wasn't versioning the patchsets before, so randomly pick 4 as the version for this patchset...)
Documentation/checkpoint/readme.txtbegins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""
[...]
Quoted 18 lines
Kernel interfaces
=================checkpoint/checkpoint.c +1
-0@@ -25,6 +25,7 @@#include <linux/magic.h> #include <linux/hrtimer.h> #include <linux/deferqueue.h> +#include <linux/security.h> #include <linux/checkpoint.h> #include <linux/checkpoint_hdr.h> @@ -351,6 +352,16 @@ static int checkpoint_write_header(struct ckpt_ctx *ctx)if (ret <0 )return ret;
checkpoint/checkpoint.c static int checkpoint_write_header(struct ckpt_ctx *ctx) · line 364
Quoted 10 lines
checkpoint/checkpoint.c +10
-0+memset (ctx->lsm_name,0 ,SECURITY_NAME_MAX +1 ); +strlcpy (ctx->lsm_name,security_get_lsm_name (),SECURITY_NAME_MAX +1 ); + ret =ckpt_write_buffer (ctx, ctx->lsm_name,SECURITY_NAME_MAX +1 ); +if (ret <0 ) +return ret; + + ret =security_checkpoint_header (ctx); +if (ret <0 ) +return ret; +
This is actually a case for a 'container-global' section that would appear after the header and before the rest of the image. (Would be useful also for network namespaces).
Quoted 28 lines
checkpoint/checkpoint.c +0
-0return checkpoint_write_header_arch (ctx); }checkpoint/files.c +13
-0@@ -145,6 +145,19 @@ static int scan_fds(struct files_struct *files, int **fdtable)return n; } +#ifdef CONFIG_SECURITY +int checkpoint_file_security (struct ckpt_ctx *ctx,struct file *file) +{ +return security_checkpoint_obj (ctx, file->f_security, +CKPT_SECURITY_FILE ); +} +#else +int checkpoint_file_security (struct ckpt_ctx *ctx,struct file *file) +{ +return -EOPNOTSUPP ; +} +#endif +int checkpoint_file_common (struct ckpt_ctx *ctx,struct file *file,struct ckpt_hdr_file *h) {
checkpoint/files.c int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file, · line 177
Quoted 6 lines
checkpoint/files.c +3
-0@@ -159,6 +172,16 @@ int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file,if (h->f_credref <0 )return h->f_credref; + h->f_secref =checkpoint_file_security (ctx, file); +if (h->f_secref == -EOPNOTSUPP ) + h->f_secref =-1 ;
#define CKPT_SECURITY_NONE -1 ??
Quoted 2 lines
checkpoint/files.c +2
-0+else if (h->f_secref <0 ) +return h->f_secref;
[...]
checkpoint/files.c
Quoted 10 lines
checkpoint/files.c +10
-0+ +static int do_checkpoint_security (struct ckpt_ctx *ctx, +const struct ckpt_stored_lsm *l) +{ +int ret, len; +struct ckpt_hdr_lsm *h; + + len =strlen (l->string); +if (len >PAGE_SIZE -sizeof (*h)) +return -E2BIG ;
A call to ckpt_write_err() here may be useful.
Quoted 17 lines
checkpoint/files.c +17
-0+ h =ckpt_hdr_get_type (ctx,sizeof (*h)+len+1 ,CKPT_HDR_SEC ); +if (!h) +return -ENOMEM ; + h->len = len; + h->sectype = l->sectype; +strncpy (h->string, l->string, len); + h->string[len] ='\0' ; + ret =ckpt_write_obj (ctx, &h->h); +ckpt_hdr_put (ctx, h); +return ret; +} + +static int checkpoint_security (struct ckpt_ctx *ctx,void *ptr) +{ +return do_checkpoint_security (ctx, (struct ckpt_stored_lsm *) ptr); +} +
checkpoint/files.c
Quoted 10 lines
checkpoint/files.c +10
-0+static struct ckpt_stored_lsm *do_restore_security (struct ckpt_ctx *ctx) +{ +struct ckpt_hdr_lsm *h; +struct ckpt_stored_lsm *l; + + h =ckpt_read_buf_type (ctx,PAGE_SIZE ,CKPT_HDR_SEC ); +if (IS_ERR (h)) +return (struct ckpt_stored_lsm *)h; +if (h->len > h->h.len -sizeof (struct ckpt_hdr ) || + h->len >PAGE_SIZE ) {
The second test (for h->len > PAGE_SIZE) is unnecessary - already done in ckpt_read_buf_type()
checkpoint/files.c
Quoted 7 lines
checkpoint/files.c +7
-0+ckpt_hdr_put (ctx, h); +return ERR_PTR (-EINVAL ); + } + l =kzalloc (sizeof (*l),GFP_KERNEL ); +if (!l) { +ckpt_hdr_put (ctx, h); +return ERR_PTR (-ENOMEM );
Nit: this part is common... set ret = -ENOMEM and use goto ?
[...]
checkpoint/files.c static int restore_task_objs(struct ckpt_ctx *ctx) · line 616
Quoted 8 lines
checkpoint/files.c +1
-3@@ -608,14 +613,21 @@ static int restore_task_objs(struct ckpt_ctx *ctx)* referenced. See comment in checkpoint_task_objs. */ ret =restore_task_creds (ctx); -if (!ret) - ret =restore_task_ns (ctx); -if (ret <0 ) +if (ret) {
Nit: (ret < 0) helps (me) read it.
Quoted 25 lines
checkpoint/files.c +10
-1+ckpt_debug ("restore_task_creds returned %d" , ret); +return ret; + } + ret =restore_task_ns (ctx); +if (ret) { +ckpt_debug ("restore_task_ns returned %d" , ret);return ret; + } h =ckpt_read_obj_type (ctx,sizeof (*h),CKPT_HDR_TASK_OBJS ); -if (IS_ERR (h)) +if (IS_ERR (h)) { +ckpt_debug ("Error fetching task obj" );return PTR_ERR (h); + } ret =restore_obj_file_table (ctx, h->files_objref);ckpt_debug ("file_table: ret %d (%p)\n" , ret, current->files);checkpoint/restart.c +0
-0@@ -457,6 +457,31 @@ static int restore_read_header(struct ckpt_ctx *ctx)if (ret <0 ) goto out;
checkpoint/restart.c static int restore_read_header(struct ckpt_ctx *ctx) · line 468
Quoted 10 lines
checkpoint/restart.c +9
-0+ ret =_ckpt_read_buffer (ctx, ctx->lsm_name,SECURITY_NAME_MAX +1 ); +if (ret <0 ) + goto out; +if (ctx->uflags &RESTART_KEEP_LSM ) { +char *cur =security_get_lsm_name (); +if (strncmp (cur, ctx->lsm_name,SECURITY_NAME_MAX +1 ) !=0 ) { +pr_warning ("c/r: checkpointed LSM %s, current is %s.\n" , + ctx->lsm_name, cur); + ret = -EINVAL ;
EPERM ?
[...]
checkpoint/restart.c struct ckpt_hdr_groupinfo { · line 289
Quoted 8 lines
checkpoint/restart.c +4
-0@@ -277,6 +283,16 @@ struct ckpt_hdr_groupinfo {__u32 groups[0 ]; } __attribute__((aligned(8))); +struct ckpt_hdr_lsm { +struct ckpt_hdr h; +__u8 sectype; +__u16 len;
Alignment ...
Quoted 10 lines
checkpoint/restart.c +6
-0+/* +* This is followed by a string of size len+1, +* null-terminated +*/ +__u8 string[0 ]; +} __attribute__((aligned(8)));/* * todo - keyrings and LSM * These may be better done with userspace help though
checkpoint/restart.c struct ckpt_hdr_file { · line 412
Quoted 5 lines
checkpoint/restart.c +2
-0@@ -392,6 +408,8 @@ struct ckpt_hdr_file {__s32 f_credref;__u64 f_pos;__u64 f_version; +__s32 f_secref; +__u32 f_padding;
No need for padding here.
checkpoint/restart.c struct ckpt_hdr_ipc_perms { · line 656
Quoted 9 lines
checkpoint/restart.c +2
-0} __attribute__((aligned(8))); struct ckpt_hdr_file_generic {@@ -634,6 +652,8 @@ struct ckpt_hdr_ipc_perms {__u32 mode;__u32 _padding;__u64 seq; +__s32 sec_ref; +__u32 padding;
Ditto.
[...]
checkpoint/restart.c static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen) · line 241
Quoted 9 lines
checkpoint/restart.c +5
-0@@ -224,6 +234,16 @@ static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen) msg->next =NULL ; pseg = &msg->next; +if ((ctx->uflags &RESTART_KEEP_LSM ) && (h->sec_ref !=-1 )) { +struct ckpt_stored_lsm *l =ckpt_obj_fetch (ctx, h->sec_ref, +CKPT_OBJ_SEC ); +if (IS_ERR (l)) +return (struct msg_msg *)l;
That's a leak. Need to 'goto out' instead.
checkpoint/restart.c static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen) · line 244
Quoted 3 lines
checkpoint/restart.c +3
-0+ ret =security_msg_msg_restore (msg, l->string); +if (ret) +return ERR_PTR (ret);
Here too.
[...]
checkpoint/restart.c static struct cred *do_restore_cred(struct ckpt_ctx *ctx) · line 822
Quoted 9 lines
checkpoint/restart.c +5
-0@@ -806,6 +815,15 @@ static struct cred *do_restore_cred(struct ckpt_ctx *ctx) ret =cred_setfsgid (cred, h->fsgid, &oldgid);if (oldgid != h->fsgid && ret <0 ) goto err_putcred; +if ((ctx->uflags &RESTART_KEEP_LSM ) && (h->sec_ref !=-1 )) { +struct ckpt_stored_lsm *l =ckpt_obj_fetch (ctx, h->sec_ref, +CKPT_OBJ_SEC ); +if (IS_ERR (l)) +return (struct cred *)l;
And here too ?
Quoted 43 lines
checkpoint/restart.c +43
-0+/** +* security_checkpoint_obj - if first checkpoint of this void* security, +* then 1. ask the LSM for a string representing the context, 2. checkpoint +* that string +* @ctx: the checkpoint context +* @security: the void* security being checkpointed +* @sectype: indicates the type of object, because LSMs can (and do) store +* different types of data for different types of objects. +* +* Returns the objref of the checkpointed ckpt_stored_lsm representing the +* context, or -error on error. +* +* This is only used at checkpoint of course. +*/ +int security_checkpoint_obj (struct ckpt_ctx *ctx,void *security, +unsigned sectype) +{ +int strref; +struct ckpt_stored_lsm *l; +char *str; +int len; + +/* +* to simplify the LSM code, short-cut a null security +* here. +*/ +if (!security) +return -EOPNOTSUPP ; + +switch (sectype) { +case CKPT_SECURITY_MSG_MSG : + str =security_msg_msg_checkpoint (security); +break ; +case CKPT_SECURITY_IPC : + str =security_ipc_checkpoint (security); +break ; +case CKPT_SECURITY_FILE : + str =security_file_checkpoint (security); +break ; +case CKPT_SECURITY_CRED : + str =security_cred_checkpoint (security); +break ; +default :
checkpoint/restart.c static struct cred *do_restore_cred(struct ckpt_ctx *ctx)
Quoted 10 lines
checkpoint/restart.c +10
-0+ str =ERR_PTR (-EINVAL ); +break ; + } +/* str will be alloc'ed for us by the LSM. We will free it when +* we clear out our hashtable */ +if (IS_ERR (str)) +return PTR_ERR (str); + + len =strlen (str); + l =kzalloc (sizeof (*l) + len +1 ,GFP_KERNEL );
Probably a dumb question: why do you allocate with the size of the string when it merely points to the string ?
Quoted 4 lines
checkpoint/restart.c +4
-0+if (!l) { +kfree (str); +return -ENOMEM ; + }
checkpoint/restart.c
Quoted 10 lines
checkpoint/restart.c +10
-0+kref_init (&l->kref); + l->sectype = sectype; + l->string = str; + + strref =checkpoint_obj (ctx, l,CKPT_OBJ_SEC ); +/* do we need to free l if strref was err? */ + return strref; +} + +#endif
Oren.
Quoted 34 lines · Oren Laadan
Quoted 10 lines · Serge E. Hallyn
(wasn't versioning the patchsets before, so randomly pick 4 as the version for this patchset...)
Documentation/checkpoint/readme.txtbegins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""[...]
Quoted 18 lines
Kernel interfaces
=================checkpoint/checkpoint.c +1
-0@@ -25,6 +25,7 @@#include <linux/magic.h> #include <linux/hrtimer.h> #include <linux/deferqueue.h> +#include <linux/security.h> #include <linux/checkpoint.h> #include <linux/checkpoint_hdr.h> @@ -351,6 +352,16 @@ static int checkpoint_write_header(struct ckpt_ctx *ctx)if (ret <0 )return ret;
Quoted 14 lines
checkpoint/checkpoint.c static int checkpoint_write_header(struct ckpt_ctx *ctx) · line 364
Quoted 10 lines
checkpoint/checkpoint.c +10
-0+memset (ctx->lsm_name,0 ,SECURITY_NAME_MAX +1 ); +strlcpy (ctx->lsm_name,security_get_lsm_name (),SECURITY_NAME_MAX +1 ); + ret =ckpt_write_buffer (ctx, ctx->lsm_name,SECURITY_NAME_MAX +1 ); +if (ret <0 ) +return ret; + + ret =security_checkpoint_header (ctx); +if (ret <0 ) +return ret; +This is actually a case for a 'container-global' section that would appear after the header and before the rest of the image. (Would be useful also for network namespaces).
But LSM's are specifically not containerized, so this is a host property, not a container one.
Quoted 31 lines
Quoted 31 lines
checkpoint/checkpoint.c +0
-0return checkpoint_write_header_arch (ctx); }checkpoint/files.c +13
-0@@ -145,6 +145,19 @@ static int scan_fds(struct files_struct *files, int **fdtable)return n; } +#ifdef CONFIG_SECURITY +int checkpoint_file_security (struct ckpt_ctx *ctx,struct file *file) +{ +return security_checkpoint_obj (ctx, file->f_security, +CKPT_SECURITY_FILE ); +} +#else +int checkpoint_file_security (struct ckpt_ctx *ctx,struct file *file) +{ +return -EOPNOTSUPP ; +} +#endif +int checkpoint_file_common (struct ckpt_ctx *ctx,struct file *file,struct ckpt_hdr_file *h) {@@ -159,6 +172,16 @@ int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file,if (h->f_credref <0 )return h->f_credref;
Quoted 5 lines
checkpoint/files.c int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file, · line 177
Quoted 3 lines
checkpoint/files.c +3
-0+ h->f_secref =checkpoint_file_security (ctx, file); +if (h->f_secref == -EOPNOTSUPP ) + h->f_secref =-1 ;#define
CKPT_SECURITY_NONE-1 ??
Yeah, that'd be cleaner.
Quoted 5 lines
Quoted 2 lines
checkpoint/files.c +2
-0+else if (h->f_secref <0 ) +return h->f_secref;[...]
Quoted 12 lines
checkpoint/files.c
Quoted 10 lines
checkpoint/files.c +10
-0+ +static int do_checkpoint_security (struct ckpt_ctx *ctx, +const struct ckpt_stored_lsm *l) +{ +int ret, len; +struct ckpt_hdr_lsm *h; + + len =strlen (l->string); +if (len >PAGE_SIZE -sizeof (*h)) +return -E2BIG ;A call to
ckpt_write_err()here may be useful.
ok
Quoted 22 lines
Quoted 22 lines
checkpoint/files.c +22
-0+ h =ckpt_hdr_get_type (ctx,sizeof (*h)+len+1 ,CKPT_HDR_SEC ); +if (!h) +return -ENOMEM ; + h->len = len; + h->sectype = l->sectype; +strncpy (h->string, l->string, len); + h->string[len] ='\0' ; + ret =ckpt_write_obj (ctx, &h->h); +ckpt_hdr_put (ctx, h); +return ret; +} + +static int checkpoint_security (struct ckpt_ctx *ctx,void *ptr) +{ +return do_checkpoint_security (ctx, (struct ckpt_stored_lsm *) ptr); +} + +static struct ckpt_stored_lsm *do_restore_security (struct ckpt_ctx *ctx) +{ +struct ckpt_hdr_lsm *h; +struct ckpt_stored_lsm *l; +
Quoted 8 lines
checkpoint/files.c
Quoted 5 lines
checkpoint/files.c +5
-0+ h =ckpt_read_buf_type (ctx,PAGE_SIZE ,CKPT_HDR_SEC ); +if (IS_ERR (h)) +return (struct ckpt_stored_lsm *)h; +if (h->len > h->h.len -sizeof (struct ckpt_hdr ) || + h->len >PAGE_SIZE ) {The second test (for
h->len>PAGE_SIZE) is unnecessary - already done inckpt_read_buf_type()
Huh. I had no idea :)
Quoted 9 lines
checkpoint/files.c
Quoted 7 lines
checkpoint/files.c +7
-0+ckpt_hdr_put (ctx, h); +return ERR_PTR (-EINVAL ); + } + l =kzalloc (sizeof (*l),GFP_KERNEL ); +if (!l) { +ckpt_hdr_put (ctx, h); +return ERR_PTR (-ENOMEM );Nit: this part is common... set ret =
-ENOMEMand use goto ?
ok
Quoted 12 lines
[...]
checkpoint/files.c static int restore_task_objs(struct ckpt_ctx *ctx) · line 616
Quoted 8 lines
checkpoint/files.c +1
-3@@ -608,14 +613,21 @@ static int restore_task_objs(struct ckpt_ctx *ctx)* referenced. See comment in checkpoint_task_objs. */ ret =restore_task_creds (ctx); -if (!ret) - ret =restore_task_ns (ctx); -if (ret <0 ) +if (ret) {Nit: (ret < 0) helps (me) read it.
Really? Whenever I review something like that it forces me to go through and make sure no >0 codes will be returned for failure... But ok.
Quoted 26 lines
Quoted 26 lines
checkpoint/files.c +10
-1+ckpt_debug ("restore_task_creds returned %d" , ret); +return ret; + } + ret =restore_task_ns (ctx); +if (ret) { +ckpt_debug ("restore_task_ns returned %d" , ret);return ret; + } h =ckpt_read_obj_type (ctx,sizeof (*h),CKPT_HDR_TASK_OBJS ); -if (IS_ERR (h)) +if (IS_ERR (h)) { +ckpt_debug ("Error fetching task obj" );return PTR_ERR (h); + } ret =restore_obj_file_table (ctx, h->files_objref);ckpt_debug ("file_table: ret %d (%p)\n" , ret, current->files);checkpoint/restart.c +0
-0@@ -457,6 +457,31 @@ static int restore_read_header(struct ckpt_ctx *ctx)if (ret <0 ) goto out;
Quoted 11 lines
checkpoint/restart.c static int restore_read_header(struct ckpt_ctx *ctx) · line 468
Quoted 9 lines
checkpoint/restart.c +9
-0+ ret =_ckpt_read_buffer (ctx, ctx->lsm_name,SECURITY_NAME_MAX +1 ); +if (ret <0 ) + goto out; +if (ctx->uflags &RESTART_KEEP_LSM ) { +char *cur =security_get_lsm_name (); +if (strncmp (cur, ctx->lsm_name,SECURITY_NAME_MAX +1 ) !=0 ) { +pr_warning ("c/r: checkpointed LSM %s, current is %s.\n" , + ctx->lsm_name, cur); + ret = -EINVAL ;EPERM ?
Hmm... I think of this not as "you're not allowed" but rather "it doesn't
make sense."
Quoted 49 lines
[...]
checkpoint/restart.c struct ckpt_hdr_groupinfo { · line 289
Quoted 8 lines
checkpoint/restart.c +4
-0@@ -277,6 +283,16 @@ struct ckpt_hdr_groupinfo {__u32 groups[0 ]; } __attribute__((aligned(8))); +struct ckpt_hdr_lsm { +struct ckpt_hdr h; +__u8 sectype; +__u16 len;Alignment ...
Quoted 10 lines
checkpoint/restart.c +6
-0+/* +* This is followed by a string of size len+1, +* null-terminated +*/ +__u8 string[0 ]; +} __attribute__((aligned(8)));/* * todo - keyrings and LSM * These may be better done with userspace help though checkpoint/restart.c struct ckpt_hdr_file { · line 412
Quoted 5 lines
checkpoint/restart.c +2
-0@@ -392,6 +408,8 @@ struct ckpt_hdr_file {__s32 f_credref;__u64 f_pos;__u64 f_version; +__s32 f_secref; +__u32 f_padding;No need for padding here.
checkpoint/restart.c struct ckpt_hdr_ipc_perms { · line 656
Quoted 9 lines
checkpoint/restart.c +2
-0} __attribute__((aligned(8))); struct ckpt_hdr_file_generic {@@ -634,6 +652,8 @@ struct ckpt_hdr_ipc_perms {__u32 mode;__u32 _padding;__u64 seq; +__s32 sec_ref; +__u32 padding;Ditto.
[...]
Quoted 4 lines
checkpoint/restart.c +0
-0@@ -224,6 +234,16 @@ static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen) msg->next =NULL ; pseg = &msg->next;
Quoted 7 lines
checkpoint/restart.c static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen) · line 241
Quoted 5 lines
checkpoint/restart.c +5
-0+if ((ctx->uflags &RESTART_KEEP_LSM ) && (h->sec_ref !=-1 )) { +struct ckpt_stored_lsm *l =ckpt_obj_fetch (ctx, h->sec_ref, +CKPT_OBJ_SEC ); +if (IS_ERR (l)) +return (struct msg_msg *)l;That's a leak. Need to 'goto out' instead.
ok
Quoted 68 lines
checkpoint/restart.c static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen) · line 244
Quoted 3 lines
checkpoint/restart.c +3
-0+ ret =security_msg_msg_restore (msg, l->string); +if (ret) +return ERR_PTR (ret);Here too.
[...]
checkpoint/restart.c static struct cred *do_restore_cred(struct ckpt_ctx *ctx) · line 822
Quoted 9 lines
checkpoint/restart.c +5
-0@@ -806,6 +815,15 @@ static struct cred *do_restore_cred(struct ckpt_ctx *ctx) ret =cred_setfsgid (cred, h->fsgid, &oldgid);if (oldgid != h->fsgid && ret <0 ) goto err_putcred; +if ((ctx->uflags &RESTART_KEEP_LSM ) && (h->sec_ref !=-1 )) { +struct ckpt_stored_lsm *l =ckpt_obj_fetch (ctx, h->sec_ref, +CKPT_OBJ_SEC ); +if (IS_ERR (l)) +return (struct cred *)l;And here too ?
Quoted 48 lines
checkpoint/restart.c +48
-0+/** +* security_checkpoint_obj - if first checkpoint of this void* security, +* then 1. ask the LSM for a string representing the context, 2. checkpoint +* that string +* @ctx: the checkpoint context +* @security: the void* security being checkpointed +* @sectype: indicates the type of object, because LSMs can (and do) store +* different types of data for different types of objects. +* +* Returns the objref of the checkpointed ckpt_stored_lsm representing the +* context, or -error on error. +* +* This is only used at checkpoint of course. +*/ +int security_checkpoint_obj (struct ckpt_ctx *ctx,void *security, +unsigned sectype) +{ +int strref; +struct ckpt_stored_lsm *l; +char *str; +int len; + +/* +* to simplify the LSM code, short-cut a null security +* here. +*/ +if (!security) +return -EOPNOTSUPP ; + +switch (sectype) { +case CKPT_SECURITY_MSG_MSG : + str =security_msg_msg_checkpoint (security); +break ; +case CKPT_SECURITY_IPC : + str =security_ipc_checkpoint (security); +break ; +case CKPT_SECURITY_FILE : + str =security_file_checkpoint (security); +break ; +case CKPT_SECURITY_CRED : + str =security_cred_checkpoint (security); +break ; +default : + str =ERR_PTR (-EINVAL ); +break ; + } +/* str will be alloc'ed for us by the LSM. We will free it when +* we clear out our hashtable */
Quoted 8 lines
checkpoint/restart.c
Quoted 5 lines
checkpoint/restart.c +5
-0+if (IS_ERR (str)) +return PTR_ERR (str); + + len =strlen (str); + l =kzalloc (sizeof (*l) + len +1 ,GFP_KERNEL );Probably a dumb question: why do you allocate with the size of the string when it merely points to the string ?
No just dumb code - I used to strcpy it in but don't anymore.
Quoted 8 lines
Quoted 8 lines
checkpoint/restart.c +8
-0+if (!l) { +kfree (str); +return -ENOMEM ; + } +kref_init (&l->kref); + l->sectype = sectype; + l->string = str; +
Quoted 8 lines
checkpoint/restart.c
Quoted 6 lines
checkpoint/restart.c +6
-0+ strref =checkpoint_obj (ctx, l,CKPT_OBJ_SEC ); +/* do we need to free l if strref was err? */ + return strref; +} + +#endif Oren.
Thanks! Will send a new version.
-serge
Quoted 13 lines · Serge E. Hallyn
Quoted 12 lines · Oren Laadan
Quoted 10 lines · Serge E. Hallyn
(wasn't versioning the patchsets before, so randomly pick 4 as the version for this patchset...)
Documentation/checkpoint/readme.txtbegins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""
[...]
Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
checkpoint/checkpoint.c +5
-0+memset (ctx->lsm_name,0 ,SECURITY_NAME_MAX +1 ); +strlcpy (ctx->lsm_name,security_get_lsm_name (),SECURITY_NAME_MAX +1 ); + ret =ckpt_write_buffer (ctx, ctx->lsm_name,SECURITY_NAME_MAX +1 ); +if (ret <0 ) +return ret;Quoted 8 lines
checkpoint/checkpoint.c static int checkpoint_write_header(struct ckpt_ctx *ctx) · line 364
Quoted 5 lines
checkpoint/checkpoint.c +5
-0+ + ret =security_checkpoint_header (ctx); +if (ret <0 ) +return ret; +This is actually a case for a 'container-global' section that would appear after the header and before the rest of the image. (Would be useful also for network namespaces).
Quoted 2 lines
But LSM's are specifically not containerized, so this is a host property, not a container one.
Hmmm... does that mean you can't apply one policy to one container and another policy to another ?
Anyway, it belongs to a 'global' section, that may have 2 parts:
host and container. (Putting it between header and arch-header seems weird...)
The header doesn't hold state, it is a declarative section about the properties of the original host (kernel and HW).
Oren.
Quoted 33 lines · Oren Laadan
Quoted 13 lines · Serge E. Hallyn
Quoted 12 lines · Oren Laadan
Quoted 10 lines · Serge E. Hallyn
(wasn't versioning the patchsets before, so randomly pick 4 as the version for this patchset...)
Documentation/checkpoint/readme.txtbegins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""[...]
Quoted 14 lines
Quoted 13 lines
checkpoint/checkpoint.c static int checkpoint_write_header(struct ckpt_ctx *ctx) · line 364
Quoted 10 lines
checkpoint/checkpoint.c +10
-0+memset (ctx->lsm_name,0 ,SECURITY_NAME_MAX +1 ); +strlcpy (ctx->lsm_name,security_get_lsm_name (),SECURITY_NAME_MAX +1 ); + ret =ckpt_write_buffer (ctx, ctx->lsm_name,SECURITY_NAME_MAX +1 ); +if (ret <0 ) +return ret; + + ret =security_checkpoint_header (ctx); +if (ret <0 ) +return ret; +This is actually a case for a 'container-global' section that would appear after the header and before the rest of the image. (Would be useful also for network namespaces).
Quoted 5 lines
Quoted 2 lines
But LSM's are specifically not containerized, so this is a host property, not a container one.
Hmmm... does that mean you can't apply one policy to one container and another policy to another ?
Yup.
Quoted 3 lines
Anyway, it belongs to a 'global' section, that may have 2 parts:
host and container. (Putting it between header and arch-header seems weird...)
Ok, then I'll add that in the next set.
Quoted 2 lines
The header doesn't hold state, it is a declarative section about the properties of the original host (kernel and HW).
Ok, I see.
thanks,
-serge
PATCH 2/3 cr: add smack support to lsm c/r (v4)
In reply to Serge E. HallynDocumentation/checkpoint/readme.txt begins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""
This patch implements checkpoint and restore of Smack security labels. The rules are the same as in previous versions:
1. when objects are created during restore() they are automatically labeled with current_security().
2. if there was a label checkpointed with the object, and that label != current_security() (which is the same as obj->security), then the object is relabeled if the sys_restart() caller has CAP_MAC_ADMIN. Otherwise we return -EPERM.
This has been tested by checkpointing tasks under labels _, vs1, and vs2, and restarting from tasks under _, vs1, and vs2, with and without CAP_MAC_ADMIN in the bounding set, and with and without the '-k' (keep_lsm) flag to mktree. Expected results:
#shell 1:
echo vs1 > /proc/self/attr/current
ckpt > out
echo vs2 > /proc/self/attr/current
mktree -F /cgroup/2 < out
(frozen)
# shell 2:
cat /proc/pidof ckpt/attr/current
vs2
echo THAWED > /cgroup/2/freezer.state
# shell 1:
mktree -k -F /cgroup/2 < out
(frozen)
# shell 2:
cat /proc/pidof ckpt/attr/current
vs1
echo THAWED > /cgroup/2/freezer.state
# shell 1:
capsh --drop=cap_mac_admin --
mktree -k -F /cgroup/2 < out
(permission denied)
There are testcases in git://git.sr71.net/~hallyn/cr_tests.git
under cr_tests/smack, which automate the above (and pass).
Changelog:
sep 3: add a version to smack lsm, accessible through
/smack/version (Casey and Serge)
sep 10: rename xyz_get_ctx() to xyz_checkpoint()
--- checkpoint/restart.c | 1 + security/smack/smack.h | 1 + security/smack/smack_lsm.c | 141 ++++++++++++++++++++++++++++++++++++++++++++ security/smack/smackfs.c | 83 ++++++++++++++++++++++++++ 4 files changed, 226 insertions(+), 0 deletions(-)
checkpoint/restart.c +1 -0
@@ -470,6 +470,7 @@ static int restore_read_header(struct ckpt_ctx *ctx) }/* to be implemented later, per-lsm */ if (strcmp (ctx->lsm_name,"lsm_none" ) !=0 && +strcmp (ctx->lsm_name,"smack" ) !=0 &&strcmp (ctx->lsm_name,"default" ) !=0 ) {pr_warning ("c/r: RESTART_KEEP_LSM unsupported for %s\n" , ctx->lsm_name);
security/smack/smack.h +1 -0
@@ -216,6 +216,7 @@ u32 smack_to_secid(const char *);extern int smack_cipso_direct;extern char *smack_net_ambient;extern char *smack_onlycap; +extern char *smack_version;extern const char *smack_cipso_option;extern struct smack_known smack_known_floor;
security/smack/smack_lsm.c +141 -0
203 lines not on this page · raw message
security/smack/smackfs.c +83 -0
113 lines not on this page · raw message
Signature · 1 line
1.6.1
PATCH 3/3 cr: add selinux support (v4)
In reply to Serge E. HallynDocumentation/checkpoint/readme.txt begins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""
This patch adds the ability to checkpoint and restore selinux contexts for tasks, open files, and sysvipc objects. Contexts are checkpointed as strings. For tasks and files, where a security struct actually points to several contexts, all contexts are written out in one string, separated by ':::'.
The default behaviors are to checkpoint contexts, but not to restore them. To attempt to restore them, sys_restart() must be given the RESTART_KEEP_LSM flag. If this is given then the caller of sys_restart() must have the new 'restore' permission to the target objclass, or for instance PROCESS__SETFSCREATE to itself to specify a create_sid.
There are some tests under cr_tests/selinux atgit://git.sr71.net/~hallyn/cr_tests.git.
A corresponding simple refpolicy (and /usr/share/selinux/devel/include) patch is needed.
The programs to checkpoint and restart (called 'checkpoint' and 'restart') come from git://git.ncl.cs.columbia.edu/pub/git/user-cr.git.
This patch applies against the checkpoint/restart-enabled kernel tree at git://git.ncl.cs.columbia.edu/pub/git/linux-cr.git/.
Changelog:
oct 01: Remove some debugging that is redundant with
avc log data.
sep 10: (Most addressing suggestions by Stephen Smalley)
1. change xyz_get_ctx() to xyz_checkpoint().
2. check entrypoint permission on cred_restore
3. always dec context length by 1
4. don't allow SECSID_NULL when that's not valid
5. when SECSID_NULL is valid, restore it
6. c/r task->osid
7. Just print nothing instead of 'null' for SECSID_NULL
8. sids are __u32, as are lenghts passed to sid_to_context.
--- checkpoint/restart.c | 1 + kernel/cred.c | 2 + security/selinux/hooks.c | 371 ++++++++++++++++++++++++++ security/selinux/include/av_perm_to_string.h | 4 + security/selinux/include/av_permissions.h | 4 + 5 files changed, 382 insertions(+), 0 deletions(-)
checkpoint/restart.c +1 -0
@@ -471,6 +471,7 @@ static int restore_read_header(struct ckpt_ctx *ctx)/* to be implemented later, per-lsm */ if (strcmp (ctx->lsm_name,"lsm_none" ) !=0 &&strcmp (ctx->lsm_name,"smack" ) !=0 && +strcmp (ctx->lsm_name,"selinux" ) !=0 &&strcmp (ctx->lsm_name,"default" ) !=0 ) {pr_warning ("c/r: RESTART_KEEP_LSM unsupported for %s\n" , ctx->lsm_name);
kernel/cred.c +2 -0
@@ -732,6 +732,8 @@ static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred)if (!h)return -ENOMEM ; +ckpt_debug ("cred uid %d fsuid %d gid %d secref %d\n" , cred->uid, + cred->fsuid, cred->gid, sec_ref); h->uid = cred->uid; h->suid = cred->suid; h->euid = cred->euid;
security/selinux/hooks.c +371 -0
421 lines not on this page · raw message
security/selinux/include/av_perm_to_string.h +4 -0
@@ -19,6 +19,7 @@ S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint") S_(SECCLASS_FILE, FILE__EXECMOD, "execmod") S_(SECCLASS_FILE, FILE__OPEN, "open") + S_(SECCLASS_FILE, FILE__RESTORE, "restore") S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans") S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")S_ (SECCLASS_CHR_FILE ,CHR_FILE__EXECMOD ,"execmod" )
@@ -88,9 +89,11 @@ S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate") + S_(SECCLASS_PROCESS, PROCESS__RESTORE, "restore") S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") S_(SECCLASS_MSG, MSG__SEND, "send") S_(SECCLASS_MSG, MSG__RECEIVE, "receive") + S_(SECCLASS_MSG, MSG__RESTORE, "restore") S_(SECCLASS_SHM, SHM__LOCK, "lock") S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av")S_ (SECCLASS_SECURITY ,SECURITY__COMPUTE_CREATE ,"compute_create" )
@@ -107,6 +110,7 @@ S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") + S_(SECCLASS_IPC, IPC__RESTORE, "restore") S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override")S_ (SECCLASS_CAPABILITY ,CAPABILITY__DAC_READ_SEARCH ,"dac_read_search" )
security/selinux/include/av_permissions.h +4 -0
@@ -101,6 +101,7 @@#define FILE__ENTRYPOINT 0x00040000UL#define FILE__EXECMOD 0x00080000UL#define FILE__OPEN 0x00100000UL +#define FILE__RESTORE 0x00200000UL#define LNK_FILE__IOCTL 0x00000001UL#define LNK_FILE__READ 0x00000002UL#define LNK_FILE__WRITE 0x00000004UL
@@ -453,6 +454,7 @@#define PROCESS__EXECHEAP 0x08000000UL#define PROCESS__SETKEYCREATE 0x10000000UL#define PROCESS__SETSOCKCREATE 0x20000000UL +#define PROCESS__RESTORE 0x40000000UL#define IPC__CREATE 0x00000001UL#define IPC__DESTROY 0x00000002UL#define IPC__GETATTR 0x00000004UL
@@ -462,6 +464,7 @@#define IPC__ASSOCIATE 0x00000040UL#define IPC__UNIX_READ 0x00000080UL#define IPC__UNIX_WRITE 0x00000100UL +#define IPC__RESTORE 0x00000200UL#define SEM__CREATE 0x00000001UL#define SEM__DESTROY 0x00000002UL#define SEM__GETATTR 0x00000004UL
@@ -483,6 +486,7 @@#define MSGQ__ENQUEUE 0x00000200UL#define MSG__SEND 0x00000001UL#define MSG__RECEIVE 0x00000002UL +#define MSG__RESTORE 0x00000004UL#define SHM__CREATE 0x00000001UL#define SHM__DESTROY 0x00000002UL#define SHM__GETATTR 0x00000004UL
Signature · 1 line
1.6.1
Re: [PATCH 3/3] cr: add selinux support (v4)
Quoted 18 lines · Serge E. Hallyn
Documentation/checkpoint/readme.txtbegins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""This patch adds the ability to checkpoint and restore selinux contexts for tasks, open files, and sysvipc objects. Contexts are checkpointed as strings. For tasks and files, where a security struct actually points to several contexts, all contexts are written out in one string, separated by ':::'.
security/selinux/hooks.c +0
-0
security/selinux/hooks.c static int selinux_file_permission(struct file *file, int mask) · line 2971
Quoted 10 lines
security/selinux/hooks.c +7
-0@@ -2961,6 +2962,108 @@ static int selinux_file_permission(struct file *file, int mask)return selinux_revalidate_file_permission (file, mask); } +/* +* for file context, we print both the fsec->sid and fsec->fown_sid +* as string representations, separated by ':::' +* We don't touch isid - if you wanted that set you shoulda set up the +* fs correctly. +*/ +static inline char *selinux_file_checkpoint (void *security)
Why are these functions declared inline? In any event, just let the compiler figure out when to make them inline if appropriate.
Quoted 43 lines
security/selinux/hooks.c +43
-0+static inline int selinux_file_restore (struct file *file,char *ctx) +{ +char *s1, *s2; +__u32 sid1 =0 , sid2 =0 ; +int ret = -EINVAL ; +struct file_security_struct *fsec = file->f_security; + +/* +* Objhash made sure the string is null-terminated. +* We make a copy so we can mangle it. +*/ + s1 =kstrdup (ctx,GFP_KERNEL ); +if (!s1) +return -ENOMEM ; + s2 =strstr (s1,":::" ); +if (!s2) + goto out; + + *s2 ='\0' ; + s2 +=3 ; +if (*s2 =='\0' ) + goto out; + +/* SECSID_NULL is not valid for file sids */ +if (strlen (s1) ==0 ||strlen (s2) ==0 ) + goto out; + + ret =security_context_to_sid (s1,strlen (s1), &sid1); +if (ret) + goto out; + ret =security_context_to_sid (s2,strlen (s2), &sid2); +if (ret) + goto out; + +if (sid1 && fsec->sid != sid1) { + ret =avc_has_perm (current_sid (), sid1,SECCLASS_FILE , +FILE__RESTORE ,NULL ); +if (ret) + goto out; + fsec->sid = sid1; + } + +#if 0
security/selinux/hooks.c static int selinux_file_permission(struct file *file, int mask) · line 3058
Quoted 10 lines
security/selinux/hooks.c +10
-0+/* The following must wait - bc we don't yet support +* c/r of fowners. */ +if (sid2 && fsec->fown_sid != sid2) { + ret =avc_has_perm (current_sid (), sid2,SECCLASS_FILE , +FILE__FOWN_RESTORE ,NULL ); +if (ret) + goto out; + fsec->fown_sid = sid2; + } +#endif
I'm not sure why you can't enable this code yet. From your comment, it sounds like c/r doesn't yet handle the uid/euid in the fown_struct, but that doesn't mean you can't manage the fown_sid that we store in the file. We just leveraged the fact that a fown_struct is never outside the context of a containing struct file (at least from a send_sigio context) to avoid introducing a separate security field with its own lifecycle there.
Quoted 8 lines
security/selinux/hooks.c +4
-0@@ -3219,6 +3322,187 @@ static int selinux_task_create(unsigned long clone_flags)return current_has_perm (current,PROCESS__FORK ); } +#define NUMTASKSIDS 6 +/* +* for cred context, we print: +* osid, sid, exec_sid, create_sid, keycreate_sid, sockcreate_sid;
security/selinux/hooks.c static int selinux_task_create(unsigned long clone_flags) · line 3338
Quoted 10 lines
security/selinux/hooks.c +10
-0+* as string representations, separated by ':::' +*/ +static inline char *selinux_cred_checkpoint (void *security) +{ +struct task_security_struct *tsec = security; +char *stmp, *sfull =NULL ; +__u32 slen, runlen; +int i, ret; +__u32 sids[NUMTASKSIDS ] = { tsec->osid, tsec->sid, tsec->exec_sid, + tsec->create_sid, tsec->keycreate_sid, tsec->sockcreate_sid };
Why are you using __u32 rather than just u32? I think the former is only necessary in certain headers that might be shared with userspace?
security/selinux/hooks.c static int selinux_task_create(unsigned long clone_flags) · line 3400
Quoted 10 lines
security/selinux/hooks.c +10
-0+static inline int selinux_cred_restore (struct file *file,struct cred *cred, +char *ctx) +{ +char *s, *s1, *s2 =NULL ; +int ret = -EINVAL ; +struct task_security_struct *tsec = cred->security; +int i; +__u32 sids[NUMTASKSIDS ]; +struct inode *ctx_inode = file->f_dentry->d_inode; +struct avc_audit_data ad;
audit code was refactored in mainline to share common data structures and code among security modules, so e.g. this became common_audit_data. Not sure what your baseline is, but this happened in July.
security/selinux/hooks.c static int selinux_task_create(unsigned long clone_flags) · line 3444
Quoted 11 lines
security/selinux/hooks.c +11
-0+/* +* Check that these transitions are allowed, and effect them. +* XXX: Do these checks suffice? +*/ +if (tsec->osid != sids[0 ]) { +/* +* Are any security decisions made based on osid? +* Is it worth adding a PROCESS_RESTORE_OSID permission +* for this? +*/ + tsec->osid = sids[0 ];
osid is only used in kernel permission checks upon a SID transition, and then it has been updated to ->sid prior to the transition. Userspace however may use it in a permission check (obtained via getprevcon) on the caller when the program runs in its own domain, e.g. passwd(1). I suppose there should be a check for it, although possibly it could be the same as for the ->sid (i.e. PROCESS__RESTORE).
security/selinux/include/av_perm_to_string.h
Quoted 4 lines
security/selinux/include/av_perm_to_string.h +0
-0
<snip>
Just FYI, this file goes away with the dynamic class/perm discovery patch that I've been posting to selinux list.
security/selinux/include/av_permissions.h
Quoted 4 lines
security/selinux/include/av_permissions.h +0
-0
<snip>
Likewise, this file goes away and is replaced by an automatically generated one from the new classmap.h file, which is the only kernel file you'll need to modify to add new permissions.
Signature · 2 lines
Stephen Smalley National Security Agency
Re: [PATCH 3/3] cr: add selinux support (v4)
Quoted 22 lines · Stephen Smalley
Quoted 21 lines · Serge E. Hallyn
Documentation/checkpoint/readme.txtbegins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""This patch adds the ability to checkpoint and restore selinux contexts for tasks, open files, and sysvipc objects. Contexts are checkpointed as strings. For tasks and files, where a security struct actually points to several contexts, all contexts are written out in one string, separated by ':::'.
security/selinux/hooks.c +0
-0@@ -2961,6 +2962,108 @@ static int selinux_file_permission(struct file *file, int mask)return selinux_revalidate_file_permission (file, mask); }
Quoted 7 lines
security/selinux/hooks.c static int selinux_file_permission(struct file *file, int mask) · line 2971
Quoted 7 lines
security/selinux/hooks.c +7
-0+/* +* for file context, we print both the fsec->sid and fsec->fown_sid +* as string representations, separated by ':::' +* We don't touch isid - if you wanted that set you shoulda set up the +* fs correctly. +*/ +static inline char *selinux_file_checkpoint (void *security)
Thanks for looking it over again, Stephen.
Quoted 2 lines
Why are these functions declared inline? In any event, just let the compiler figure out when to make them inline if appropriate.
Yikes, I don't know. Must have cut-n-pasted the prototypes from include/linux/security.h. Fixed below.
Quoted 54 lines
Quoted 43 lines
security/selinux/hooks.c +43
-0+static inline int selinux_file_restore (struct file *file,char *ctx) +{ +char *s1, *s2; +__u32 sid1 =0 , sid2 =0 ; +int ret = -EINVAL ; +struct file_security_struct *fsec = file->f_security; + +/* +* Objhash made sure the string is null-terminated. +* We make a copy so we can mangle it. +*/ + s1 =kstrdup (ctx,GFP_KERNEL ); +if (!s1) +return -ENOMEM ; + s2 =strstr (s1,":::" ); +if (!s2) + goto out; + + *s2 ='\0' ; + s2 +=3 ; +if (*s2 =='\0' ) + goto out; + +/* SECSID_NULL is not valid for file sids */ +if (strlen (s1) ==0 ||strlen (s2) ==0 ) + goto out; + + ret =security_context_to_sid (s1,strlen (s1), &sid1); +if (ret) + goto out; + ret =security_context_to_sid (s2,strlen (s2), &sid2); +if (ret) + goto out; + +if (sid1 && fsec->sid != sid1) { + ret =avc_has_perm (current_sid (), sid1,SECCLASS_FILE , +FILE__RESTORE ,NULL ); +if (ret) + goto out; + fsec->sid = sid1; + } + +#if 0 security/selinux/hooks.c static int selinux_file_permission(struct file *file, int mask) · line 3024
Quoted 10 lines
security/selinux/hooks.c +10
-0+/* The following must wait - bc we don't yet support +* c/r of fowners. */ +if (sid2 && fsec->fown_sid != sid2) { + ret =avc_has_perm (current_sid (), sid2,SECCLASS_FILE , +FILE__FOWN_RESTORE ,NULL ); +if (ret) + goto out; + fsec->fown_sid = sid2; + } +#endif
Quoted 7 lines
I'm not sure why you can't enable this code yet. From your comment, it sounds like c/r doesn't yet handle the uid/euid in the
fown_struct, but that doesn't mean you can't manage thefown_sidthat we store in the file. We just leveraged the fact that afown_structis never outside the context of a containing struct file (at least from asend_sigiocontext) to avoid introducing a separate security field with its own lifecycle there.
Ok, I enabled it (with no resulting problems).
Quoted 13 lines
Quoted 13 lines
security/selinux/hooks.c +9
-0@@ -3219,6 +3322,187 @@ static int selinux_task_create(unsigned long clone_flags)return current_has_perm (current,PROCESS__FORK ); } +#define NUMTASKSIDS 6 +/* +* for cred context, we print: +* osid, sid, exec_sid, create_sid, keycreate_sid, sockcreate_sid; +* as string representations, separated by ':::' +*/ +static inline char *selinux_cred_checkpoint (void *security) +{ +struct task_security_struct *tsec = security;
Quoted 8 lines
security/selinux/hooks.c static int selinux_task_create(unsigned long clone_flags) · line 3338
Quoted 5 lines
security/selinux/hooks.c +5
-0+char *stmp, *sfull =NULL ; +__u32 slen, runlen; +int i, ret; +__u32 sids[NUMTASKSIDS ] = { tsec->osid, tsec->sid, tsec->exec_sid, + tsec->create_sid, tsec->keycreate_sid, tsec->sockcreate_sid };Why are you using
__u32rather than just u32? I think the former is only necessary in certain headers that might be shared with userspace?
Changed below
Quoted 6 lines
Quoted 6 lines
security/selinux/hooks.c +6
-0+static inline int selinux_cred_restore (struct file *file,struct cred *cred, +char *ctx) +{ +char *s, *s1, *s2 =NULL ; +int ret = -EINVAL ; +struct task_security_struct *tsec = cred->security;
Quoted 8 lines
security/selinux/hooks.c static int selinux_task_create(unsigned long clone_flags) · line 3348
Quoted 4 lines
security/selinux/hooks.c +4
-0+int i; +__u32 sids[NUMTASKSIDS ]; +struct inode *ctx_inode = file->f_dentry->d_inode; +struct avc_audit_data ad;audit code was refactored in mainline to share common data structures and code among security modules, so e.g. this became
common_audit_data. Not sure what your baseline is, but this happened in July.
It was merged by Linus on Sep 11, though, which is 2 days after our latest c/r port to his tree :)
Quoted 11 lines
Quoted 11 lines
security/selinux/hooks.c +10
-0+/* +* Check that these transitions are allowed, and effect them. +* XXX: Do these checks suffice? +*/ +if (tsec->osid != sids[0 ]) { +/* +* Are any security decisions made based on osid? +* Is it worth adding a PROCESS_RESTORE_OSID permission +* for this? +*/
Quoted 8 lines
security/selinux/hooks.c static int selinux_task_create(unsigned long clone_flags) · line 3359
Quoted 1 line
security/selinux/hooks.c +1
-0+ tsec->osid = sids[0 ];osid is only used in kernel permission checks upon a SID transition, and then it has been updated to ->sid prior to the transition. Userspace however may use it in a permission check (obtained via getprevcon) on the caller when the program runs in its own domain, e.g. passwd(1). I suppose there should be a check for it, although possibly it could be the same as for the ->sid (i.e.
PROCESS__RESTORE).
Ok, done.
Quoted 15 lines
security/selinux/include/av_perm_to_string.h
Quoted 4 lines
security/selinux/include/av_perm_to_string.h +0
-0<snip>
Just FYI, this file goes away with the dynamic class/perm discovery patch that I've been posting to selinux list.
Quoted 4 lines
security/selinux/include/av_permissions.h +0
-0<snip>
Quoted 3 lines
Likewise, this file goes away and is replaced by an automatically generated one from the new
classmap.hfile, which is the only kernel file you'll need to modify to add new permissions.
Ok, that's nice actually.
So I have some work to do when we re-base to Linus' tree, but in the meantime, here is a version addressing the rest of the comments. Or would you prefer I wait and resend after a re-base?
thanks,
-serge
From 77a3a47895fd43e1593752a79b0b09d40744fb41 Mon Sep 17 00:00:00 2001
From: Serge E. Hallyn <[email protected]>
Date: Thu, 27 Aug 2009 08:19:36 -0700
Subject: [PATCH 1/1] cr: add selinux support (v5)
Documentation/checkpoint/readme.txt begins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""
This patch adds the ability to checkpoint and restore selinux contexts for tasks, open files, and sysvipc objects. Contexts are checkpointed as strings. For tasks and files, where a security struct actually points to several contexts, all contexts are written out in one string, separated by ':::'.
The default behaviors are to checkpoint contexts, but not to restore them. To attempt to restore them, sys_restart() must be given the RESTART_KEEP_LSM flag. If this is given then the caller of sys_restart() must have the new 'restore' permission to the target objclass, or for instance PROCESS__SETFSCREATE to itself to specify a create_sid.
There are some tests under cr_tests/selinux atgit://git.sr71.net/~hallyn/cr_tests.git.
A corresponding simple refpolicy (and /usr/share/selinux/devel/include) patch is needed.
The programs to checkpoint and restart (called 'checkpoint' and 'restart') come from git://git.ncl.cs.columbia.edu/pub/git/user-cr.git.
This patch applies against the checkpoint/restart-enabled kernel tree at git://git.ncl.cs.columbia.edu/pub/git/linux-cr.git/.
Changelog:
oct 02: (Stephen Smalley suggestions):
1. s/__u32/u32/
2. enable the fown sid restoration
3. use process_restore to authorize resetting osid
4. don't make new hooks inline.
oct 01: Remove some debugging that is redundant with
avc log data.
sep 10: (Most addressing suggestions by Stephen Smalley)
1. change xyz_get_ctx() to xyz_checkpoint().
2. check entrypoint permission on cred_restore
3. always dec context length by 1
4. don't allow SECSID_NULL when that's not valid
5. when SECSID_NULL is valid, restore it
6. c/r task->osid
7. Just print nothing instead of 'null' for SECSID_NULL
8. sids are __u32, as are lenghts passed to sid_to_context.
--- checkpoint/restart.c | 1 + kernel/cred.c | 2 + security/selinux/hooks.c | 367 ++++++++++++++++++++++++++ security/selinux/include/av_perm_to_string.h | 5 + security/selinux/include/av_permissions.h | 5 + 5 files changed, 380 insertions(+), 0 deletions(-)
checkpoint/restart.c +1 -0
@@ -471,6 +471,7 @@ static int restore_read_header(struct ckpt_ctx *ctx)/* to be implemented later, per-lsm */ if (strcmp (ctx->lsm_name,"lsm_none" ) !=0 &&strcmp (ctx->lsm_name,"smack" ) !=0 && +strcmp (ctx->lsm_name,"selinux" ) !=0 &&strcmp (ctx->lsm_name,"default" ) !=0 ) {pr_warning ("c/r: RESTART_KEEP_LSM unsupported for %s\n" , ctx->lsm_name);
kernel/cred.c +2 -0
@@ -732,6 +732,8 @@ static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred)if (!h)return -ENOMEM ; +ckpt_debug ("cred uid %d fsuid %d gid %d secref %d\n" , cred->uid, + cred->fsuid, cred->gid, sec_ref); h->uid = cred->uid; h->suid = cred->suid; h->euid = cred->euid;
security/selinux/hooks.c +367 -0
417 lines not on this page · raw message
security/selinux/include/av_perm_to_string.h +5 -0
@@ -19,6 +19,8 @@ S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint") S_(SECCLASS_FILE, FILE__EXECMOD, "execmod") S_(SECCLASS_FILE, FILE__OPEN, "open") + S_(SECCLASS_FILE, FILE__RESTORE, "restore") + S_(SECCLASS_FILE, FILE__FOWN_RESTORE, "fown_restore") S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans") S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")S_ (SECCLASS_CHR_FILE ,CHR_FILE__EXECMOD ,"execmod" )
@@ -88,9 +90,11 @@ S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate") + S_(SECCLASS_PROCESS, PROCESS__RESTORE, "restore") S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") S_(SECCLASS_MSG, MSG__SEND, "send") S_(SECCLASS_MSG, MSG__RECEIVE, "receive") + S_(SECCLASS_MSG, MSG__RESTORE, "restore") S_(SECCLASS_SHM, SHM__LOCK, "lock") S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av")S_ (SECCLASS_SECURITY ,SECURITY__COMPUTE_CREATE ,"compute_create" )
@@ -107,6 +111,7 @@ S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") + S_(SECCLASS_IPC, IPC__RESTORE, "restore") S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override")S_ (SECCLASS_CAPABILITY ,CAPABILITY__DAC_READ_SEARCH ,"dac_read_search" )
security/selinux/include/av_permissions.h +5 -0
@@ -101,6 +101,8 @@#define FILE__ENTRYPOINT 0x00040000UL#define FILE__EXECMOD 0x00080000UL#define FILE__OPEN 0x00100000UL +#define FILE__RESTORE 0x00200000UL +#define FILE__FOWN_RESTORE 0x00400000UL#define LNK_FILE__IOCTL 0x00000001UL#define LNK_FILE__READ 0x00000002UL#define LNK_FILE__WRITE 0x00000004UL
@@ -453,6 +455,7 @@#define PROCESS__EXECHEAP 0x08000000UL#define PROCESS__SETKEYCREATE 0x10000000UL#define PROCESS__SETSOCKCREATE 0x20000000UL +#define PROCESS__RESTORE 0x40000000UL#define IPC__CREATE 0x00000001UL#define IPC__DESTROY 0x00000002UL#define IPC__GETATTR 0x00000004UL
@@ -462,6 +465,7 @@#define IPC__ASSOCIATE 0x00000040UL#define IPC__UNIX_READ 0x00000080UL#define IPC__UNIX_WRITE 0x00000100UL +#define IPC__RESTORE 0x00000200UL#define SEM__CREATE 0x00000001UL#define SEM__DESTROY 0x00000002UL#define SEM__GETATTR 0x00000004UL
@@ -483,6 +487,7 @@#define MSGQ__ENQUEUE 0x00000200UL#define MSG__SEND 0x00000001UL#define MSG__RECEIVE 0x00000002UL +#define MSG__RESTORE 0x00000004UL#define SHM__CREATE 0x00000001UL#define SHM__DESTROY 0x00000002UL#define SHM__GETATTR 0x00000004UL
Signature · 1 line
1.6.1
Re: [PATCH 3/3] cr: add selinux support (v4)
In reply to Serge E. HallynQuoted 44 lines · Serge E. Hallyn
Documentation/checkpoint/readme.txtbegins:
"""
Application checkpoint/restart is the ability to save the state of a running application so that it can later resume its execution from the time at which it was checkpointed.
"""This patch adds the ability to checkpoint and restore selinux contexts for tasks, open files, and sysvipc objects. Contexts are checkpointed as strings. For tasks and files, where a security struct actually points to several contexts, all contexts are written out in one string, separated by ':::'.
The default behaviors are to checkpoint contexts, but not to restore them. To attempt to restore them,
sys_restart()must be given theRESTART_KEEP_LSMflag. If this is given then the caller ofsys_restart()must have the new 'restore' permission to the target objclass, or for instancePROCESS__SETFSCREATEto itself to specify acreate_sid.There are some tests under cr_tests/selinux at
git://git.sr71.net/~hallyn/cr_tests.git.A corresponding simple refpolicy (and
/usr/share/selinux/devel/include) patch is needed.The programs to checkpoint and restart (called 'checkpoint' and 'restart') come from
git://git.ncl.cs.columbia.edu/pub/git/user-cr.git.
This patch applies against the checkpoint/restart-enabled kernel tree atgit://git.ncl.cs.columbia.edu/pub/git/linux-cr.git/.Changelog:
oct 01: Remove some debugging that is redundant with
avc log data.
sep 10: (Most addressing suggestions by Stephen Smalley)
1. changexyz_get_ctx()toxyz_checkpoint().
2. check entrypoint permission oncred_restore
3. always dec context length by 1
4. don't allowSECSID_NULLwhen that's not valid
5. whenSECSID_NULLis valid, restore it
6. c/rtask->osid
7. Just print nothing instead of 'null' forSECSID_NULL
8. sids are__u32, as are lenghts passed tosid_to_context.
Quoted 2 lines
Signed-off-by Serge E. Hallyn <[email protected]>Cc Stephen Smalley <[email protected]>
I don't know much about SElinux, so this is only for the strict c/r code...
Quoted 13 lines
--- checkpoint/restart.c | 1 + kernel/cred.c | 2 + security/selinux/hooks.c | 371 ++++++++++++++++++++++++++ security/selinux/include/av_perm_to_string.h | 4 + security/selinux/include/av_permissions.h | 4 + 5 files changed, 382 insertions(+), 0 deletions(-)checkpoint/restart.c +0
-0
checkpoint/restart.c static int restore_read_header(struct ckpt_ctx *ctx) · line 475
Quoted 5 lines
checkpoint/restart.c +1
-0@@ -471,6 +471,7 @@ static int restore_read_header(struct ckpt_ctx *ctx)/* to be implemented later, per-lsm */ if (strcmp (ctx->lsm_name,"lsm_none" ) !=0 &&strcmp (ctx->lsm_name,"smack" ) !=0 && +strcmp (ctx->lsm_name,"selinux" ) !=0 &&strcmp (ctx->lsm_name,"default" ) !=0 ) {
If we expect this to grow, it may make sense to look it up in an array.
kernel/cred.c static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred) · line 736
Quoted 12 lines
checkpoint/restart.c +0
-0pr_warning ("c/r: RESTART_KEEP_LSM unsupported for %s\n" , ctx->lsm_name);kernel/cred.c +2
-0@@ -732,6 +732,8 @@ static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred)if (!h)return -ENOMEM ; +ckpt_debug ("cred uid %d fsuid %d gid %d secref %d\n" , cred->uid, + cred->fsuid, cred->gid, sec_ref);
Please place this (and a few others also in other patches) debug-only changes in a separate patch - it will make my life tremendously easier when merging v18-dev to a nice and clean v19.
[...]
Quoted 11 lines
kernel/cred.c +11
-0+static inline char *selinux_file_checkpoint (void *security) +{ +struct file_security_struct *fsec = security; +char *s1 =NULL , *s2 =NULL , *sfull; +__u32 len1, len2, lenfull; +int ret; + +if (fsec->sid ==0 || fsec->fown_sid ==0 ) +return ERR_PTR (-EINVAL ); + + ret =security_sid_to_context (fsec->sid, &s1, &len1);
kernel/cred.c static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred)
Quoted 10 lines
kernel/cred.c +10
-0+if (ret) +return ERR_PTR (ret); + len1--; + ret =security_sid_to_context (fsec->fown_sid, &s2, &len2); +if (ret) { +kfree (s1); +return ERR_PTR (ret); + } + len2--; + lenfull = len1+len2+3 ;
Would checkpatch.pl complain about no spaces here ?
[...]
Hmm... the rest doesn't make sense to me anyway :o
Oren.
Re: [PATCH 3/3] cr: add selinux support (v4)
Quoted 15 lines · Oren Laadan
checkpoint/restart.c static int restore_read_header(struct ckpt_ctx *ctx) · line 475
Quoted 10 lines · Serge E. Hallyn
checkpoint/restart.c +1
-0@@ -471,6 +471,7 @@ static int restore_read_header(struct ckpt_ctx *ctx)/* to be implemented later, per-lsm */ if (strcmp (ctx->lsm_name,"lsm_none" ) !=0 &&strcmp (ctx->lsm_name,"smack" ) !=0 && +strcmp (ctx->lsm_name,"selinux" ) !=0 &&strcmp (ctx->lsm_name,"default" ) !=0 ) {If we expect this to grow, it may make sense to look it up in an array.
We don't :) The only other LSM in the kernel right now is TOMOYO.
Quoted 10 lines
Quoted 10 lines
checkpoint/restart.c +0
-0pr_warning ("c/r: RESTART_KEEP_LSM unsupported for %s\n" , ctx->lsm_name);kernel/cred.c +0
-0@@ -732,6 +732,8 @@ static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred)if (!h)return -ENOMEM ;
Quoted 6 lines
kernel/cred.c static int do_checkpoint_cred(struct ckpt_ctx *ctx, struct cred *cred) · line 736
Quoted 2 lines
kernel/cred.c +2
-0+ckpt_debug ("cred uid %d fsuid %d gid %d secref %d\n" , cred->uid, + cred->fsuid, cred->gid, sec_ref);Please place this (and a few others also in other patches) debug-only changes in a separate patch - it will make my life tremendously easier when merging v18-dev to a nice and clean v19.
Ok, I'll resend those just to containers@ to spare the lsm folks.
Quoted 17 lines
[...]
Quoted 15 lines
kernel/cred.c +15
-0+static inline char *selinux_file_checkpoint (void *security) +{ +struct file_security_struct *fsec = security; +char *s1 =NULL , *s2 =NULL , *sfull; +__u32 len1, len2, lenfull; +int ret; + +if (fsec->sid ==0 || fsec->fown_sid ==0 ) +return ERR_PTR (-EINVAL ); + + ret =security_sid_to_context (fsec->sid, &s1, &len1); +if (ret) +return ERR_PTR (ret); + len1--; + ret =security_sid_to_context (fsec->fown_sid, &s2, &len2);
Quoted 8 lines
kernel/cred.c
Quoted 6 lines
kernel/cred.c +6
-0+if (ret) { +kfree (s1); +return ERR_PTR (ret); + } + len2--; + lenfull = len1+len2+3 ;Would checkpatch.pl complain about no spaces here ?
Hmm, it doesn't, actually... you'd think it should! I'll change that in the split-up version I'll send in a bit.
thanks,
-serge
Re: [PATCH 3/3] cr: add selinux support (v4)
Quoted 6 lines · Serge E. Hallyn
Quoted 3 lines · Oren Laadan
Please place this (and a few others also in other patches) debug-only changes in a separate patch - it will make my life tremendously easier when merging v18-dev to a nice and clean v19.
Ok, I'll resend those just to containers@ to spare the lsm folks.
Oops, I was thinking this was the patch 1/3. I won't spare the lsm folks from revised patches 2/3 or 3/3 :)
-serge