All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Serge E. Hallyn" <serue@us.ibm.com>
To: Oren Laadan <orenl@librato.com>
Cc: Linux Containers <containers@lists.osdl.org>,
	Casey Schaufler <casey@schaufler-ca.com>,
	linux-security-module@vger.kernel.org,
	Stephen Smalley <sds@epoch.ncsc.mil>,
	SELinux <selinux@tycho.nsa.gov>
Subject: Re: [PATCH 1/3] cr: add generic LSM c/r support (v4)
Date: Fri, 2 Oct 2009 17:13:49 -0500	[thread overview]
Message-ID: <20091002221349.GC7446@us.ibm.com> (raw)
In-Reply-To: <4AC6694F.3050509@librato.com>

Quoting Oren Laadan (orenl@librato.com):
> 
> 
> Serge E. Hallyn wrote:
> > (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.
> > """
> > 
> 
> [...]
> 
> >  Kernel interfaces
> >  =================
> > diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
> > index 1eeb557..6722035 100644
> > --- a/checkpoint/checkpoint.c
> > +++ b/checkpoint/checkpoint.c
> > @@ -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;
> > +
> 
> 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.

> >  	return checkpoint_write_header_arch(ctx);
> >  }
> >  
> > diff --git a/checkpoint/files.c b/checkpoint/files.c
> > index 27e29a0..570facb 100644
> > --- a/checkpoint/files.c
> > +++ b/checkpoint/files.c
> > @@ -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;
> 
> #define CKPT_SECURITY_NONE  -1     ??

Yeah, that'd be cleaner.

> > +	else if (h->f_secref < 0)
> > +		return h->f_secref;
> 
> [...]
> 
> > +
> > +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

> > +	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;
> > +
> > +	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()

Huh.  I had no idea :)

> > +		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 ?

ok

> [...]
> 
> > @@ -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.

> > +		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);
> > diff --git a/checkpoint/restart.c b/checkpoint/restart.c
> > index b12c8bd..bba2b45 100644
> > --- a/checkpoint/restart.c
> > +++ b/checkpoint/restart.c
> > @@ -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;
> 
> EPERM ?

Hmm...   I think of this not as "you're not allowed" but rather "it doesn't
make sense."

> [...]
> 
> > @@ -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 ...
> 
> > +	/*
> > +	 * 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;
> 
> No need for padding here.
> 
> >  } __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.
> 
> [...]
> 
> > @@ -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.

ok

> > +		ret = security_msg_msg_restore(msg, l->string);
> > +		if (ret)
> > +			return ERR_PTR(ret);
> 
> Here too.
> 
> [...]
> 
> > @@ -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 ?
> 
> > +/**
> > + * 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 */
> > +	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.

> > +	if (!l) {
> > +		kfree(str);
> > +		return -ENOMEM;
> > +	}
> > +	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.

Thanks!  Will send a new version.

-serge

WARNING: multiple messages have this Message-ID (diff)
From: "Serge E. Hallyn" <serue@us.ibm.com>
To: Oren Laadan <orenl@librato.com>
Cc: Linux Containers <containers@lists.osdl.org>,
	Casey Schaufler <casey@schaufler-ca.com>,
	linux-security-module@vger.kernel.org,
	Stephen Smalley <sds@epoch.ncsc.mil>,
	SELinux <selinux@tycho.nsa.gov>
Subject: Re: [PATCH 1/3] cr: add generic LSM c/r support (v4)
Date: Fri, 2 Oct 2009 17:13:49 -0500	[thread overview]
Message-ID: <20091002221349.GC7446@us.ibm.com> (raw)
In-Reply-To: <4AC6694F.3050509@librato.com>

Quoting Oren Laadan (orenl@librato.com):
> 
> 
> Serge E. Hallyn wrote:
> > (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.
> > """
> > 
> 
> [...]
> 
> >  Kernel interfaces
> >  =================
> > diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
> > index 1eeb557..6722035 100644
> > --- a/checkpoint/checkpoint.c
> > +++ b/checkpoint/checkpoint.c
> > @@ -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;
> > +
> 
> 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.

> >  	return checkpoint_write_header_arch(ctx);
> >  }
> >  
> > diff --git a/checkpoint/files.c b/checkpoint/files.c
> > index 27e29a0..570facb 100644
> > --- a/checkpoint/files.c
> > +++ b/checkpoint/files.c
> > @@ -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;
> 
> #define CKPT_SECURITY_NONE  -1     ??

