The policy is 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) Signed-off-by: Serge E. Hallyn <serue@xxxxxxxxxx> --- checkpoint/restart.c | 1 + security/security.c | 8 ++++ security/smack/smack_lsm.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 0 deletions(-) diff --git a/checkpoint/restart.c b/checkpoint/restart.c index 6fb9359..0b8d29d 100644 --- a/checkpoint/restart.c +++ b/checkpoint/restart.c @@ -378,6 +378,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); diff --git a/security/security.c b/security/security.c index 6bafb9e..d198d0c 100644 --- a/security/security.c +++ b/security/security.c @@ -1316,6 +1316,14 @@ int security_checkpoint_obj(struct ckpt_ctx *ctx, void *security, char *str; int len; + /* + * to simplify the LSM code, short-cut a null security + * here - hopefully not actually needed; test without + * this one day. + */ + if (!security) + return -EOPNOTSUPP; + switch (sectype) { case CKPT_SECURITY_MSG_MSG: str = security_msg_msg_get_ctx(security); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0023182..279fdce 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -892,6 +892,28 @@ static int smack_file_permission(struct file *file, int mask) return 0; } +static inline char *smack_file_get_ctx(void *security) +{ + return kstrdup((char *)security, GFP_KERNEL); +} + +static inline int smack_file_restore(struct file *file, char *ctx) +{ + char *newsmack = smk_import(ctx, 0); + + if (newsmack == NULL) + return -EINVAL; + /* I think by definition, file->f_security == current_security + * right now, but let's assume somehow it might not be */ + if (newsmack == file->f_security) + return 0; + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + file->f_security = newsmack; + + return 0; +} + /** * smack_file_alloc_security - assign a file security blob * @file: the object @@ -1079,6 +1101,26 @@ static int smack_file_receive(struct file *file) * Task hooks */ +static inline char *smack_cred_get_ctx(void *security) +{ + return kstrdup((char *)security, GFP_KERNEL); +} + +static inline int smack_cred_restore(struct cred *cred, char *ctx) +{ + char *newsmack = smk_import(ctx, 0); + + if (newsmack == NULL) + return -EINVAL; + if (newsmack == cred->security) + return 0; + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + cred->security = newsmack; + + return 0; +} + /** * smack_cred_free - "free" task-level security credentials * @cred: the credentials in question @@ -1742,6 +1784,26 @@ static int smack_msg_msg_alloc_security(struct msg_msg *msg) return 0; } +static inline char *smack_msg_msg_get_ctx(void *security) +{ + return kstrdup((char *)security, GFP_KERNEL); +} + +static inline int smack_msg_msg_restore(struct msg_msg *msg, char *ctx) +{ + char *newsmack = smk_import(ctx, 0); + + if (newsmack == NULL) + return -EINVAL; + if (newsmack == msg->security) + return 0; + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + msg->security = newsmack; + + return 0; +} + /** * smack_msg_msg_free_security - Clear the security blob for msg_msg * @msg: the object @@ -2175,6 +2237,26 @@ static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) *secid = smack_to_secid(smack); } +static inline char *smack_ipc_get_ctx(void *security) +{ + return kstrdup((char *)security, GFP_KERNEL); +} + +static inline int smack_ipc_restore(struct kern_ipc_perm *ipcp, char *ctx) +{ + char *newsmack = smk_import(ctx, 0); + + if (newsmack == NULL) + return -EINVAL; + if (newsmack == ipcp->security) + return 0; + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + ipcp->security = newsmack; + + return 0; +} + /** * smack_d_instantiate - Make sure the blob is correct on an inode * @opt_dentry: unused @@ -3064,6 +3146,8 @@ struct security_operations smack_ops = { .inode_getsecid = smack_inode_getsecid, .file_permission = smack_file_permission, + .file_get_ctx = smack_file_get_ctx, + .file_restore = smack_file_restore, .file_alloc_security = smack_file_alloc_security, .file_free_security = smack_file_free_security, .file_ioctl = smack_file_ioctl, @@ -3073,6 +3157,8 @@ struct security_operations smack_ops = { .file_send_sigiotask = smack_file_send_sigiotask, .file_receive = smack_file_receive, + .cred_get_ctx = smack_cred_get_ctx, + .cred_restore = smack_cred_restore, .cred_free = smack_cred_free, .cred_prepare = smack_cred_prepare, .cred_commit = smack_cred_commit, @@ -3094,8 +3180,12 @@ struct security_operations smack_ops = { .ipc_permission = smack_ipc_permission, .ipc_getsecid = smack_ipc_getsecid, + .ipc_get_ctx = smack_ipc_get_ctx, + .ipc_restore = smack_ipc_restore, .msg_msg_alloc_security = smack_msg_msg_alloc_security, + .msg_msg_get_ctx = smack_msg_msg_get_ctx, + .msg_msg_restore = smack_msg_msg_restore, .msg_msg_free_security = smack_msg_msg_free_security, .msg_queue_alloc_security = smack_msg_queue_alloc_security, -- 1.6.1 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers