public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 04/22] CRED: Request a credential record for a kernel service
  2007-09-21 14:47 [PATCH 00/22] Introduce credential record David Howells
@ 2007-09-21 14:47 ` David Howells
  0 siblings, 0 replies; 3+ messages in thread
From: David Howells @ 2007-09-21 14:47 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells

Request a credential record for the named kernel service.  This produces a
cred struct with appropriate DAC and MAC controls for effecting that service.
It may be used to override the credentials on a task to do work on that task's
behalf.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 include/linux/cred.h     |    2 +
 include/linux/security.h |   45 ++++++++++++++++++++++++++++++
 kernel/cred.c            |   68 ++++++++++++++++++++++++++++++++++++++++++++++
 security/dummy.c         |   13 +++++++++
 security/selinux/hooks.c |   47 ++++++++++++++++++++++++++++++++
 5 files changed, 175 insertions(+), 0 deletions(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index f2df1c3..fcbfc89 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -49,6 +49,8 @@ extern void change_fsgid(struct cred *, gid_t);
 extern void change_groups(struct cred *, struct group_info *);
 extern void change_cap(struct cred *, kernel_cap_t);
 extern struct cred *dup_cred(const struct cred *);
+extern struct cred *get_kernel_cred(const char *, struct task_struct *);
+extern int change_create_files_as(struct cred *, struct inode *);
 
 /**
  * get_cred - Get an extra reference on a credentials record
diff --git a/include/linux/security.h b/include/linux/security.h
index 74cc204..7f11e6d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -514,6 +514,20 @@ struct request_sock;
  * @cred_destroy:
  *	Destroy the credentials attached to a cred structure.
  *	@cred points to the credentials structure that is to be destroyed.
+ * @cred_kernel_act_as:
+ *	Set the credentials for a kernel service to act as (subjective context).
+ *	@cred points to the credentials structure to be filled in.
+ *	@service names the service making the request.
+ *	@daemon: A userspace daemon to be used as a base for the context.
+ *	@dentry: A file or dir to be used as a base for the file creation
+ *	  context.
+ *	Return 0 if successful.
+ * @cred_create_files_as:
+ *	Set the file creation context in a credentials record to be the same as
+ *	the objective context of an inode.
+ *	@cred points to the credentials structure to be altered.
+ *	@inode points to the inode to use as a reference.
+ *	Return 0 if successful.
  *
  * Security hooks for task operations.
  *
@@ -1270,6 +1284,9 @@ struct security_operations {
 
 	int (*cred_dup)(struct cred *cred);
 	void (*cred_destroy)(struct cred *cred);
+	int (*cred_kernel_act_as)(struct cred *cred, const char *service,
+			       struct task_struct *daemon);
+	int (*cred_create_files_as)(struct cred *cred, struct inode *inode);
 
 	int (*task_create) (unsigned long clone_flags);
 	int (*task_alloc_security) (struct task_struct * p);
@@ -1888,6 +1905,21 @@ static inline void security_cred_destroy(struct cred *cred)
 	return security_ops->cred_destroy(cred);
 }
 
+static inline int security_cred_kernel_act_as(struct cred *cred,
+					   const char *service,
+					   struct task_struct *daemon)
+{
+	return security_ops->cred_kernel_act_as(cred, service, daemon);
+}
+
+static inline int security_cred_create_files_as(struct cred *cred,
+						struct inode *inode)
+{
+	if (IS_PRIVATE(inode))
+		return -EINVAL;
+	return security_ops->cred_create_files_as(cred, inode);
+}
+
 static inline int security_task_create (unsigned long clone_flags)
 {
 	return security_ops->task_create (clone_flags);
@@ -2579,6 +2611,19 @@ static inline void security_cred_destroy(struct cred *cred)
 {
 }
 
+static inline int security_cred_kernel_act_as(struct cred *cred,
+					      const char *service,
+					      struct task_struct *daemon)
+{
+	return 0;
+}
+
+static inline int security_cred_create_files_as(struct cred *cred,
+						struct inode *inode)
+{
+	return 0;
+}
+
 static inline int security_task_create (unsigned long clone_flags)
 {
 	return 0;
diff --git a/kernel/cred.c b/kernel/cred.c
index c391f66..46a6661 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -206,3 +206,71 @@ void change_cap(struct cred *cred, kernel_cap_t cap)
 }
 
 EXPORT_SYMBOL(change_cap);
+
+/**
+ * get_kernel_cred - Get credentials for a named kernel service
+ * @service: The name of the service
+ * @daemon: A userspace daemon to be used as a base for the context
+ *
+ * Get a set of credentials for a specific kernel service.  These can then be
+ * used to override a task's credentials so that work can be done on behalf of
+ * that task.
+ *
+ * @daemon is used to provide a base for the security context, but can be NULL.
+ * If @deamon is supplied, then the cred's uid, gid and groups list will be
+ * derived from that; otherwise they'll be set to 0 and no groups.
+ *
+ * @daemon is also passd to the LSM module as a base from which to initialise
+ * any MAC controls.
+ *
+ * The caller may change these controls afterwards if desired.
+ */
+struct cred *get_kernel_cred(const char *service,
+			     struct task_struct *daemon)
+{
+	struct cred *cred, *dcred;
+	int ret;
+
+	cred = kzalloc(sizeof *cred, GFP_KERNEL);
+	if (!cred)
+		return ERR_PTR(-ENOMEM);
+
+	if (daemon) {
+		rcu_read_lock();
+		dcred = task_cred(daemon);
+		cred->uid = dcred->uid;
+		cred->gid = dcred->gid;
+		cred->group_info = dcred->group_info;
+		atomic_inc(&cred->group_info->usage);
+		rcu_read_unlock();
+	} else {
+		cred->group_info = &init_groups;
+		atomic_inc(&init_groups.usage);
+	}
+
+	ret = security_cred_kernel_act_as(cred, service, daemon);
+	if (ret < 0) {
+		put_cred(cred);
+		return ERR_PTR(ret);
+	}
+
+	return cred;
+}
+
+EXPORT_SYMBOL(get_kernel_cred);
+
+/**
+ * change_create_files_as - Change the file creation context in a new cred record
+ * @cred: The credential record to alter
+ * @inode: The inode to take the context from
+ *
+ * Change the file creation context in a new credentials record to be the same
+ * as the object context of the specified inode, so that the new inodes have
+ * the same MAC context as that inode.
+ */
+int change_create_files_as(struct cred *cred, struct inode *inode)
+{
+	return security_cred_create_files_as(cred, inode);
+}
+
+EXPORT_SYMBOL(change_create_files_as);
diff --git a/security/dummy.c b/security/dummy.c
index f403658..004bb21 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -488,6 +488,17 @@ static void dummy_cred_destroy(struct cred *cred)
 {
 }
 
+static int dummy_cred_kernel_act_as(struct cred *cred, const char *service,
+				    struct task_struct *daemon)
+{
+	return 0;
+}
+
+static int dummy_cred_create_files_as(struct cred *cred, struct inode *inode)
+{
+	return 0;
+}
+
 static int dummy_task_create (unsigned long clone_flags)
 {
 	return 0;
@@ -1063,6 +1074,8 @@ void security_fixup_ops (struct security_operations *ops)
 	set_to_dummy_if_null(ops, file_receive);
 	set_to_dummy_if_null(ops, cred_dup);
 	set_to_dummy_if_null(ops, cred_destroy);
+	set_to_dummy_if_null(ops, cred_kernel_act_as);
+	set_to_dummy_if_null(ops, cred_create_files_as);
 	set_to_dummy_if_null(ops, task_create);
 	set_to_dummy_if_null(ops, task_alloc_security);
 	set_to_dummy_if_null(ops, task_free_security);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4e72dbb..fa11211 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2771,6 +2771,51 @@ static void selinux_cred_destroy(struct cred *cred)
 	kfree(cred->security);
 }
 
+/*
+ * get the credentials for a kernel service, deriving the subjective context
+ * from the credentials of a userspace daemon if one supplied
+ * - all the creation contexts are set to unlabelled
+ */
+static int selinux_cred_kernel_act_as(struct cred *cred,
+				      const char *service,
+				      struct task_struct *daemon)
+{
+	struct task_security_struct *tsec;
+	struct cred_security_struct *csec;
+	u32 ksid;
+	int ret;
+
+	tsec = daemon ? daemon->security : init_task.security;
+
+	ret = security_transition_sid(tsec->victim_sid, SECINITSID_KERNEL,
+				      SECCLASS_PROCESS, &ksid);
+	if (ret < 0)
+		return ret;
+
+	csec = kzalloc(sizeof(struct cred_security_struct), GFP_KERNEL);
+	if (!csec)
+		return -ENOMEM;
+
+	csec->action_sid = ksid;
+	csec->create_sid = SECINITSID_UNLABELED;
+	csec->keycreate_sid = SECINITSID_UNLABELED;
+	csec->sockcreate_sid = SECINITSID_UNLABELED;
+	cred->security = csec;
+	return 0;
+}
+
+/*
+ * set the file creation context in a credentials record to the same as the
+ * objective context of the specified inode
+ */
+static int selinux_cred_create_files_as(struct cred *cred, struct inode *inode)
+{
+	struct cred_security_struct *csec = cred->security;
+	struct inode_security_struct *isec = inode->i_security;
+
+	csec->create_sid = isec->sid;
+	return 0;
+}
 
 /* task security operations */
 
@@ -4887,6 +4932,8 @@ static struct security_operations selinux_ops = {
 
 	.cred_dup =			selinux_cred_dup,
 	.cred_destroy =			selinux_cred_destroy,
+	.cred_kernel_act_as =		selinux_cred_kernel_act_as,
+	.cred_create_files_as =		selinux_cred_create_files_as,
 
 	.task_create =			selinux_task_create,
 	.task_alloc_security =		selinux_task_alloc_security,


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 04/22] CRED: Request a credential record for a kernel service
@ 2007-09-25 19:20 Jonathan Corbet
  2007-09-25 19:27 ` David Howells
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Corbet @ 2007-09-25 19:20 UTC (permalink / raw)
  To: David Howells
  Cc: viro, hch, Trond.Myklebust, sds, casey, linux-kernel, selinux,
	linux-security-module

Hi, David,

One little thing I noticed:

> + * @cred_kernel_act_as:
> + *	Set the credentials for a kernel service to act as (subjective context).
> + *	@cred points to the credentials structure to be filled in.
> + *	@service names the service making the request.
> + *	@daemon: A userspace daemon to be used as a base for the context.
> + *	@dentry: A file or dir to be used as a base for the file creation
> + *	  context.
> + *	Return 0 if successful.

The comment describes a "dentry" argument, but the actual function does
not have that argument.

jon

Jonathan Corbet / LWN.net / corbet@lwn.net

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 04/22] CRED: Request a credential record for a kernel service
  2007-09-25 19:20 [PATCH 04/22] CRED: Request a credential record for a kernel service Jonathan Corbet
@ 2007-09-25 19:27 ` David Howells
  0 siblings, 0 replies; 3+ messages in thread
From: David Howells @ 2007-09-25 19:27 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: dhowells, viro, hch, Trond.Myklebust, sds, casey, linux-kernel,
	selinux, linux-security-module

Jonathan Corbet <corbet@lwn.net> wrote:

> The comment describes a "dentry" argument, but the actual function does
> not have that argument.

oops.  Yeah, I decided I didn't want that there.

David

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-09-25 19:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-25 19:20 [PATCH 04/22] CRED: Request a credential record for a kernel service Jonathan Corbet
2007-09-25 19:27 ` David Howells
  -- strict thread matches above, loose matches on Subject: below --
2007-09-21 14:47 [PATCH 00/22] Introduce credential record David Howells
2007-09-21 14:47 ` [PATCH 04/22] CRED: Request a credential record for a kernel service David Howells

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox