[Devel] Re: [PATCH 2/4] cr: add generic LSM c/r support (v5)

Oren Laadan orenl at librato.com
Thu Oct 15 07:57:30 PDT 2009



Serge E. Hallyn wrote:
> 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)

[...]

Can you please pull this part, which adds a global "container" section
to the checkpoint image, into a separate patch ?

(It will be helpful for folding the patches into ckpt-v19 eventually).

And IIRC, this needs to be accompanied by a user-cr patch, right ?

> diff --git a/Documentation/checkpoint/readme.txt b/Documentation/checkpoint/readme.txt
> index 571c469..9c6422c 100644
> --- a/Documentation/checkpoint/readme.txt
> +++ b/Documentation/checkpoint/readme.txt
> @@ -161,9 +161,10 @@ in-userspace conversion tools.
>  
>  The general format of the checkpoint image is as follows:
>  1. Image header
> -2. Task hierarchy
> -3. Tasks' state
> -4. Image trailer
> +2. Container configuration
> +3. Task hierarchy
> +4. Tasks' state
> +5. Image trailer
>  
>  The image always begins with a general header that holds a magic
>  number, an architecture identifier (little endian format), a format
> @@ -172,6 +173,11 @@ version number (@rev), followed by information about the kernel
>  checkpoint and the flags given to sys_checkpoint(). This header is
>  followed by an arch-specific header.
>  
> +The container configuration section contains details about the
> +security (LSM) configuration.  Network configuration and
> +container-wide mounts may also go here, so that the userspace
> +restart coordinator can re-create a suitable environment.
> +
>  The task hierarchy comes next so that userspace tools can read it
>  early (even from a stream) and re-create the restarting tasks. This is
>  basically an array of all checkpointed tasks, and their relationships
> @@ -333,6 +339,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.

[...]

> +/*
> + * We restore a security label only if
> + * 1. sys_restart specified RESTART_KEEP_LSM
> + * 2. the checkpointed security context was not SECURITY_CTX_NONE
> + */
> +static inline int ckpt_restore_lsm_label(struct ckpt_ctx *ctx, int sec_ref)

Maybe add 'may' somewhere inside tol make it more descriptive ?
(e.g. ckpt_may_restore_lsm_label)

> +{
> +	if ((ctx->uflags & RESTART_KEEP_LSM) && (sec_ref != SECURITY_CTX_NONE))
> +		return 1;
> +	return 0;
> +}
> +

[...]

>  
> +/* stored on hashtable */
> +struct ckpt_stored_lsm {
> +	struct kref kref;
> +	int sectype;
> +	char *string;
> +};

Nit: maybe ckpt_lsm_str(ing) ?

[...]

> +#ifdef CONFIG_CHECKPOINT
> +
> +/**
> + * 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 secref, len, new, ret, fulllen;
> +	char *str;
> +	struct ckpt_hdr_lsm *h;
> +
> +	if (!security)
> +		return -EOPNOTSUPP;
> +
> +	secref = ckpt_obj_lookup_add(ctx, security, CKPT_OBJ_CHECKPOINT_SEC,
> +					&new);
> +	if (!new)
> +		return secref;
> +
> +	ret = ckpt_write_objref(ctx, CKPT_OBJ_SEC, secref);
> +	if (ret < 0)
> +		return ret;
> +
> +	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;
> +	}

Let me suggest a different scheme (also last night's IRC); I think it's
less hackish and uses better the existing {checkpoint,restore}_obj().

* Define one obj type CKPT_OBJ_SEC_{IPC, MSG_MSG, FILE, CRED}, with
matching c/r functions security_{c,r}_{ipc,msg_msg,file,cred}_obj()

* Define one obj type for the string representation CKPT_OBJ_SEC_STR
with matchin c/r functions security_{c,r}_string_obj()

* The helper will now:

	security_checkpoint_obj()
	{
		switch (type) {
		case CKPT_OBJ_SEC_IPC:
			ret = checkpoint_obj(ctx, sec, CKPT_OBJ_SEC_IPC);
			break;
		case CKPT_OBJ_SEC_CRED:
			ret = checkpoint_obj(ctx, sec, CKPT_OBJ_SEC_CRED);
		...
	}

	security_checkpoint_ipc_obj()
	{
		...
		ckpt_lsm_str = str_from_sec_ipc();   /* like you do now */
		objref = checkpoint_obj(ctx, ckpt_lsm_str, CKPT_OBJ_SEC_STR);
		...
		h->objref = objref;
		ckpt_write_obj();
	}

Perhaps a variation on this where the string is checkpoint_obj()'ed
first would also work.

I haven't looked at all the details, but I hope something along these
lines would help untangle the current mess.

Oren.
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers




More information about the Devel mailing list