public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "J. Bruce Fields" <bfields@fieldses.org>
To: David Howells <dhowells@redhat.com>
Cc: sds@tycho.nsa.gov, casey@schaufler-ca.com,
	Trond.Myklebust@netapp.com, neilb@suse.de,
	linux-kernel@vger.kernel.org, selinux@tycho.nsa.gov,
	linux-security-module@vger.kernel.org, nfs@lists.sourceforge.net
Subject: Re: [PATCH 06b/26] Security: Make NFSD work with detached security
Date: Thu, 17 Jan 2008 15:48:04 -0500	[thread overview]
Message-ID: <20080117204804.GC6416@fieldses.org> (raw)
In-Reply-To: <20849.1200590240@redhat.com>

On Thu, Jan 17, 2008 at 05:17:20PM +0000, David Howells wrote:
> 
> Make NFSD work with detached security, using the patches that excise the
> security information from task_struct to struct task_security as a base.
> 
> Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to
> do NFS operations), a task_security record is derived from NFSD's *objective*
> security, modified and then applied as the *subjective* security.  This means
> (a) the changes are not visible to anyone looking at NFSD through /proc, (b)
> there is no leakage between two consecutive ops with different security
> configurations.
> 
> Consideration should probably be given to caching the task_security record on
> the basis that there'll probably be several ops that will want to use any
> particular security configuration.

Just curious--why?  Are get_kernel_security(), etc., particularly
expensive?

--b.