Yeah, that'd be cleaner.

> > +	else if (h->f_secref < 0)
> > +		return h->f_secref;
> 
> [...]
> 
> > +
> > +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

> > +	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;
> > +
> > +	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()

Huh.  I had no idea :)

> > +		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 ?

ok

> [...]
> 
> > @@ -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.

> > +		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);
> > diff --git a/checkpoint/restart.c b/checkpoint/restart.c
> > index b12c8bd..bba2b45 100644
> > --- a/checkpoint/restart.c
> > +++ b/checkpoint/restart.c
> > @@ -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;
> 
> EPERM ?

Hmm...   I think of this not as "you're not allowed" but rather "it doesn't
make sense."

> [...]
> 
> > @@ -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 ...
> 
> > +	/*
> > +	 * 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;
> 
> No need for padding here.
> 
> >  } __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.
> 
> [...]
> 
> > @@ -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.

ok

> > +		ret = security_msg_msg_restore(msg, l->string);
> > +		if (ret)
> > +			return ERR_PTR(ret);
> 
> Here too.
> 
> [...]
> 
> > @@ -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 ?
> 
> > +/**
> > + * 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 */
> > +	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.

> > +	if (!l) {
> > +		kfree(str);
> > +		return -ENOMEM;
> > +	}
> > +	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.

Thanks!  Will send a new version.

-serge

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

  reply	other threads:[~2009-10-02 22:13 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-02  3:49 [PATCH 1/3] cr: add generic LSM c/r support (v4) Serge E. Hallyn
2009-10-02  3:49 ` Serge E. Hallyn
2009-10-02  3:52 ` [PATCH 2/3] cr: add smack support to lsm c/r (v4) Serge E. Hallyn
2009-10-02  3:52 ` [PATCH 3/3] cr: add selinux support (v4) Serge E. Hallyn
2009-10-02  3:52   ` Serge E. Hallyn
2009-10-02 12:59   ` Stephen Smalley
2009-10-02 12:59     ` Stephen Smalley
2009-10-02 21:55     ` Serge E. Hallyn
2009-10-02 21:55       ` Serge E. Hallyn
2009-10-02 21:14   ` Oren Laadan
2009-10-02 22:05     ` Serge E. Hallyn
2009-10-02 22:05       ` Serge E. Hallyn
2009-10-02 22:14       ` Serge E. Hallyn
2009-10-02 22:14         ` Serge E. Hallyn
     [not found] ` <20091002034916.GA16871-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-02  3:51   ` [PATCH 1/1] restart: accept the lsm_name field in header and add -k flag Serge E. Hallyn
     [not found]     ` <20091002035157.GA16920-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2009-10-02 21:02       ` Oren Laadan
2009-10-02 20:57   ` [PATCH 1/3] cr: add generic LSM c/r support (v4) Oren Laadan
2009-10-02 22:13     ` Serge E. Hallyn [this message]
2009-10-02 22:13       ` Serge E. Hallyn
2009-10-02 22:23       ` Oren Laadan
2009-10-02 22:31         ` Serge E. Hallyn
2009-10-02 22:31           ` Serge E. Hallyn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20091002221349.GC7446@us.ibm.com \
    --to=serue@us.ibm.com \
    --cc=casey@schaufler-ca.com \
    --cc=containers@lists.osdl.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=orenl@librato.com \
    --cc=sds@epoch.ncsc.mil \
    --cc=selinux@tycho.nsa.gov \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.