> 
> Furthermore, nfs4recover.c perhaps ought to set an appropriate LSM context on
> the record pointed to by rec_security so that the disk is accessed
> appropriately (see set_security_override[_from_ctx]()).
> 
> NOTE!  This patch must be and will be rolled in to patch 06 of 26 to make the
> latter compile fully, however it may be useful to the nfsd maintainers to see
> it as a separate patch.
> 
> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
> 
>  fs/nfsd/auth.c        |   31 +++++++++++++++++-------
>  fs/nfsd/nfs4recover.c |   64 +++++++++++++++++++++++++++++++------------------
>  include/linux/sched.h |    1 +
>  kernel/sys.c          |   27 ++++++++++++++++++---
>  4 files changed, 86 insertions(+), 37 deletions(-)
> 
> 
> diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
> index 2192805..462d989 100644
> --- a/fs/nfsd/auth.c
> +++ b/fs/nfsd/auth.c
> @@ -6,6 +6,7 @@
>  
>  #include <linux/types.h>
>  #include <linux/sched.h>
> +#include <linux/cred.h>
>  #include <linux/sunrpc/svc.h>
>  #include <linux/sunrpc/svcauth.h>
>  #include <linux/nfsd/nfsd.h>
> @@ -28,11 +29,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
>  
>  int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
>  {
> +	struct task_security *sec, *old;
>  	struct svc_cred	cred = rqstp->rq_cred;
>  	int i;
>  	int flags = nfsexp_flags(rqstp, exp);
>  	int ret;
>  
> +	/* derive the new security record from nfsd's objective security */
> +	sec = get_kernel_security(current);
> +	if (!sec)
> +		return -ENOMEM;
> +
>  	if (flags & NFSEXP_ALLSQUASH) {
>  		cred.cr_uid = exp->ex_anon_uid;
>  		cred.cr_gid = exp->ex_anon_gid;
> @@ -56,23 +63,29 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
>  		get_group_info(cred.cr_group_info);
>  
>  	if (cred.cr_uid != (uid_t) -1)
> -		current->fsuid = cred.cr_uid;
> +		sec->fsuid = cred.cr_uid;
>  	else
> -		current->fsuid = exp->ex_anon_uid;
> +		sec->fsuid = exp->ex_anon_uid;
>  	if (cred.cr_gid != (gid_t) -1)
> -		current->fsgid = cred.cr_gid;
> +		sec->fsgid = cred.cr_gid;
>  	else
> -		current->fsgid = exp->ex_anon_gid;
> +		sec->fsgid = exp->ex_anon_gid;
>  
> -	if (!cred.cr_group_info)
> +	if (!cred.cr_group_info) {
> +		put_task_security(sec);
>  		return -ENOMEM;
> -	ret = set_current_groups(cred.cr_group_info);
> +	}
> +	ret = set_groups(sec, cred.cr_group_info);
>  	put_group_info(cred.cr_group_info);
>  	if ((cred.cr_uid)) {
> -		cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
> +		cap_t(sec->cap_effective) &= ~CAP_NFSD_MASK;
>  	} else {
> -		cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
> -						  current->cap_permitted);
> +		cap_t(sec->cap_effective) |= CAP_NFSD_MASK & sec->cap_permitted;
>  	}
> +
> +	/* set the new security as nfsd's subjective security */
> +	old = current->act_as;
> +	current->act_as = sec;
> +	put_task_security(old);
>  	return ret;
>  }
> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> index 1602cd0..ae91262 100644
> --- a/fs/nfsd/nfs4recover.c
> +++ b/fs/nfsd/nfs4recover.c
> @@ -46,27 +46,37 @@
>  #include <linux/scatterlist.h>
>  #include <linux/crypto.h>
>  #include <linux/sched.h>
> +#include <linux/cred.h>
>  
>  #define NFSDDBG_FACILITY                NFSDDBG_PROC
>  
>  /* Globals */
>  static struct nameidata rec_dir;
>  static int rec_dir_init = 0;
> +static struct task_security *rec_security;
>  
> +/*
> + * switch the special recovery access security in on the current task's
> + * subjective security
> + */
>  static void
> -nfs4_save_user(uid_t *saveuid, gid_t *savegid)
> +nfs4_begin_secure(struct task_security **saved_sec)
>  {
> -	*saveuid = current->fsuid;
> -	*savegid = current->fsgid;
> -	current->fsuid = 0;
> -	current->fsgid = 0;
> +	*saved_sec = current->act_as;
> +	current->act_as = get_task_security(rec_security);
>  }
>  
> +/*
> + * return the current task's subjective security to its former glory
> + */
>  static void
> -nfs4_reset_user(uid_t saveuid, gid_t savegid)
> +nfs4_end_secure(struct task_security *saved_sec)
>  {
> -	current->fsuid = saveuid;
> -	current->fsgid = savegid;
> +	struct task_security *discard;
> +
> +	discard = current->act_as;
> +	current->act_as = saved_sec;
> +	put_task_security(discard);
>  }
>  
>  static void
> @@ -128,10 +138,9 @@ nfsd4_sync_rec_dir(void)
>  int
>  nfsd4_create_clid_dir(struct nfs4_client *clp)
>  {
> +	struct task_security *saved_sec;
>  	char *dname = clp->cl_recdir;
>  	struct dentry *dentry;
> -	uid_t uid;
> -	gid_t gid;
>  	int status;
>  
>  	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
> @@ -139,7 +148,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
>  	if (!rec_dir_init || clp->cl_firststate)
>  		return 0;
>  
> -	nfs4_save_user(&uid, &gid);
> +	nfs4_begin_secure(&saved_sec);
>  
>  	/* lock the parent */
>  	mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
> @@ -163,7 +172,7 @@ out_unlock:
>  		clp->cl_firststate = 1;
>  		nfsd4_sync_rec_dir();
>  	}
> -	nfs4_reset_user(uid, gid);
> +	nfs4_end_secure(saved_sec);
>  	dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
>  	return status;
>  }
> @@ -206,20 +215,19 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
>  static int
>  nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
>  {
> +	struct task_security *saved_sec;
>  	struct file *filp;
>  	struct dentry_list_arg dla = {
>  		.parent = dir,
>  	};
>  	struct list_head *dentries = &dla.dentries;
>  	struct dentry_list *child;
> -	uid_t uid;
> -	gid_t gid;
>  	int status;
>  
>  	if (!rec_dir_init)
>  		return 0;
>  
> -	nfs4_save_user(&uid, &gid);
> +	nfs4_begin_secure(&saved_sec);
>  
>  	filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
>  	status = PTR_ERR(filp);
> @@ -244,7 +252,7 @@ out:
>  		dput(child->dentry);
>  		kfree(child);
>  	}
> -	nfs4_reset_user(uid, gid);
> +	nfs4_end_secure(saved_sec);
>  	return status;
>  }
>  
> @@ -306,17 +314,16 @@ out:
>  void
>  nfsd4_remove_clid_dir(struct nfs4_client *clp)
>  {
> -	uid_t uid;
> -	gid_t gid;
> +	struct task_security *saved_sec;
>  	int status;
>  
>  	if (!rec_dir_init || !clp->cl_firststate)
>  		return;
>  
>  	clp->cl_firststate = 0;
> -	nfs4_save_user(&uid, &gid);
> +	nfs4_begin_secure(&saved_sec);
>  	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
> -	nfs4_reset_user(uid, gid);
> +	nfs4_end_secure(saved_sec);
>  	if (status == 0)
>  		nfsd4_sync_rec_dir();
>  	if (status)
> @@ -387,8 +394,7 @@ nfsd4_recdir_load(void) {
>  void
>  nfsd4_init_recdir(char *rec_dirname)
>  {
> -	uid_t			uid = 0;
> -	gid_t			gid = 0;
> +	struct task_security	*saved_sec;
>  	int 			status;
>  
>  	printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
> @@ -396,7 +402,15 @@ nfsd4_init_recdir(char *rec_dirname)
>  
>  	BUG_ON(rec_dir_init);
>  
> -	nfs4_save_user(&uid, &gid);
> +	/* derive the security record from this task's objective security */
> +	rec_security = get_kernel_security(current);
> +	if (!rec_security) {
> +		printk("NFSD:"
> +		       " unable to allocate recovery directory security\n");
> +		return;
> +	}
> +
> +	nfs4_begin_secure(&saved_sec);
>  
>  	status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
>  			&rec_dir);
> @@ -406,7 +420,8 @@ nfsd4_init_recdir(char *rec_dirname)
>  
>  	if (!status)
>  		rec_dir_init = 1;
> -	nfs4_reset_user(uid, gid);
> +
> +	nfs4_end_secure(saved_sec);
>  }
>  
>  void
> @@ -416,4 +431,5 @@ nfsd4_shutdown_recdir(void)
>  		return;
>  	rec_dir_init = 0;
>  	path_release(&rec_dir);
> +	put_task_security(rec_security);
>  }
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 697e707..d079b85 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -886,6 +886,7 @@ struct group_info {
>  extern struct group_info *groups_alloc(int gidsetsize);
>  extern void groups_free(struct group_info *group_info);
>  extern int set_current_groups(struct group_info *group_info);
> +extern int set_groups(struct task_security *sec, struct group_info *group_info);
>  extern int groups_search(struct group_info *group_info, gid_t grp);
>  /* access the groups "array" with this macro */
>  #define GROUP_AT(gi, i) \
> diff --git a/kernel/sys.c b/kernel/sys.c
> index e331b6f..790639f 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -1245,10 +1245,16 @@ int groups_search(struct group_info *group_info, gid_t grp)
>  	return 0;
>  }
>  
> -/* validate and set current->group_info */
> -int set_current_groups(struct group_info *group_info)
> +/**
> + * set_groups - Change a group subscription in a security record
> + * @sec: The security record to alter
> + * @group_info: The group list to impose
> + *
> + * Validate a group subscription and, if valid, impose it upon a task security
> + * record.
> + */
> +int set_groups(struct task_security *sec, struct group_info *group_info)
>  {
> -	struct task_security *sec = current->sec;
>  	int retval;
>  	struct group_info *old_info;
>  
> @@ -1265,10 +1271,23 @@ int set_current_groups(struct group_info *group_info)
>  	spin_unlock(&sec->lock);
>  
>  	put_group_info(old_info);
> -
>  	return 0;
>  }
>  
> +EXPORT_SYMBOL(set_groups);
> +
> +/**
> + * set_current_groups - Change current's group subscription
> + * @group_info: The group list to impose
> + *
> + * Validate a group subscription and, if valid, impose it upon current's task
> + * security record.
> + */
> +int set_current_groups(struct group_info *group_info)
> +{
> +	return set_groups(current->sec, group_info);
> +}
> +
>  EXPORT_SYMBOL(set_current_groups);
>  
>  asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)

  reply	other threads:[~2008-01-17 20:48 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-15 23:46 [PATCH 00/26] Permit filesystem local caching David Howells
2008-01-15 23:46 ` [PATCH 01/26] KEYS: Increase the payload size when instantiating a key David Howells
2008-01-15 23:47 ` [PATCH 02/26] KEYS: Check starting keyring as part of search David Howells
2008-01-15 23:47 ` [PATCH 03/26] KEYS: Allow the callout data to be passed as a blob rather than a string David Howells
2008-01-15 23:47 ` [PATCH 04/26] KEYS: Add keyctl function to get a security label David Howells
2008-01-16 15:47   ` Stephen Smalley
2008-01-15 23:47 ` [PATCH 05/26] Security: Change current->fs[ug]id to current_fs[ug]id() David Howells
2008-01-15 23:47 ` [PATCH 06/26] Security: Separate task security context from task_struct David Howells
2008-01-17 17:14   ` [PATCH 06a/26] Extra task_struct -> task_security separation David Howells
2008-01-17 17:17   ` [PATCH 06b/26] Security: Make NFSD work with detached security David Howells
2008-01-17 20:48     ` J. Bruce Fields [this message]
2008-01-17 22:48       ` David Howells
2008-01-17 23:02         ` David Howells
2008-01-15 23:47 ` [PATCH 07/26] Security: De-embed task security record from task and use refcounting David Howells
2008-01-15 23:47 ` [PATCH 08/26] Add a secctx_to_secid() LSM hook to go along with the existing David Howells
2008-01-16  1:05   ` James Morris
2008-01-16 13:41     ` Paul Moore
2008-01-16 17:08       ` Casey Schaufler
2008-01-16 22:13       ` James Morris
2008-01-16 22:19         ` Paul Moore
2008-01-15 23:47 ` [PATCH 09/26] Security: Pre-add additional non-caching classes David Howells
2008-01-15 23:47 ` [PATCH 10/26] Security: Add a kernel_service object class to SELinux David Howells
2008-01-15 23:47 ` [PATCH 11/26] Security: Allow kernel services to override LSM settings for task actions David Howells
2008-01-15 23:47 ` [PATCH 12/26] FS-Cache: Release page->private after failed readahead David Howells
2008-01-15 23:48 ` [PATCH 13/26] FS-Cache: Recruit a couple of page flags for cache management David Howells
2008-01-15 23:48 ` [PATCH 14/26] FS-Cache: Provide an add_wait_queue_tail() function David Howells
2008-01-15 23:48 ` [PATCH 15/26] FS-Cache: Generic filesystem caching facility David Howells
2008-01-15 23:48 ` [PATCH 16/26] CacheFiles: Add missing copy_page export for ia64 David Howells
2008-01-15 23:48 ` [PATCH 17/26] CacheFiles: Be consistent about the use of mapping vs file->f_mapping in Ext3 David Howells
2008-01-15 23:48 ` [PATCH 18/26] CacheFiles: Add a hook to write a single page of data to an inode David Howells
2008-01-15 23:48 ` [PATCH 19/26] CacheFiles: Permit the page lock state to be monitored David Howells
2008-01-15 23:48 ` [PATCH 20/26] CacheFiles: Export things for CacheFiles David Howells
2008-01-15 23:48 ` [PATCH 21/26] CacheFiles: A cache that backs onto a mounted filesystem David Howells
2008-01-15 23:48 ` [PATCH 22/26] NFS: Fix memory leak David Howells
2008-01-15 23:48 ` [PATCH 23/26] NFS: Use local caching David Howells
2008-01-15 23:49 ` [PATCH 24/26] NFS: Configuration and mount option changes to enable local caching on NFS David Howells
2008-01-15 23:49 ` [PATCH 25/26] NFS: Display local caching state David Howells
2008-01-15 23:49 ` [PATCH 26/26] NFS: Separate caching by superblock, explicitly if necessary David Howells
2008-01-16  0:58 ` [PATCH 00/26] Permit filesystem local caching James Morris
2008-01-16 16:48   ` David Howells
2008-01-16  1:52 ` James Morris
2008-01-16  2:24 ` Kyle Moffett
2008-01-16 16:55   ` David Howells

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=20080117204804.GC6416@fieldses.org \
    --to=bfields@fieldses.org \
    --cc=Trond.Myklebust@netapp.com \
    --cc=casey@schaufler-ca.com \
    --cc=dhowells@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=neilb@suse.de \
    --cc=nfs@lists.sourceforge.net \
    --cc=sds@tycho.nsa.gov \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox