linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] Permit filesystem local caching
@ 2007-12-05 19:37 David Howells
  2007-12-05 19:37 ` [PATCH 1/7] KEYS: Increase the payload size when instantiating a key David Howells
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: David Howells @ 2007-12-05 19:37 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells



These patches add local caching for network filesystems such as NFS and AFS.

The patches can roughly be broken down into a number of sets:

  (*) 01-keys-inc-payload.diff
  (*) 02-keys-search-keyring.diff
  (*) 03-keys-callout-blob.diff

      Three patches to the keyring code made to help the CIFS people.
      Included because of patches 05-08.

  (*) 04-keys-get-label.diff

      A patch to allow the security label of a key to be retrieved.
      Included because of patches 05-08.

  (*) 05-security-current-fsugid.diff
  (*) 06-security-separate-task-bits.diff
  (*) 07-security-subjective.diff
  (*) 08-security-kernel-service.diff

      Patches to permit the subjective security of a task to be overridden.
      All the security details in task_struct are decanted into a new struct
      that task_struct then has two pointers two: one that defines the
      objective security of that task (how other tasks may affect it) and one
      that defines the subjective security (how it may affect other objects).

      Note that I have dropped the idea of struct cred for the moment.  With
      the amount of stuff that was excluded from it, it wasn't actually any
      use to me.  However, it can be added later.

      Required for cachefiles.

  (*) 09-release-page.diff
  (*) 10-fscache-page-flags.diff
  (*) 11-add_wait_queue_tail.diff
  (*) 12-fscache.diff

      Patches to provide a local caching facility for network filesystems.

  (*) 13-cachefiles-ia64.diff
  (*) 14-cachefiles-ext3-f_mapping.diff
  (*) 15-cachefiles-write.diff
  (*) 16-cachefiles-monitor.diff
  (*) 17-cachefiles-export.diff
  (*) 18-cachefiles.diff

      Patches to provide a local cache in a directory of an already mounted
      filesystem.

  (*) 19-fscache-nfs.diff
  (*) 20-fscache-nfs-mount.diff
  (*) 21-fscache-nfs-display.diff

      Patches to provide NFS with local caching.

  (*) 22-fcrypt-bit-annotate.diff

      A fix for AFS.

  (*) 23-afs-testsetpageerror.diff
  (*) 24-afs-cancel_rejected_write.diff
  (*) 25-afs-rejected-writeback.diff
  (*) 26-afs-opID.diff
  (*) 27-afs-shared-writable-mmap.diff

      Patches to provide AFS with improved write support.

  (*) 28-fscache-afs.diff

      Patches to provide AFS with local caching.

There are some issues with these patches that I'd like advice on:

 (1) Is the security override stuff acceptable?

 (2) Should the audit context be placed in the task_security struct?

 (3) Should the task security context actually be shared by CLONE_THREAD?
     (should it be placed in struct thread_group_security).

 (4) How to handle superblock sharing in NFS?  (I've sent a separate email on
     this)

Andrew, Linus, can you please hold off on taking these patches for the moment.


--
A tarball of the patches is available at:

	http://people.redhat.com/~dhowells/fscache/patches/nfs+fscache-25.tar.bz2


To use this version of CacheFiles, the cachefilesd-0.9 is also required.  It
is available as an SRPM:

	http://people.redhat.com/~dhowells/fscache/cachefilesd-0.9-1.fc7.src.rpm

Or as individual bits:

	http://people.redhat.com/~dhowells/fscache/cachefilesd-0.9.tar.bz2
	http://people.redhat.com/~dhowells/fscache/cachefilesd.fc
	http://people.redhat.com/~dhowells/fscache/cachefilesd.if
	http://people.redhat.com/~dhowells/fscache/cachefilesd.te
	http://people.redhat.com/~dhowells/fscache/cachefilesd.spec

The .fc, .if and .te files are for manipulating SELinux.

David

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

* [PATCH 1/7] KEYS: Increase the payload size when instantiating a key
  2007-12-05 19:37 [PATCH 0/7] Permit filesystem local caching David Howells
@ 2007-12-05 19:37 ` David Howells
  2007-12-05 19:37 ` [PATCH 2/7] KEYS: Check starting keyring as part of search David Howells
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: David Howells @ 2007-12-05 19:37 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells

Increase the size of a payload that can be used to instantiate a key in
add_key() and keyctl_instantiate_key().  This permits huge CIFS SPNEGO blobs to
be passed around.  The limit is raised to 1MB.  If kmalloc() can't allocate a
buffer of sufficient size, vmalloc() will be tried instead.

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

 security/keys/keyctl.c |   38 ++++++++++++++++++++++++++++++--------
 1 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index d9ca15c..8ec8432 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -19,6 +19,7 @@
 #include <linux/capability.h>
 #include <linux/string.h>
 #include <linux/err.h>
+#include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -62,9 +63,10 @@ asmlinkage long sys_add_key(const char __user *_type,
 	char type[32], *description;
 	void *payload;
 	long ret;
+	bool vm;
 
 	ret = -EINVAL;
-	if (plen > 32767)
+	if (plen > 1024 * 1024 - 1)
 		goto error;
 
 	/* draw all the data into kernel space */
@@ -81,11 +83,18 @@ asmlinkage long sys_add_key(const char __user *_type,
 	/* pull the payload in if one was supplied */
 	payload = NULL;
 
+	vm = false;
 	if (_payload) {
 		ret = -ENOMEM;
 		payload = kmalloc(plen, GFP_KERNEL);
-		if (!payload)
-			goto error2;
+		if (!payload) {
+			if (plen <= PAGE_SIZE)
+				goto error2;
+			vm = true;
+			payload = vmalloc(plen);
+			if (!payload)
+				goto error2;
+		}
 
 		ret = -EFAULT;
 		if (copy_from_user(payload, _payload, plen) != 0)
@@ -113,7 +122,10 @@ asmlinkage long sys_add_key(const char __user *_type,
 
 	key_ref_put(keyring_ref);
  error3:
-	kfree(payload);
+	if (!vm)
+		kfree(payload);
+	else
+		vfree(payload);
  error2:
 	kfree(description);
  error:
@@ -821,9 +833,10 @@ long keyctl_instantiate_key(key_serial_t id,
 	key_ref_t keyring_ref;
 	void *payload;
 	long ret;
+	bool vm = false;
 
 	ret = -EINVAL;
-	if (plen > 32767)
+	if (plen > 1024 * 1024 - 1)
 		goto error;
 
 	/* the appropriate instantiation authorisation key must have been
@@ -843,8 +856,14 @@ long keyctl_instantiate_key(key_serial_t id,
 	if (_payload) {
 		ret = -ENOMEM;
 		payload = kmalloc(plen, GFP_KERNEL);
-		if (!payload)
-			goto error;
+		if (!payload) {
+			if (plen <= PAGE_SIZE)
+				goto error;
+			vm = true;
+			payload = vmalloc(plen);
+			if (!payload)
+				goto error;
+		}
 
 		ret = -EFAULT;
 		if (copy_from_user(payload, _payload, plen) != 0)
@@ -877,7 +896,10 @@ long keyctl_instantiate_key(key_serial_t id,
 	}
 
 error2:
-	kfree(payload);
+	if (!vm)
+		kfree(payload);
+	else
+		vfree(payload);
 error:
 	return ret;
 


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

* [PATCH 2/7] KEYS: Check starting keyring as part of search
  2007-12-05 19:37 [PATCH 0/7] Permit filesystem local caching David Howells
  2007-12-05 19:37 ` [PATCH 1/7] KEYS: Increase the payload size when instantiating a key David Howells
@ 2007-12-05 19:37 ` David Howells
  2007-12-05 19:37 ` [PATCH 3/7] KEYS: Allow the callout data to be passed as a blob rather than a string David Howells
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: David Howells @ 2007-12-05 19:37 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells

Check the starting keyring as part of the search to (a) see if that is what
we're searching for, and (b) to check it is still valid for searching.

The scenario:  User in process A does things that cause things to be
created in its process session keyring.  The user then does an su to
another user and starts a new process, B.  The two processes now
share the same process session keyring.

Process B does an NFS access which results in an upcall to gssd.
When gssd attempts to instantiate the context key (to be linked
into the process session keyring), it is denied access even though it
has an authorization key.

The order of calls is:

   keyctl_instantiate_key()
      lookup_user_key()				    (the default: case)
         search_process_keyrings(current)
	    search_process_keyrings(rka->context)   (recursive call)
	       keyring_search_aux()

keyring_search_aux() verifies the keys and keyrings underneath the
top-level keyring it is given, but that top-level keyring is neither
fully validated nor checked to see if it is the thing being searched for.

This patch changes keyring_search_aux() to:
1) do more validation on the top keyring it is given and
2) check whether that top-level keyring is the thing being searched for


Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 security/keys/keyring.c |   35 +++++++++++++++++++++++++++++++----
 1 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 88292e3..76b89b2 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -292,7 +292,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
 
 	struct keyring_list *keylist;
 	struct timespec now;
-	unsigned long possessed;
+	unsigned long possessed, kflags;
 	struct key *keyring, *key;
 	key_ref_t key_ref;
 	long err;
@@ -318,6 +318,32 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
 	now = current_kernel_time();
 	err = -EAGAIN;
 	sp = 0;
+	
+	/* firstly we should check to see if this top-level keyring is what we
+	 * are looking for */
+	key_ref = ERR_PTR(-EAGAIN);
+	kflags = keyring->flags;
+	if (keyring->type == type && match(keyring, description)) {
+		key = keyring;
+
+		/* check it isn't negative and hasn't expired or been
+		 * revoked */
+		if (kflags & (1 << KEY_FLAG_REVOKED))
+			goto error_2;
+		if (key->expiry && now.tv_sec >= key->expiry)
+			goto error_2;
+		key_ref = ERR_PTR(-ENOKEY);
+		if (kflags & (1 << KEY_FLAG_NEGATIVE))
+			goto error_2;
+		goto found;
+	}
+
+	/* otherwise, the top keyring must not be revoked, expired, or
+	 * negatively instantiated if we are to search it */
+	key_ref = ERR_PTR(-EAGAIN);
+	if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) ||
+	    (keyring->expiry && now.tv_sec >= keyring->expiry))
+		goto error_2;
 
 	/* start processing a new keyring */
 descend:
@@ -331,13 +357,14 @@ descend:
 	/* iterate through the keys in this keyring first */
 	for (kix = 0; kix < keylist->nkeys; kix++) {
 		key = keylist->keys[kix];
+		kflags = key->flags;
 
 		/* ignore keys not of this type */
 		if (key->type != type)
 			continue;
 
 		/* skip revoked keys and expired keys */
-		if (test_bit(KEY_FLAG_REVOKED, &key->flags))
+		if (kflags & (1 << KEY_FLAG_REVOKED))
 			continue;
 
 		if (key->expiry && now.tv_sec >= key->expiry)
@@ -352,8 +379,8 @@ descend:
 					context, KEY_SEARCH) < 0)
 			continue;
 
-		/* we set a different error code if we find a negative key */
-		if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
+		/* we set a different error code if we pass a negative key */
+		if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
 			err = -ENOKEY;
 			continue;
 		}


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

* [PATCH 3/7] KEYS: Allow the callout data to be passed as a blob rather than a string
  2007-12-05 19:37 [PATCH 0/7] Permit filesystem local caching David Howells
  2007-12-05 19:37 ` [PATCH 1/7] KEYS: Increase the payload size when instantiating a key David Howells
  2007-12-05 19:37 ` [PATCH 2/7] KEYS: Check starting keyring as part of search David Howells
@ 2007-12-05 19:37 ` David Howells
  2007-12-05 19:37 ` [PATCH 4/7] KEYS: Add keyctl function to get a security label David Howells
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: David Howells @ 2007-12-05 19:37 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells

Allow the callout data to be passed as a blob rather than a string for internal
kernel services that call any request_key_*() interface other than
request_key().  request_key() itself still takes a NUL-terminated string.

The functions that change are:

	request_key_with_auxdata()
	request_key_async()
	request_key_async_with_auxdata()

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

 Documentation/keys-request-key.txt |   11 +++++---
 Documentation/keys.txt             |   14 +++++++---
 include/linux/key.h                |    9 ++++---
 security/keys/internal.h           |    9 ++++---
 security/keys/keyctl.c             |    7 ++++-
 security/keys/request_key.c        |   49 ++++++++++++++++++++++--------------
 security/keys/request_key_auth.c   |   12 +++++----
 7 files changed, 70 insertions(+), 41 deletions(-)

diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt
index 266955d..09b55e4 100644
--- a/Documentation/keys-request-key.txt
+++ b/Documentation/keys-request-key.txt
@@ -11,26 +11,29 @@ request_key*():
 
 	struct key *request_key(const struct key_type *type,
 				const char *description,
-				const char *callout_string);
+				const char *callout_info);
 
 or:
 
 	struct key *request_key_with_auxdata(const struct key_type *type,
 					     const char *description,
-					     const char *callout_string,
+					     const char *callout_info,
+					     size_t callout_len,
 					     void *aux);
 
 or:
 
 	struct key *request_key_async(const struct key_type *type,
 				      const char *description,
-				      const char *callout_string);
+				      const char *callout_info,
+				      size_t callout_len);
 
 or:
 
 	struct key *request_key_async_with_auxdata(const struct key_type *type,
 						   const char *description,
-						   const char *callout_string,
+						   const char *callout_info,
+					     	   size_t callout_len,
 						   void *aux);
 
 Or by userspace invoking the request_key system call:
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 51652d3..b82d38d 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -771,7 +771,7 @@ payload contents" for more information.
 
 	struct key *request_key(const struct key_type *type,
 				const char *description,
-				const char *callout_string);
+				const char *callout_info);
 
     This is used to request a key or keyring with a description that matches
     the description specified according to the key type's match function. This
@@ -793,24 +793,28 @@ payload contents" for more information.
 
 	struct key *request_key_with_auxdata(const struct key_type *type,
 					     const char *description,
-					     const char *callout_string,
+					     const void *callout_info,
+					     size_t callout_len,
 					     void *aux);
 
     This is identical to request_key(), except that the auxiliary data is
-    passed to the key_type->request_key() op if it exists.
+    passed to the key_type->request_key() op if it exists, and the callout_info
+    is a blob of length callout_len, if given (the length may be 0).
 
 
 (*) A key can be requested asynchronously by calling one of:
 
 	struct key *request_key_async(const struct key_type *type,
 				      const char *description,
-				      const char *callout_string);
+				      const void *callout_info,
+				      size_t callout_len);
 
     or:
 
 	struct key *request_key_async_with_auxdata(const struct key_type *type,
 						   const char *description,
-						   const char *callout_string,
+						   const char *callout_info,
+					     	   size_t callout_len,
 					     	   void *aux);
 
     which are asynchronous equivalents of request_key() and
diff --git a/include/linux/key.h b/include/linux/key.h
index fcdbd5e..4a6021a 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -208,16 +208,19 @@ extern struct key *request_key(struct key_type *type,
 
 extern struct key *request_key_with_auxdata(struct key_type *type,
 					    const char *description,
-					    const char *callout_info,
+					    const void *callout_info,
+					    size_t callout_len,
 					    void *aux);
 
 extern struct key *request_key_async(struct key_type *type,
 				     const char *description,
-				     const char *callout_info);
+				     const void *callout_info,
+				     size_t callout_len);
 
 extern struct key *request_key_async_with_auxdata(struct key_type *type,
 						  const char *description,
-						  const char *callout_info,
+						  const void *callout_info,
+						  size_t callout_len,
 						  void *aux);
 
 extern int wait_for_key_construction(struct key *key, bool intr);
diff --git a/security/keys/internal.h b/security/keys/internal.h
index d36d693..f004835 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -109,7 +109,8 @@ extern int install_process_keyring(struct task_struct *tsk);
 
 extern struct key *request_key_and_link(struct key_type *type,
 					const char *description,
-					const char *callout_info,
+					const void *callout_info,
+					size_t callout_len,
 					void *aux,
 					struct key *dest_keyring,
 					unsigned long flags);
@@ -120,13 +121,15 @@ extern struct key *request_key_and_link(struct key_type *type,
 struct request_key_auth {
 	struct key		*target_key;
 	struct task_struct	*context;
-	char			*callout_info;
+	void			*callout_info;
+	size_t			callout_len;
 	pid_t			pid;
 };
 
 extern struct key_type key_type_request_key_auth;
 extern struct key *request_key_auth_new(struct key *target,
-					const char *callout_info);
+					const void *callout_info,
+					size_t callout_len);
 
 extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
 
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 8ec8432..1698bf9 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -152,6 +152,7 @@ asmlinkage long sys_request_key(const char __user *_type,
 	struct key_type *ktype;
 	struct key *key;
 	key_ref_t dest_ref;
+	size_t callout_len;
 	char type[32], *description, *callout_info;
 	long ret;
 
@@ -169,12 +170,14 @@ asmlinkage long sys_request_key(const char __user *_type,
 
 	/* pull the callout info into kernel space */
 	callout_info = NULL;
+	callout_len = 0;
 	if (_callout_info) {
 		callout_info = strndup_user(_callout_info, PAGE_SIZE);
 		if (IS_ERR(callout_info)) {
 			ret = PTR_ERR(callout_info);
 			goto error2;
 		}
+		callout_len = strlen(callout_info);
 	}
 
 	/* get the destination keyring if specified */
@@ -195,8 +198,8 @@ asmlinkage long sys_request_key(const char __user *_type,
 	}
 
 	/* do the search */
-	key = request_key_and_link(ktype, description, callout_info, NULL,
-				   key_ref_to_ptr(dest_ref),
+	key = request_key_and_link(ktype, description, callout_info,
+				   callout_len, NULL, key_ref_to_ptr(dest_ref),
 				   KEY_ALLOC_IN_QUOTA);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 6381e61..aee4897 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -161,21 +161,22 @@ error_alloc:
  * call out to userspace for key construction
  * - we ignore program failure and go on key status instead
  */
-static int construct_key(struct key *key, const char *callout_info, void *aux)
+static int construct_key(struct key *key, const void *callout_info,
+			 size_t callout_len, void *aux)
 {
 	struct key_construction *cons;
 	request_key_actor_t actor;
 	struct key *authkey;
 	int ret;
 
-	kenter("%d,%s,%p", key->serial, callout_info, aux);
+	kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux);
 
 	cons = kmalloc(sizeof(*cons), GFP_KERNEL);
 	if (!cons)
 		return -ENOMEM;
 
 	/* allocate an authorisation key */
-	authkey = request_key_auth_new(key, callout_info);
+	authkey = request_key_auth_new(key, callout_info, callout_len);
 	if (IS_ERR(authkey)) {
 		kfree(cons);
 		ret = PTR_ERR(authkey);
@@ -331,6 +332,7 @@ alloc_failed:
 static struct key *construct_key_and_link(struct key_type *type,
 					  const char *description,
 					  const char *callout_info,
+					  size_t callout_len,
 					  void *aux,
 					  struct key *dest_keyring,
 					  unsigned long flags)
@@ -348,7 +350,7 @@ static struct key *construct_key_and_link(struct key_type *type,
 	key_user_put(user);
 
 	if (ret == 0) {
-		ret = construct_key(key, callout_info, aux);
+		ret = construct_key(key, callout_info, callout_len, aux);
 		if (ret < 0)
 			goto construction_failed;
 	}
@@ -370,7 +372,8 @@ construction_failed:
  */
 struct key *request_key_and_link(struct key_type *type,
 				 const char *description,
-				 const char *callout_info,
+				 const void *callout_info,
+				 size_t callout_len,
 				 void *aux,
 				 struct key *dest_keyring,
 				 unsigned long flags)
@@ -378,8 +381,8 @@ struct key *request_key_and_link(struct key_type *type,
 	struct key *key;
 	key_ref_t key_ref;
 
-	kenter("%s,%s,%s,%p,%p,%lx",
-	       type->name, description, callout_info, aux,
+	kenter("%s,%s,%p,%zu,%p,%p,%lx",
+	       type->name, description, callout_info, callout_len, aux,
 	       dest_keyring, flags);
 
 	/* search all the process keyrings for a key */
@@ -398,7 +401,8 @@ struct key *request_key_and_link(struct key_type *type,
 			goto error;
 
 		key = construct_key_and_link(type, description, callout_info,
-					     aux, dest_keyring, flags);
+					     callout_len, aux, dest_keyring,
+					     flags);
 	}
 
 error:
@@ -434,10 +438,13 @@ struct key *request_key(struct key_type *type,
 			const char *callout_info)
 {
 	struct key *key;
+	size_t callout_len = 0;
 	int ret;
 
-	key = request_key_and_link(type, description, callout_info, NULL,
-				   NULL, KEY_ALLOC_IN_QUOTA);
+	if (callout_info)
+		callout_len = strlen(callout_info);
+	key = request_key_and_link(type, description, callout_info, callout_len,
+				   NULL, NULL, KEY_ALLOC_IN_QUOTA);
 	if (!IS_ERR(key)) {
 		ret = wait_for_key_construction(key, false);
 		if (ret < 0) {
@@ -458,14 +465,15 @@ EXPORT_SYMBOL(request_key);
  */
 struct key *request_key_with_auxdata(struct key_type *type,
 				     const char *description,
-				     const char *callout_info,
+				     const void *callout_info,
+				     size_t callout_len,
 				     void *aux)
 {
 	struct key *key;
 	int ret;
 
-	key = request_key_and_link(type, description, callout_info, aux,
-				   NULL, KEY_ALLOC_IN_QUOTA);
+	key = request_key_and_link(type, description, callout_info, callout_len,
+				   aux, NULL, KEY_ALLOC_IN_QUOTA);
 	if (!IS_ERR(key)) {
 		ret = wait_for_key_construction(key, false);
 		if (ret < 0) {
@@ -485,10 +493,12 @@ EXPORT_SYMBOL(request_key_with_auxdata);
  */
 struct key *request_key_async(struct key_type *type,
 			      const char *description,
-			      const char *callout_info)
+			      const void *callout_info,
+			      size_t callout_len)
 {
-	return request_key_and_link(type, description, callout_info, NULL,
-				    NULL, KEY_ALLOC_IN_QUOTA);
+	return request_key_and_link(type, description, callout_info,
+				    callout_len, NULL, NULL,
+				    KEY_ALLOC_IN_QUOTA);
 }
 EXPORT_SYMBOL(request_key_async);
 
@@ -500,10 +510,11 @@ EXPORT_SYMBOL(request_key_async);
  */
 struct key *request_key_async_with_auxdata(struct key_type *type,
 					   const char *description,
-					   const char *callout_info,
+					   const void *callout_info,
+					   size_t callout_len,
 					   void *aux)
 {
-	return request_key_and_link(type, description, callout_info, aux,
-				    NULL, KEY_ALLOC_IN_QUOTA);
+	return request_key_and_link(type, description, callout_info,
+				    callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA);
 }
 EXPORT_SYMBOL(request_key_async_with_auxdata);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 510f7be..6827ae3 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -61,7 +61,7 @@ static void request_key_auth_describe(const struct key *key,
 
 	seq_puts(m, "key:");
 	seq_puts(m, key->description);
-	seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info));
+	seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
 
 } /* end request_key_auth_describe() */
 
@@ -77,7 +77,7 @@ static long request_key_auth_read(const struct key *key,
 	size_t datalen;
 	long ret;
 
-	datalen = strlen(rka->callout_info);
+	datalen = rka->callout_len;
 	ret = datalen;
 
 	/* we can return the data as is */
@@ -137,7 +137,8 @@ static void request_key_auth_destroy(struct key *key)
  * create an authorisation token for /sbin/request-key or whoever to gain
  * access to the caller's security data
  */
-struct key *request_key_auth_new(struct key *target, const char *callout_info)
+struct key *request_key_auth_new(struct key *target, const void *callout_info,
+				 size_t callout_len)
 {
 	struct request_key_auth *rka, *irka;
 	struct key *authkey = NULL;
@@ -152,7 +153,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
 		kleave(" = -ENOMEM");
 		return ERR_PTR(-ENOMEM);
 	}
-	rka->callout_info = kmalloc(strlen(callout_info) + 1, GFP_KERNEL);
+	rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
 	if (!rka->callout_info) {
 		kleave(" = -ENOMEM");
 		kfree(rka);
@@ -186,7 +187,8 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
 	}
 
 	rka->target_key = key_get(target);
-	strcpy(rka->callout_info, callout_info);
+	memcpy(rka->callout_info, callout_info, callout_len);
+	rka->callout_len = callout_len;
 
 	/* allocate the auth key */
 	sprintf(desc, "%x", target->serial);


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

* [PATCH 4/7] KEYS: Add keyctl function to get a security label
  2007-12-05 19:37 [PATCH 0/7] Permit filesystem local caching David Howells
                   ` (2 preceding siblings ...)
  2007-12-05 19:37 ` [PATCH 3/7] KEYS: Allow the callout data to be passed as a blob rather than a string David Howells
@ 2007-12-05 19:37 ` David Howells
  2007-12-05 20:12   ` Casey Schaufler
  2007-12-05 19:37 ` [PATCH 5/7] Security: Change current->fs[ug]id to current_fs[ug]id() David Howells
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: David Howells @ 2007-12-05 19:37 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells

Add a keyctl() function to get the security label of a key.

The following is added to Documentation/keys.txt:

 (*) Get the LSM security context attached to a key.

	long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
		    size_t buflen)

     This function returns a string that represents the LSM security context
     attached to a key in the buffer provided.

     Unless there's an error, it always returns the amount of data it could
     produce, even if that's too big for the buffer, but it won't copy more
     than requested to userspace. If the buffer pointer is NULL then no copy
     will take place.

     A NUL character is included at the end of the string if the buffer is
     sufficiently big.  This is included in the returned count.  If no LSM is
     in force then an empty string will be returned.

     A process must have view permission on the key for this function to be
     successful.

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

 Documentation/keys.txt   |   21 +++++++++++++++
 include/linux/keyctl.h   |    1 +
 include/linux/security.h |   20 +++++++++++++-
 security/dummy.c         |    8 ++++++
 security/keys/compat.c   |    3 ++
 security/keys/keyctl.c   |   66 ++++++++++++++++++++++++++++++++++++++++++++++
 security/security.c      |    5 +++
 security/selinux/hooks.c |   21 +++++++++++++--
 8 files changed, 141 insertions(+), 4 deletions(-)

diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index b82d38d..be424b0 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -711,6 +711,27 @@ The keyctl syscall functions are:
      The assumed authoritative key is inherited across fork and exec.
 
 
+ (*) Get the LSM security context attached to a key.
+
+	long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
+		    size_t buflen)
+
+     This function returns a string that represents the LSM security context
+     attached to a key in the buffer provided.
+
+     Unless there's an error, it always returns the amount of data it could
+     produce, even if that's too big for the buffer, but it won't copy more
+     than requested to userspace. If the buffer pointer is NULL then no copy
+     will take place.
+
+     A NUL character is included at the end of the string if the buffer is
+     sufficiently big.  This is included in the returned count.  If no LSM is
+     in force then an empty string will be returned.
+
+     A process must have view permission on the key for this function to be
+     successful.
+
+
 ===============
 KERNEL SERVICES
 ===============
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 3365945..656ee6b 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -49,5 +49,6 @@
 #define KEYCTL_SET_REQKEY_KEYRING	14	/* set default request-key keyring */
 #define KEYCTL_SET_TIMEOUT		15	/* set key timeout */
 #define KEYCTL_ASSUME_AUTHORITY		16	/* assume request_key() authorisation */
+#define KEYCTL_GET_SECURITY		17	/* get key security label */
 
 #endif /*  _LINUX_KEYCTL_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index ac05083..8d9e946 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -959,6 +959,17 @@ struct request_sock;
  *	@perm describes the combination of permissions required of this key.
  *	Return 1 if permission granted, 0 if permission denied and -ve it the
  *      normal permissions model should be effected.
+ * @key_getsecurity:
+ *	Get a textual representation of the security context attached to a key
+ *	for the purposes of honouring KEYCTL_GETSECURITY.  This function
+ *	allocates the storage for the NUL-terminated string and the caller
+ *	should free it.
+ *	@key points to the key to be queried.
+ *	@_buffer points to a pointer that should be set to point to the
+ *	 resulting string (if no label or an error occurs).
+ *	Return the length of the string (including terminating NUL) or -ve if
+ *      an error.
+ *	May also return 0 (and a NULL buffer pointer) if there is no label.
  *
  * Security hooks affecting all System V IPC operations.
  *
@@ -1437,7 +1448,7 @@ struct security_operations {
 	int (*key_permission)(key_ref_t key_ref,
 			      struct task_struct *context,
 			      key_perm_t perm);
-
+	int (*key_getsecurity)(struct key *key, char **_buffer);
 #endif	/* CONFIG_KEYS */
 
 };
@@ -2567,6 +2578,7 @@ int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long f
 void security_key_free(struct key *key);
 int security_key_permission(key_ref_t key_ref,
 			    struct task_struct *context, key_perm_t perm);
+int security_key_getsecurity(struct key *key, char **_buffer);
 
 #else
 
@@ -2588,6 +2600,12 @@ static inline int security_key_permission(key_ref_t key_ref,
 	return 0;
 }
 
+static inline int security_key_getsecurity(struct key *key, char **_buffer)
+{
+	*_buffer = NULL;
+	return 0;
+}
+
 #endif
 #endif /* CONFIG_KEYS */
 
diff --git a/security/dummy.c b/security/dummy.c
index 6d895ad..7993b30 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -949,6 +949,13 @@ static inline int dummy_key_permission(key_ref_t key_ref,
 {
 	return 0;
 }
+
+static int dummy_key_getsecurity(struct key *key, char **_buffer)
+{
+	*_buffer = NULL;
+	return 0;
+}
+
 #endif /* CONFIG_KEYS */
 
 struct security_operations dummy_security_ops;
@@ -1133,6 +1140,7 @@ void security_fixup_ops (struct security_operations *ops)
 	set_to_dummy_if_null(ops, key_alloc);
 	set_to_dummy_if_null(ops, key_free);
 	set_to_dummy_if_null(ops, key_permission);
+	set_to_dummy_if_null(ops, key_getsecurity);
 #endif	/* CONFIG_KEYS */
 
 }
diff --git a/security/keys/compat.c b/security/keys/compat.c
index e10ec99..c766c68 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
 	case KEYCTL_ASSUME_AUTHORITY:
 		return keyctl_assume_authority(arg2);
 
+	case KEYCTL_GET_SECURITY:
+		return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 1698bf9..56e963b 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -20,6 +20,7 @@
 #include <linux/string.h>
 #include <linux/err.h>
 #include <linux/vmalloc.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -1080,6 +1081,66 @@ error:
 
 } /* end keyctl_assume_authority() */
 
+/*
+ * get the security label of a key
+ * - the key must grant us view permission
+ * - if there's a buffer, we place up to buflen bytes of data into it
+ * - unless there's an error, we return the amount of information available,
+ *   irrespective of how much we may have copied (including the terminal NUL)
+ * - implements keyctl(KEYCTL_GET_SECURITY)
+ */
+long keyctl_get_security(key_serial_t keyid,
+			 char __user *buffer,
+			 size_t buflen)
+{
+	struct key *key, *instkey;
+	key_ref_t key_ref;
+	char *context;
+	long ret;
+
+	key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
+	if (IS_ERR(key_ref)) {
+		if (PTR_ERR(key_ref) != -EACCES)
+			return PTR_ERR(key_ref);
+
+		/* viewing a key under construction is also permitted if we
+		 * have the authorisation token handy */
+		instkey = key_get_instantiation_authkey(keyid);
+		if (IS_ERR(instkey))
+			return PTR_ERR(key_ref);
+		key_put(instkey);
+
+		key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
+		if (IS_ERR(key_ref))
+			return PTR_ERR(key_ref);
+	}
+
+	key = key_ref_to_ptr(key_ref);
+	ret = security_key_getsecurity(key, &context);
+	if (ret == 0) {
+		/* if no information was returned, give userspace an empty
+		 * string */
+		ret = 1;
+		if (buffer && buflen > 0 &&
+		    copy_to_user(buffer, "", 1) != 0)
+			ret = -EFAULT;
+	} else if (ret > 0) {
+		/* return as much data as there's room for */
+		if (buffer && buflen > 0) {
+			if (buflen > ret)
+				buflen = ret;
+
+			if (copy_to_user(buffer, context, buflen) != 0)
+				ret = -EFAULT;
+		}
+
+		kfree(context);
+	}
+
+	key_ref_put(key_ref);
+	return ret;
+}
+
 /*****************************************************************************/
 /*
  * the key control system call
@@ -1160,6 +1221,11 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
 	case KEYCTL_ASSUME_AUTHORITY:
 		return keyctl_assume_authority((key_serial_t) arg2);
 
+	case KEYCTL_GET_SECURITY:
+		return keyctl_get_security((key_serial_t) arg2,
+					   (char *) arg3,
+					   (size_t) arg4);
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/security/security.c b/security/security.c
index 0e1f1f1..16213e3 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1079,4 +1079,9 @@ int security_key_permission(key_ref_t key_ref,
 	return security_ops->key_permission(key_ref, context, perm);
 }
 
+int security_key_getsecurity(struct key *key, char **_buffer)
+{
+	return security_ops->key_getsecurity(key, _buffer);
+}
+
 #endif	/* CONFIG_KEYS */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9f3124b..bd4cfab 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4768,6 +4768,20 @@ static int selinux_key_permission(key_ref_t key_ref,
 			    SECCLASS_KEY, perm, NULL);
 }
 
+static int selinux_key_getsecurity(struct key *key, char **_buffer)
+{
+	struct key_security_struct *ksec = key->security;
+	char *context = NULL;
+	unsigned len;
+	int rc;
+
+	rc = security_sid_to_context(ksec->sid, &context, &len);
+	if (!rc)
+		rc = len;
+	*_buffer = context;
+	return rc;
+}
+
 #endif
 
 static struct security_operations selinux_ops = {
@@ -4943,9 +4957,10 @@ static struct security_operations selinux_ops = {
 #endif
 
 #ifdef CONFIG_KEYS
-	.key_alloc =                    selinux_key_alloc,
-	.key_free =                     selinux_key_free,
-	.key_permission =               selinux_key_permission,
+	.key_alloc =			selinux_key_alloc,
+	.key_free =			selinux_key_free,
+	.key_permission =		selinux_key_permission,
+	.key_getsecurity =		selinux_key_getsecurity,
 #endif
 };
 


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

* [PATCH 5/7] Security: Change current->fs[ug]id to current_fs[ug]id()
  2007-12-05 19:37 [PATCH 0/7] Permit filesystem local caching David Howells
                   ` (3 preceding siblings ...)
  2007-12-05 19:37 ` [PATCH 4/7] KEYS: Add keyctl function to get a security label David Howells
@ 2007-12-05 19:37 ` David Howells
  2007-12-07 17:44   ` Serge E. Hallyn
  2007-12-08  0:53   ` David Howells
  2007-12-05 19:37 ` [PATCH 6/7] SECURITY: Separate task security context from task_struct David Howells
  2007-12-05 19:37 ` [PATCH 7/7] SECURITY: De-embed task security record from task and use refcounting David Howells
  6 siblings, 2 replies; 14+ messages in thread
From: David Howells @ 2007-12-05 19:37 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells

Change current->fs[ug]id to current_fs[ug]id() so that fsgid and fsuid can be
separated from the task_struct.

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

 arch/ia64/kernel/perfmon.c                |    4 ++--
 arch/powerpc/platforms/cell/spufs/inode.c |    4 ++--
 drivers/isdn/capi/capifs.c                |    4 ++--
 drivers/usb/core/inode.c                  |    4 ++--
 fs/9p/fid.c                               |    2 +-
 fs/9p/vfs_inode.c                         |    4 ++--
 fs/9p/vfs_super.c                         |    4 ++--
 fs/affs/inode.c                           |    4 ++--
 fs/anon_inodes.c                          |    4 ++--
 fs/attr.c                                 |    4 ++--
 fs/bfs/dir.c                              |    4 ++--
 fs/cifs/cifsproto.h                       |    2 +-
 fs/cifs/dir.c                             |   12 ++++++------
 fs/cifs/inode.c                           |    8 ++++----
 fs/cifs/misc.c                            |    4 ++--
 fs/coda/cache.c                           |    6 +++---
 fs/coda/upcall.c                          |    4 ++--
 fs/devpts/inode.c                         |    4 ++--
 fs/dquot.c                                |    2 +-
 fs/exec.c                                 |    4 ++--
 fs/ext2/balloc.c                          |    2 +-
 fs/ext2/ialloc.c                          |    4 ++--
 fs/ext2/ioctl.c                           |    2 +-
 fs/ext3/balloc.c                          |    2 +-
 fs/ext3/ialloc.c                          |    4 ++--
 fs/ext4/balloc.c                          |    2 +-
 fs/ext4/ialloc.c                          |    4 ++--
 fs/fuse/dev.c                             |    4 ++--
 fs/gfs2/inode.c                           |   10 +++++-----
 fs/hfs/inode.c                            |    4 ++--
 fs/hfsplus/inode.c                        |    4 ++--
 fs/hpfs/namei.c                           |   24 ++++++++++++------------
 fs/hugetlbfs/inode.c                      |   16 ++++++++--------
 fs/jffs2/fs.c                             |    4 ++--
 fs/jfs/jfs_inode.c                        |    4 ++--
 fs/locks.c                                |    2 +-
 fs/minix/bitmap.c                         |    4 ++--
 fs/namei.c                                |    8 ++++----
 fs/nfsd/vfs.c                             |    4 ++--
 fs/ocfs2/dlm/dlmfs.c                      |    8 ++++----
 fs/ocfs2/namei.c                          |    4 ++--
 fs/pipe.c                                 |    4 ++--
 fs/posix_acl.c                            |    4 ++--
 fs/ramfs/inode.c                          |    4 ++--
 fs/reiserfs/namei.c                       |    4 ++--
 fs/sysv/ialloc.c                          |    4 ++--
 fs/udf/ialloc.c                           |    4 ++--
 fs/udf/namei.c                            |    2 +-
 fs/ufs/ialloc.c                           |    4 ++--
 fs/xfs/linux-2.6/xfs_linux.h              |    4 ++--
 fs/xfs/xfs_acl.c                          |    6 +++---
 fs/xfs/xfs_attr.c                         |    2 +-
 fs/xfs/xfs_inode.c                        |    6 +++---
 fs/xfs/xfs_vnodeops.c                     |    8 ++++----
 include/linux/fs.h                        |    2 +-
 include/linux/sched.h                     |    3 +++
 ipc/mqueue.c                              |    4 ++--
 kernel/cgroup.c                           |    4 ++--
 mm/shmem.c                                |    8 ++++----
 net/9p/client.c                           |    2 +-
 net/socket.c                              |    4 ++--
 net/sunrpc/auth.c                         |    8 ++++----
 security/commoncap.c                      |    8 ++++----
 security/keys/key.c                       |    2 +-
 security/keys/keyctl.c                    |    2 +-
 security/keys/request_key.c               |   10 +++++-----
 security/keys/request_key_auth.c          |    2 +-
 67 files changed, 163 insertions(+), 160 deletions(-)

diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 73e7c2e..ef383d9 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2206,8 +2206,8 @@ pfm_alloc_fd(struct file **cfile)
 	DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode));
 
 	inode->i_mode = S_IFCHR|S_IRUGO;
-	inode->i_uid  = current->fsuid;
-	inode->i_gid  = current->fsgid;
+	inode->i_uid  = current_fsuid();
+	inode->i_gid  = current_fsgid();
 
 	sprintf(name, "[%lu]", inode->i_ino);
 	this.name = name;
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index c0e968a..4efe7bf 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -85,8 +85,8 @@ spufs_new_inode(struct super_block *sb, int mode)
 		goto out;
 
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
 	inode->i_blocks = 0;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 out:
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index 2dd1b57..26b9aea 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -148,8 +148,8 @@ void capifs_new_ncci(unsigned int number, dev_t device)
 	if (!inode)
 		return;
 	inode->i_ino = number+2;
-	inode->i_uid = config.setuid ? config.uid : current->fsuid;
-	inode->i_gid = config.setgid ? config.gid : current->fsgid;
+	inode->i_uid = config.setuid ? config.uid : current_fsuid();
+	inode->i_gid = config.setgid ? config.gid : current_fsgid();
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	//inode->i_op = &capifs_file_inode_operations;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index cd4f111..9173eae 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -246,8 +246,8 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
 
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current_fsuid();
+		inode->i_gid = current_fsgid();
 		inode->i_blocks = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		switch (mode & S_IFMT) {
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index b364da7..cd7799c 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -121,7 +121,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
 	switch (access) {
 	case V9FS_ACCESS_SINGLE:
 	case V9FS_ACCESS_USER:
-		uid = current->fsuid;
+		uid = current_fsuid();
 		any = 0;
 		break;
 
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 23581bc..b6d7fc9 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -202,8 +202,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 	inode = new_inode(sb);
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current_fsuid();
+		inode->i_gid = current_fsgid();
 		inode->i_blocks = 0;
 		inode->i_rdev = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 678c02f..465520d 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -112,8 +112,8 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
 	struct v9fs_session_info *v9ses = NULL;
 	struct p9_stat *st = NULL;
 	int mode = S_IRWXUGO | S_ISVTX;
-	uid_t uid = current->fsuid;
-	gid_t gid = current->fsgid;
+	uid_t uid = current_fsuid();
+	gid_t gid = current_fsgid();
 	struct p9_fid *fid;
 	int retval = 0;
 
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 4609a6c..fb84ebc 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -305,8 +305,8 @@ affs_new_inode(struct inode *dir)
 	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
 
-	inode->i_uid     = current->fsuid;
-	inode->i_gid     = current->fsgid;
+	inode->i_uid     = current_fsuid();
+	inode->i_gid     = current_fsgid();
 	inode->i_ino     = block;
 	inode->i_nlink   = 1;
 	inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 2332188..a2f6a13 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -162,8 +162,8 @@ static struct inode *anon_inode_mkinode(void)
 	 */
 	inode->i_state = I_DIRTY;
 	inode->i_mode = S_IRUSR | S_IWUSR;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	return inode;
 }
diff --git a/fs/attr.c b/fs/attr.c
index 966b73e..117cca7 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -29,13 +29,13 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
 
 	/* Make sure a caller can chown. */
 	if ((ia_valid & ATTR_UID) &&
-	    (current->fsuid != inode->i_uid ||
+	    (current_fsuid() != inode->i_uid ||
 	     attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
 		goto error;
 
 	/* Make sure caller can chgrp. */
 	if ((ia_valid & ATTR_GID) &&
-	    (current->fsuid != inode->i_uid ||
+	    (current_fsuid() != inode->i_uid ||
 	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
 	    !capable(CAP_CHOWN))
 		goto error;
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 1fd056d..499c531 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -104,8 +104,8 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	}
 	set_bit(ino, info->si_imap);
 	info->si_freei--;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current_fsgid();
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_blocks = 0;
 	inode->i_op = &bfs_file_inops;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 8350eec..1c659db 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -39,7 +39,7 @@ extern int smb_send(struct socket *, struct smb_hdr *,
 			unsigned int /* length */ , struct sockaddr *);
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
-#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current_fsuid()));
 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 37dc97a..728726a 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -211,8 +211,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 			mode &= ~current->fs->umask;
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
-					(__u64)current->fsuid,
-					(__u64)current->fsgid,
+					(__u64)current_fsuid(),
+					(__u64)current_fsgid(),
 					0 /* dev */,
 					cifs_sb->local_nls,
 					cifs_sb->mnt_cifs_flags &
@@ -246,8 +246,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 				if ((oplock & CIFS_CREATE_ACTION) &&
 				    (cifs_sb->mnt_cifs_flags &
 				     CIFS_MOUNT_SET_UID)) {
-					newinode->i_uid = current->fsuid;
-					newinode->i_gid = current->fsgid;
+					newinode->i_uid = current_fsuid();
+					newinode->i_gid = current_fsgid();
 				}
 			}
 		}
@@ -340,8 +340,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
 		mode &= ~current->fs->umask;
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
-				mode, (__u64)current->fsuid,
-				(__u64)current->fsgid,
+				mode, (__u64)current_fsuid(),
+				(__u64)current_fsgid(),
 				device_number, cifs_sb->local_nls,
 				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index e915eb1..8040b1b 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1031,8 +1031,8 @@ mkdir_get_info:
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
 						    mode,
-						    (__u64)current->fsuid,
-						    (__u64)current->fsgid,
+						    (__u64)current_fsuid(),
+						    (__u64)current_fsgid(),
 						    0 /* dev_t */,
 						    cifs_sb->local_nls,
 						    cifs_sb->mnt_cifs_flags &
@@ -1055,9 +1055,9 @@ mkdir_get_info:
 				if (cifs_sb->mnt_cifs_flags &
 				     CIFS_MOUNT_SET_UID) {
 					direntry->d_inode->i_uid =
-						current->fsuid;
+						current_fsuid();
 					direntry->d_inode->i_gid =
-						current->fsgid;
+						current_fsgid();
 				}
 			}
 		}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 15546c2..b862231 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -351,13 +351,13 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
 		/*  BB Add support for establishing new tCon and SMB Session  */
 		/*      with userid/password pairs found on the smb session   */
 		/*	for other target tcp/ip addresses 		BB    */
-				if (current->fsuid != treeCon->ses->linux_uid) {
+				if (current_fsuid() != treeCon->ses->linux_uid) {
 					cFYI(1, ("Multiuser mode and UID "
 						 "did not match tcon uid"));
 					read_lock(&GlobalSMBSeslock);
 					list_for_each(temp_item, &GlobalSMBSessionList) {
 						ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
-						if (ses->linux_uid == current->fsuid) {
+						if (ses->linux_uid == current_fsuid()) {
 							if (ses->server == treeCon->ses->server) {
 								cFYI(1, ("found matching uid substitute right smb_uid"));
 								buffer->Uid = ses->Suid;
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 8a23703..a5bf577 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -32,8 +32,8 @@ void coda_cache_enter(struct inode *inode, int mask)
 	struct coda_inode_info *cii = ITOC(inode);
 
 	cii->c_cached_epoch = atomic_read(&permission_epoch);
-	if (cii->c_uid != current->fsuid) {
-                cii->c_uid = current->fsuid;
+	if (cii->c_uid != current_fsuid()) {
+		cii->c_uid = current_fsuid();
                 cii->c_cached_perm = mask;
         } else
                 cii->c_cached_perm |= mask;
@@ -60,7 +60,7 @@ int coda_cache_check(struct inode *inode, int mask)
         int hit;
 	
         hit = (mask & cii->c_cached_perm) == mask &&
-		cii->c_uid == current->fsuid &&
+		cii->c_uid == current_fsuid() &&
 		cii->c_cached_epoch == atomic_read(&permission_epoch);
 
         return hit;
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 359e531..806e6aa 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -54,9 +54,9 @@ static void *alloc_upcall(int opcode, int size)
 	inp->ih.pgid = task_pgrp_nr(current);
 #ifdef CONFIG_CODA_FS_OLD_API
 	memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
-	inp->ih.cred.cr_fsuid = current->fsuid;
+	inp->ih.cred.cr_fsuid = current_fsuid();
 #else
-	inp->ih.uid = current->fsuid;
+	inp->ih.uid = current_fsuid();
 #endif
 	return (void*)inp;
 }
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 06ef9a2..1c9ffd9 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -172,8 +172,8 @@ int devpts_pty_new(struct tty_struct *tty)
 		return -ENOMEM;
 
 	inode->i_ino = number+2;
-	inode->i_uid = config.setuid ? config.uid : current->fsuid;
-	inode->i_gid = config.setgid ? config.gid : current->fsgid;
+	inode->i_uid = config.setuid ? config.uid : current_fsuid();
+	inode->i_gid = config.setgid ? config.gid : current_fsgid();
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	inode->i_private = tty;
diff --git a/fs/dquot.c b/fs/dquot.c
index 2809768..3dc58a8 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -837,7 +837,7 @@ static inline int need_print_warning(struct dquot *dquot)
 
 	switch (dquot->dq_type) {
 		case USRQUOTA:
-			return current->fsuid == dquot->dq_id;
+			return current_fsuid() == dquot->dq_id;
 		case GRPQUOTA:
 			return in_group_p(dquot->dq_id);
 	}
diff --git a/fs/exec.c b/fs/exec.c
index 282240a..a09ce1b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1678,7 +1678,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	struct inode * inode;
 	struct file * file;
 	int retval = 0;
-	int fsuid = current->fsuid;
+	int fsuid = current_fsuid();
 	int flag = 0;
 	int ispipe = 0;
 	unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
@@ -1784,7 +1784,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	 * Dont allow local users get cute and trick others to coredump
 	 * into their pre-created files:
 	 */
-	if (inode->i_uid != current->fsuid)
+	if (inode->i_uid != current_fsuid())
 		goto close_fail;
 	if (!file->f_op)
 		goto close_fail;
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 377ad17..bbddd14 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -1128,7 +1128,7 @@ static int ext2_has_free_blocks(struct ext2_sb_info *sbi)
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current->fsuid &&
+		sbi->s_resuid != current_fsuid() &&
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		return 0;
 	}
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 5deb8b7..1d020a9 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -554,7 +554,7 @@ got:
 
 	sb->s_dirt = 1;
 	mark_buffer_dirty(bh2);
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -562,7 +562,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 	inode->i_mode = mode;
 
 	inode->i_ino = ino;
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 320b2cb..f5fdb95 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -105,7 +105,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		if (IS_RDONLY(inode))
 			return -EROFS;
 
-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
 			return -EACCES;
 
 		if (get_user(rsv_window_size, (int __user *)arg))
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index a8ba7e8..55e39a3 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1360,7 +1360,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current->fsuid &&
+		sbi->s_resuid != current_fsuid() &&
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		return 0;
 	}
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 1bc8cd8..fe20718 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -543,7 +543,7 @@ got:
 		percpu_counter_inc(&sbi->s_dirs_counter);
 	sb->s_dirt = 1;
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -551,7 +551,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 	inode->i_mode = mode;
 
 	inode->i_ino = ino;
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 71ee95e..a67d6bc 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1480,7 +1480,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = ext4_r_blocks_count(sbi->s_es);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current->fsuid &&
+		sbi->s_resuid != current_fsuid() &&
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		return 0;
 	}
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index c61f37f..37e95d2 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -674,7 +674,7 @@ got:
 		percpu_counter_inc(&sbi->s_dirs_counter);
 	sb->s_dirt = 1;
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -682,7 +682,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 	inode->i_mode = mode;
 
 	inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index db534bc..471a256 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -79,8 +79,8 @@ static void __fuse_put_request(struct fuse_req *req)
 
 static void fuse_req_init_context(struct fuse_req *req)
 {
-	req->in.h.uid = current->fsuid;
-	req->in.h.gid = current->fsgid;
+	req->in.h.uid = current_fsuid();
+	req->in.h.gid = current_fsgid();
 	req->in.h.pid = current->pid;
 }
 
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 5f6dc32..7719132 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -688,18 +688,18 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
 	    (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
 		if (S_ISDIR(*mode))
 			*mode |= S_ISUID;
-		else if (dip->i_inode.i_uid != current->fsuid)
+		else if (dip->i_inode.i_uid != current_fsuid())
 			*mode &= ~07111;
 		*uid = dip->i_inode.i_uid;
 	} else
-		*uid = current->fsuid;
+		*uid = current_fsuid();
 
 	if (dip->i_inode.i_mode & S_ISGID) {
 		if (S_ISDIR(*mode))
 			*mode |= S_ISGID;
 		*gid = dip->i_inode.i_gid;
 	} else
-		*gid = current->fsgid;
+		*gid = current_fsgid();
 }
 
 static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
@@ -1108,8 +1108,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
 		return -EPERM;
 
 	if ((dip->i_inode.i_mode & S_ISVTX) &&
-	    dip->i_inode.i_uid != current->fsuid &&
-	    ip->i_inode.i_uid != current->fsuid && !capable(CAP_FOWNER))
+	    dip->i_inode.i_uid != current_fsuid() &&
+	    ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER))
 		return -EPERM;
 
 	if (IS_APPEND(&dip->i_inode))
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 97f8446..29caee5 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -155,8 +155,8 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
 	hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
 	inode->i_ino = HFS_SB(sb)->next_id++;
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
 	inode->i_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	HFS_I(inode)->flags = 0;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 37744cf..af54c28 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -312,8 +312,8 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
 
 	inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
 	inode->i_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index d256559..2af4578 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -92,11 +92,11 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	inc_nlink(dir);
 	insert_inode_hash(result);
 
-	if (result->i_uid != current->fsuid ||
-	    result->i_gid != current->fsgid ||
+	if (result->i_uid != current_fsuid() ||
+	    result->i_gid != current_fsgid() ||
 	    result->i_mode != (mode | S_IFDIR)) {
-		result->i_uid = current->fsuid;
-		result->i_gid = current->fsgid;
+		result->i_uid = current_fsuid();
+		result->i_gid = current_fsgid();
 		result->i_mode = mode | S_IFDIR;
 		hpfs_write_inode_nolock(result);
 	}
@@ -184,11 +184,11 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
 
 	insert_inode_hash(result);
 
-	if (result->i_uid != current->fsuid ||
-	    result->i_gid != current->fsgid ||
+	if (result->i_uid != current_fsuid() ||
+	    result->i_gid != current_fsgid() ||
 	    result->i_mode != (mode | S_IFREG)) {
-		result->i_uid = current->fsuid;
-		result->i_gid = current->fsgid;
+		result->i_uid = current_fsuid();
+		result->i_gid = current_fsgid();
 		result->i_mode = mode | S_IFREG;
 		hpfs_write_inode_nolock(result);
 	}
@@ -247,8 +247,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
 	result->i_mtime.tv_nsec = 0;
 	result->i_atime.tv_nsec = 0;
 	hpfs_i(result)->i_ea_size = 0;
-	result->i_uid = current->fsuid;
-	result->i_gid = current->fsgid;
+	result->i_uid = current_fsuid();
+	result->i_gid = current_fsgid();
 	result->i_nlink = 1;
 	result->i_size = 0;
 	result->i_blocks = 1;
@@ -325,8 +325,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
 	result->i_atime.tv_nsec = 0;
 	hpfs_i(result)->i_ea_size = 0;
 	result->i_mode = S_IFLNK | 0777;
-	result->i_uid = current->fsuid;
-	result->i_gid = current->fsgid;
+	result->i_uid = current_fsuid();
+	result->i_gid = current_fsgid();
 	result->i_blocks = 1;
 	result->i_nlink = 1;
 	result->i_size = strlen(symlink);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 09ee07f..39ad919 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -543,9 +543,9 @@ static int hugetlbfs_mknod(struct inode *dir,
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else {
-		gid = current->fsgid;
+		gid = current_fsgid();
 	}
-	inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid, gid, mode, dev);
+	inode = hugetlbfs_get_inode(dir->i_sb, current_fsuid(), gid, mode, dev);
 	if (inode) {
 		dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 		d_instantiate(dentry, inode);
@@ -578,9 +578,9 @@ static int hugetlbfs_symlink(struct inode *dir,
 	if (dir->i_mode & S_ISGID)
 		gid = dir->i_gid;
 	else
-		gid = current->fsgid;
+		gid = current_fsgid();
 
-	inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid,
+	inode = hugetlbfs_get_inode(dir->i_sb, current_fsuid(),
 					gid, S_IFLNK|S_IRWXUGO, 0);
 	if (inode) {
 		int l = strlen(symname)+1;
@@ -819,8 +819,8 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
 
 	config.nr_blocks = -1; /* No limit on size by default */
 	config.nr_inodes = -1; /* No limit on number of inodes by default */
-	config.uid = current->fsuid;
-	config.gid = current->fsgid;
+	config.uid = current_fsuid();
+	config.gid = current_fsgid();
 	config.mode = 0755;
 	ret = hugetlbfs_parse_options(data, &config);
 	if (ret)
@@ -933,8 +933,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
 		goto out_shm_unlock;
 
 	error = -ENOSPC;
-	inode = hugetlbfs_get_inode(root->d_sb, current->fsuid,
-				current->fsgid, S_IFREG | S_IRWXUGO, 0);
+	inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(),
+				current_fsgid(), S_IFREG | S_IRWXUGO, 0);
 	if (!inode)
 		goto out_dentry;
 
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index d2e06f7..61849f3 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -425,14 +425,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
 
 	memset(ri, 0, sizeof(*ri));
 	/* Set OS-specific defaults for new inodes */
-	ri->uid = cpu_to_je16(current->fsuid);
+	ri->uid = cpu_to_je16(current_fsuid());
 
 	if (dir_i->i_mode & S_ISGID) {
 		ri->gid = cpu_to_je16(dir_i->i_gid);
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else {
-		ri->gid = cpu_to_je16(current->fsgid);
+		ri->gid = cpu_to_je16(current_fsgid());
 	}
 
 	/* POSIX ACLs have to be processed now, at least partly.
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index ed6574b..70022fd 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -93,13 +93,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
 		return ERR_PTR(rc);
 	}
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (parent->i_mode & S_ISGID) {
 		inode->i_gid = parent->i_gid;
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 
 	/*
 	 * New inodes need to save sane values on disk when
diff --git a/fs/locks.c b/fs/locks.c
index 8b8388e..359030b 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1358,7 +1358,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 	struct inode *inode = dentry->d_inode;
 	int error, rdlease_count = 0, wrlease_count = 0;
 
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
+	if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE))
 		return -EACCES;
 	if (!S_ISREG(inode->i_mode))
 		return -EINVAL;
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 703cc35..3aebe32 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -262,8 +262,8 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
 		iput(inode);
 		return NULL;
 	}
-	inode->i_uid = current->fsuid;
-	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current_fsgid();
 	inode->i_ino = j;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_blocks = 0;
diff --git a/fs/namei.c b/fs/namei.c
index 3b993db..8963e91 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -184,7 +184,7 @@ int generic_permission(struct inode *inode, int mask,
 {
 	umode_t			mode = inode->i_mode;
 
-	if (current->fsuid == inode->i_uid)
+	if (current_fsuid() == inode->i_uid)
 		mode >>= 6;
 	else {
 		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
@@ -452,7 +452,7 @@ static int exec_permission_lite(struct inode *inode,
 	if (inode->i_op && inode->i_op->permission)
 		return -EAGAIN;
 
-	if (current->fsuid == inode->i_uid)
+	if (current_fsuid() == inode->i_uid)
 		mode >>= 6;
 	else if (in_group_p(inode->i_gid))
 		mode >>= 3;
@@ -1435,9 +1435,9 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
 {
 	if (!(dir->i_mode & S_ISVTX))
 		return 0;
-	if (inode->i_uid == current->fsuid)
+	if (inode->i_uid == current_fsuid())
 		return 0;
-	if (dir->i_uid == current->fsuid)
+	if (dir->i_uid == current_fsuid())
 		return 0;
 	return !capable(CAP_FOWNER);
 }
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index d019918..f11c48d 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1857,7 +1857,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
 		IS_APPEND(inode)?	" append" : "",
 		IS_RDONLY(inode)?	" ro" : "");
 	dprintk("      owner %d/%d user %d/%d\n",
-		inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
+		inode->i_uid, inode->i_gid, current_fsuid(), current->fsgid);
 #endif
 
 	/* Normally we reject any write/sattr etc access on a read-only file
@@ -1899,7 +1899,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
 	 * with NFSv3.
 	 */
 	if ((acc & MAY_OWNER_OVERRIDE) &&
-	    inode->i_uid == current->fsuid)
+	    inode->i_uid == current_fsuid())
 		return 0;
 
 	err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 6639baa..ea65979 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -328,8 +328,8 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
 		ip = DLMFS_I(inode);
 
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current_fsuid();
+		inode->i_gid = current_fsgid();
 		inode->i_blocks = 0;
 		inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -354,8 +354,8 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
 		return NULL;
 
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
 	inode->i_blocks = 0;
 	inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 989ac27..86e2717 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -426,13 +426,13 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
 	fe->i_blkno = cpu_to_le64(fe_blkno);
 	fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
 	fe->i_suballoc_slot = cpu_to_le16(osb->slot_num);
-	fe->i_uid = cpu_to_le32(current->fsuid);
+	fe->i_uid = cpu_to_le32(current_fsuid());
 	if (dir->i_mode & S_ISGID) {
 		fe->i_gid = cpu_to_le32(dir->i_gid);
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		fe->i_gid = cpu_to_le32(current->fsgid);
+		fe->i_gid = cpu_to_le32(current_fsgid());
 	fe->i_mode = cpu_to_le16(mode);
 	if (S_ISCHR(mode) || S_ISBLK(mode))
 		fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
diff --git a/fs/pipe.c b/fs/pipe.c
index e66ec48..598cf6c 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -938,8 +938,8 @@ static struct inode * get_pipe_inode(void)
 	 */
 	inode->i_state = I_DIRTY;
 	inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
 	return inode;
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index aec931e..39df95a 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -217,11 +217,11 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
                 switch(pa->e_tag) {
                         case ACL_USER_OBJ:
 				/* (May have been checked already) */
-                                if (inode->i_uid == current->fsuid)
+				if (inode->i_uid == current_fsuid())
                                         goto check_perm;
                                 break;
                         case ACL_USER:
-                                if (pa->e_id == current->fsuid)
+				if (pa->e_id == current_fsuid())
                                         goto mask;
 				break;
                         case ACL_GROUP_OBJ:
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 8428d5b..98421f7 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -55,8 +55,8 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
 
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current_fsuid();
+		inode->i_gid = current_fsgid();
 		inode->i_blocks = 0;
 		inode->i_mapping->a_ops = &ramfs_aops;
 		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index b378eea..84458f3 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -582,7 +582,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
 	/* the quota init calls have to know who to charge the quota to, so
 	 ** we have to set uid and gid here
 	 */
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	inode->i_mode = mode;
 	/* Make inode invalid - just in case we are going to drop it before
 	 * the initialization happens */
@@ -593,7 +593,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
 		if (S_ISDIR(mode))
 			inode->i_mode |= S_ISGID;
 	} else {
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 	}
 	DQUOT_INIT(inode);
 	return 0;
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index 115ab0d..241e976 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -165,9 +165,9 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	inode->i_ino = fs16_to_cpu(sbi, ino);
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_blocks = 0;
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 636d8f6..1f3c01a 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -105,13 +105,13 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
 		mark_buffer_dirty(UDF_SB_LVIDBH(sb));
 	}
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (dir->i_mode & S_ISGID) {
 		inode->i_gid = dir->i_gid;
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else {
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 	}
 
 	UDF_I_LOCATION(inode).logicalBlockNum = block;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index bec96a6..e2d466c 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -636,7 +636,7 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
 	if (!inode)
 		goto out;
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	init_special_inode(inode, mode, rdev);
 	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
 		inode->i_nlink--;
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 7e260bc..88f8889 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -304,13 +304,13 @@ cg_found:
 
 	inode->i_ino = cg * uspi->s_ipg + bit;
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (dir->i_mode & S_ISGID) {
 		inode->i_gid = dir->i_gid;
 		if (S_ISDIR(mode))
 			inode->i_mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 
 	inode->i_blocks = 0;
 	inode->i_generation = 0;
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index dc3752d..0b943dd 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -126,8 +126,8 @@
 
 #define current_cpu()		(raw_smp_processor_id())
 #define current_pid()		(current->pid)
-#define current_fsuid(cred)	(current->fsuid)
-#define current_fsgid(cred)	(current->fsgid)
+#define this_fsuid(cred)	(current_fsuid())
+#define this_fsgid(cred)	(current_fsgid())
 #define current_test_flags(f)	(current->flags & (f))
 #define current_set_flags_nested(sp, f)		\
 		(*(sp) = current->flags, current->flags |= (f))
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 5bfb66f..878ca6e 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -386,7 +386,7 @@ xfs_acl_allow_set(
 	error = xfs_getattr(ip, &va, 0);
 	if (error)
 		return error;
-	if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
+	if (va.va_uid != current_fsuid() && !capable(CAP_FOWNER))
 		return EPERM;
 	return error;
 }
@@ -460,13 +460,13 @@ xfs_acl_access(
 		switch (fap->acl_entry[i].ae_tag) {
 		case ACL_USER_OBJ:
 			seen_userobj = 1;
-			if (fuid != current->fsuid)
+			if (fuid != current_fsuid())
 				continue;
 			matched.ae_tag = ACL_USER_OBJ;
 			matched.ae_perm = allows;
 			break;
 		case ACL_USER:
-			if (fap->acl_entry[i].ae_id != current->fsuid)
+			if (fap->acl_entry[i].ae_id != current_fsuid())
 				continue;
 			matched.ae_tag = ACL_USER;
 			matched.ae_perm = allows;
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 93fa64d..33c1173 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -2627,7 +2627,7 @@ attr_user_capable(
 	    !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
-	    (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
+	    (this_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
 		return -EPERM;
 	return 0;
 }
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index abf509a..31eba0d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1132,8 +1132,8 @@ xfs_ialloc(
 	ip->i_d.di_onlink = 0;
 	ip->i_d.di_nlink = nlink;
 	ASSERT(ip->i_d.di_nlink == nlink);
-	ip->i_d.di_uid = current_fsuid(cr);
-	ip->i_d.di_gid = current_fsgid(cr);
+	ip->i_d.di_uid = this_fsuid(cr);
+	ip->i_d.di_gid = this_fsgid(cr);
 	ip->i_d.di_projid = prid;
 	memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
 
@@ -3640,7 +3640,7 @@ xfs_iaccess(
 	if ((error = _ACL_XFS_IACCESS(ip, mode, cr)) != -1)
 		return error ? XFS_ERROR(error) : 0;
 
-	if (current_fsuid(cr) != ip->i_d.di_uid) {
+	if (this_fsuid(cr) != ip->i_d.di_uid) {
 		mode >>= 3;
 		if (!in_group_p((gid_t)ip->i_d.di_gid))
 			mode >>= 3;
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index efd5aff..86bc8ec 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -341,7 +341,7 @@ xfs_setattr(
 	xfs_ilock(ip, lock_flags);
 
 	/* boolean: are we the file owner? */
-	file_owner = (current_fsuid(credp) == ip->i_d.di_uid);
+	file_owner = (this_fsuid(credp) == ip->i_d.di_uid);
 
 	/*
 	 * Change various properties of a file.
@@ -1878,7 +1878,7 @@ xfs_create(
 	 * Make sure that we have allocated dquot(s) on disk.
 	 */
 	error = XFS_QM_DQVOPALLOC(mp, dp,
-			current_fsuid(credp), current_fsgid(credp), prid,
+			this_fsuid(credp), this_fsgid(credp), prid,
 			XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
 	if (error)
 		goto std_return;
@@ -2757,7 +2757,7 @@ xfs_mkdir(
 	 * Make sure that we have allocated dquot(s) on disk.
 	 */
 	error = XFS_QM_DQVOPALLOC(mp, dp,
-			current_fsuid(credp), current_fsgid(credp), prid,
+			this_fsuid(credp), this_fsgid(credp), prid,
 			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
 	if (error)
 		goto std_return;
@@ -3249,7 +3249,7 @@ xfs_symlink(
 	 * Make sure that we have allocated dquot(s) on disk.
 	 */
 	error = XFS_QM_DQVOPALLOC(mp, dp,
-			current_fsuid(credp), current_fsgid(credp), prid,
+			this_fsuid(credp), this_fsgid(credp), prid,
 			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
 	if (error)
 		goto std_return;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b3ec4a4..850d3fc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1057,7 +1057,7 @@ enum {
 #define has_fs_excl() atomic_read(&current->fs_excl)
 
 #define is_owner_or_cap(inode)	\
-	((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER))
+	((current_fsuid() == (inode)->i_uid) || capable(CAP_FOWNER))
 
 /* not quite ready to be deprecated, but... */
 extern void lock_super(struct super_block *);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ac3d496..88a5626 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1180,6 +1180,9 @@ struct task_struct {
 	struct prop_local_single dirties;
 };
 
+#define current_fsuid() (current->fsuid)
+#define current_fsgid() (current->fsgid)
+
 /*
  * Priority of a process goes from 0..MAX_PRIO-1, valid RT
  * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 6ca7b97..590045a 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -109,8 +109,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
 	inode = new_inode(sb);
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current_fsuid();
+		inode->i_gid = current_fsgid();
 		inode->i_blocks = 0;
 		inode->i_mtime = inode->i_ctime = inode->i_atime =
 				CURRENT_TIME;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 1a3c239..1b85df5 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -577,8 +577,8 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
 
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current_fsuid();
+		inode->i_gid = current_fsgid();
 		inode->i_blocks = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
diff --git a/mm/shmem.c b/mm/shmem.c
index 51b3d6c..292b329 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1412,8 +1412,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 	inode = new_inode(sb);
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current_fsuid();
+		inode->i_gid = current_fsgid();
 		inode->i_blocks = 0;
 		inode->i_mapping->a_ops = &shmem_aops;
 		inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
@@ -2241,8 +2241,8 @@ static int shmem_fill_super(struct super_block *sb,
 	struct inode *inode;
 	struct dentry *root;
 	int mode   = S_IRWXUGO | S_ISVTX;
-	uid_t uid = current->fsuid;
-	gid_t gid = current->fsgid;
+	uid_t uid = current_fsuid();
+	gid_t gid = current_fsgid();
 	int err = -ENOMEM;
 	struct shmem_sb_info *sbinfo;
 	unsigned long blocks = 0;
diff --git a/net/9p/client.c b/net/9p/client.c
index af91993..9cb8b3b 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -938,7 +938,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 	fid->rdir_fpos = 0;
 	fid->rdir_pos = 0;
 	fid->rdir_fcall = NULL;
-	fid->uid = current->fsuid;
+	fid->uid = current_fsuid();
 	fid->clnt = clnt;
 	fid->aux = NULL;
 
diff --git a/net/socket.c b/net/socket.c
index 74784df..e5f8151 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -484,8 +484,8 @@ static struct socket *sock_alloc(void)
 	sock = SOCKET_I(inode);
 
 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
 
 	get_cpu_var(sockets_in_use)++;
 	put_cpu_var(sockets_in_use);
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 1ea2755..390a1ec 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -337,8 +337,8 @@ struct rpc_cred *
 rpcauth_lookupcred(struct rpc_auth *auth, int flags)
 {
 	struct auth_cred acred = {
-		.uid = current->fsuid,
-		.gid = current->fsgid,
+		.uid = current_fsuid(),
+		.gid = current_fsgid(),
 		.group_info = current->group_info,
 	};
 	struct rpc_cred *ret;
@@ -373,8 +373,8 @@ rpcauth_bindcred(struct rpc_task *task)
 {
 	struct rpc_auth *auth = task->tk_client->cl_auth;
 	struct auth_cred acred = {
-		.uid = current->fsuid,
-		.gid = current->fsgid,
+		.uid = current_fsuid(),
+		.gid = current_fsgid(),
 		.group_info = current->group_info,
 	};
 	struct rpc_cred *ret;
diff --git a/security/commoncap.c b/security/commoncap.c
index 5bc1895..bbe188e 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -336,8 +336,8 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
 		}
 	}
 
-	current->suid = current->euid = current->fsuid = bprm->e_uid;
-	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+	current->suid = current->euid = current_fsuid() = bprm->e_uid;
+	current->sgid = current->egid = current_fsgid() = bprm->e_gid;
 
 	/* For init, we want to retain the capabilities set
 	 * in the init_task struct. Thus we skip the usual
@@ -466,11 +466,11 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
 			 */
 
 			if (!issecure (SECURE_NO_SETUID_FIXUP)) {
-				if (old_fsuid == 0 && current->fsuid != 0) {
+				if (old_fsuid == 0 && current_fsuid() != 0) {
 					cap_t (current->cap_effective) &=
 					    ~CAP_FS_MASK;
 				}
-				if (old_fsuid != 0 && current->fsuid == 0) {
+				if (old_fsuid != 0 && current_fsuid() == 0) {
 					cap_t (current->cap_effective) |=
 					    (cap_t (current->cap_permitted) &
 					     CAP_FS_MASK);
diff --git a/security/keys/key.c b/security/keys/key.c
index fdd5ca6..48fabb1 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -817,7 +817,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 		perm |= KEY_USR_WRITE;
 
 	/* allocate a new key */
-	key = key_alloc(ktype, description, current->fsuid, current->fsgid,
+	key = key_alloc(ktype, description, current_fsuid(), current->fsgid,
 			current, perm, flags);
 	if (IS_ERR(key)) {
 		key_ref = ERR_PTR(PTR_ERR(key));
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 56e963b..b3a63dd 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -810,7 +810,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
 	down_write(&key->sem);
 
 	/* if we're not the sysadmin, we can only change a key that we own */
-	if (capable(CAP_SYS_ADMIN) || key->uid == current->fsuid) {
+	if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) {
 		key->perm = perm;
 		ret = 0;
 	}
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index aee4897..6d25911 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -76,7 +76,7 @@ static int call_sbin_request_key(struct key_construction *cons,
 	/* allocate a new session keyring */
 	sprintf(desc, "_req.%u", key->serial);
 
-	keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current,
+	keyring = keyring_alloc(desc, current_fsuid(), current->fsgid, current,
 				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
@@ -89,8 +89,8 @@ static int call_sbin_request_key(struct key_construction *cons,
 		goto error_link;
 
 	/* record the UID and GID */
-	sprintf(uid_str, "%d", current->fsuid);
-	sprintf(gid_str, "%d", current->fsgid);
+	sprintf(uid_str, "%d", current_fsuid());
+	sprintf(gid_str, "%d", current_fsgid());
 
 	/* we say which key is under construction */
 	sprintf(key_str, "%d", key->serial);
@@ -278,7 +278,7 @@ static int construct_alloc_key(struct key_type *type,
 	mutex_lock(&user->cons_lock);
 
 	key = key_alloc(type, description,
-			current->fsuid, current->fsgid, current, KEY_POS_ALL,
+			current_fsuid(), current->fsgid, current, KEY_POS_ALL,
 			flags);
 	if (IS_ERR(key))
 		goto alloc_failed;
@@ -341,7 +341,7 @@ static struct key *construct_key_and_link(struct key_type *type,
 	struct key *key;
 	int ret;
 
-	user = key_user_lookup(current->fsuid);
+	user = key_user_lookup(current_fsuid());
 	if (!user)
 		return ERR_PTR(-ENOMEM);
 
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 6827ae3..cce6b4d 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -194,7 +194,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 	sprintf(desc, "%x", target->serial);
 
 	authkey = key_alloc(&key_type_request_key_auth, desc,
-			    current->fsuid, current->fsgid, current,
+			    current_fsuid(), current->fsgid, current,
 			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
 			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
 	if (IS_ERR(authkey)) {


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

* [PATCH 6/7] SECURITY: Separate task security context from task_struct
  2007-12-05 19:37 [PATCH 0/7] Permit filesystem local caching David Howells
                   ` (4 preceding siblings ...)
  2007-12-05 19:37 ` [PATCH 5/7] Security: Change current->fs[ug]id to current_fs[ug]id() David Howells
@ 2007-12-05 19:37 ` David Howells
  2007-12-05 19:37 ` [PATCH 7/7] SECURITY: De-embed task security record from task and use refcounting David Howells
  6 siblings, 0 replies; 14+ messages in thread
From: David Howells @ 2007-12-05 19:37 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells

Separate the task security context from task_struct.  At this point, the
security data is temporarily embedded in the task_struct with two pointers
pointing to it.

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

 drivers/block/loop.c             |    5 -
 drivers/char/agp/frontend.c      |    2 
 drivers/char/drm/drm_fops.c      |    2 
 drivers/char/tty_audit.c         |    2 
 fs/affs/super.c                  |    4 -
 fs/autofs/inode.c                |    4 -
 fs/autofs4/inode.c               |    4 -
 fs/autofs4/waitq.c               |    4 -
 fs/binfmt_elf.c                  |   12 +-
 fs/cifs/connect.c                |    5 -
 fs/cifs/ioctl.c                  |    2 
 fs/ecryptfs/messaging.c          |   15 +-
 fs/exec.c                        |   20 ++-
 fs/fat/inode.c                   |    4 -
 fs/fcntl.c                       |    7 +
 fs/file_table.c                  |    4 -
 fs/fuse/dir.c                    |   12 +-
 fs/hfs/super.c                   |    4 -
 fs/hfsplus/options.c             |    4 -
 fs/hpfs/super.c                  |    4 -
 fs/hugetlbfs/inode.c             |    4 -
 fs/inotify_user.c                |    2 
 fs/ioprio.c                      |   12 +-
 fs/namei.c                       |    6 +
 fs/ncpfs/ioctl.c                 |   32 ++---
 fs/open.c                        |   22 ++-
 fs/proc/array.c                  |   14 +-
 fs/proc/base.c                   |   16 +-
 fs/proc/proc_sysctl.c            |    4 -
 fs/quota.c                       |    4 -
 fs/smbfs/dir.c                   |    4 -
 fs/smbfs/inode.c                 |    2 
 fs/smbfs/proc.c                  |    2 
 include/linux/init_task.h        |   23 +++
 include/linux/sched.h            |   78 +++++++++---
 include/net/scm.h                |    4 -
 ipc/mqueue.c                     |    4 -
 ipc/msg.c                        |    4 -
 ipc/sem.c                        |    4 -
 ipc/shm.c                        |   16 +-
 ipc/util.c                       |    7 +
 kernel/acct.c                    |    8 +
 kernel/auditsc.c                 |   40 +++---
 kernel/cgroup.c                  |    5 -
 kernel/exit.c                    |   12 +-
 kernel/fork.c                    |   23 ++-
 kernel/futex.c                   |    8 +
 kernel/futex_compat.c            |    5 -
 kernel/ptrace.c                  |   14 +-
 kernel/sched.c                   |    9 +
 kernel/signal.c                  |   26 ++--
 kernel/sys.c                     |  251 ++++++++++++++++++++------------------
 kernel/sysctl.c                  |    2 
 kernel/timer.c                   |    8 +
 kernel/uid16.c                   |   28 ++--
 kernel/user.c                    |    4 -
 kernel/user_namespace.c          |    2 
 mm/oom_kill.c                    |    6 -
 net/core/scm.c                   |   10 +-
 net/sunrpc/auth.c                |    4 -
 net/unix/af_unix.c               |   12 +-
 security/dummy.c                 |   40 ++++--
 security/keys/key.c              |    2 
 security/keys/keyctl.c           |   25 ++--
 security/keys/permission.c       |   11 +-
 security/keys/process_keys.c     |   76 ++++++------
 security/keys/request_key.c      |   17 +--
 security/keys/request_key_auth.c |   14 +-
 security/selinux/exports.c       |    4 -
 security/selinux/hooks.c         |  111 ++++++++---------
 security/selinux/selinuxfs.c     |    2 
 71 files changed, 635 insertions(+), 528 deletions(-)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 56e2304..36caefb 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -928,7 +928,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 	int err;
 	struct loop_func_table *xfer;
 
-	if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid &&
+	if (lo->lo_encrypt_key_size &&
+	    lo->lo_key_owner != current->act_as->uid &&
 	    !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (lo->lo_state != Lo_bound)
@@ -979,7 +980,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 	if (info->lo_encrypt_key_size) {
 		memcpy(lo->lo_encrypt_key, info->lo_encrypt_key,
 		       info->lo_encrypt_key_size);
-		lo->lo_key_owner = current->uid;
+		lo->lo_key_owner = current->act_as->uid;
 	}	
 
 	return 0;
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 7791e98..b07d2d2 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -689,7 +689,7 @@ static int agp_open(struct inode *inode, struct file *file)
 	set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
 	priv->my_pid = current->pid;
 
-	if ((current->uid == 0) || (current->suid == 0)) {
+	if ((current->act_as->uid == 0) || (current->act_as->suid == 0)) {
 		/* Root priv, can be controller */
 		set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);
 	}
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 3992f73..1f8d0a7 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -243,7 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 	memset(priv, 0, sizeof(*priv));
 	filp->private_data = priv;
 	priv->filp = filp;
-	priv->uid = current->euid;
+	priv->uid = current->act_as->euid;
 	priv->pid = task_pid_nr(current);
 	priv->minor = minor;
 	priv->head = drm_heads[minor];
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
index d222012..625c12b 100644
--- a/drivers/char/tty_audit.c
+++ b/drivers/char/tty_audit.c
@@ -86,7 +86,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
 		char name[sizeof(tsk->comm)];
 
 		audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
-				 "minor=%d comm=", tsk->pid, tsk->uid,
+				 "minor=%d comm=", tsk->pid, tsk->sec->uid,
 				 loginuid, buf->major, buf->minor);
 		get_task_comm(name, tsk);
 		audit_log_untrustedstring(ab, name);
diff --git a/fs/affs/super.c b/fs/affs/super.c
index b53e5d0..ed79ab3 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -159,8 +159,8 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
 
 	/* Fill in defaults */
 
-	*uid        = current->uid;
-	*gid        = current->gid;
+	*uid        = current->sec->uid;
+	*gid        = current->sec->gid;
 	*reserved   = 2;
 	*root       = -1;
 	*blocksize  = -1;
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index 45f5992..ac3bd58 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -78,8 +78,8 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
 	substring_t args[MAX_OPT_ARGS];
 	int option;
 
-	*uid = current->uid;
-	*gid = current->gid;
+	*uid = current->sec->uid;
+	*gid = current->sec->gid;
 	*pgrp = task_pgrp_nr(current);
 
 	*minproto = *maxproto = AUTOFS_PROTO_VERSION;
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 7f05d6c..fac6121 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -224,8 +224,8 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
 	substring_t args[MAX_OPT_ARGS];
 	int option;
 
-	*uid = current->uid;
-	*gid = current->gid;
+	*uid = current->sec->uid;
+	*gid = current->sec->gid;
 	*pgrp = task_pgrp_nr(current);
 
 	*minproto = AUTOFS_MIN_PROTO_VERSION;
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 1fe28e4..f41f5b7 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -294,8 +294,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 		wq->len = len;
 		wq->dev = autofs4_get_dev(sbi);
 		wq->ino = autofs4_get_ino(sbi);
-		wq->uid = current->uid;
-		wq->gid = current->gid;
+		wq->uid = current->sec->uid;
+		wq->gid = current->sec->gid;
 		wq->pid = current->pid;
 		wq->tgid = current->tgid;
 		wq->status = -EINTR; /* Status return if interrupted */
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index ba8de7c..d50db36 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -200,10 +200,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 	NEW_AUX_ENT(AT_BASE, interp_load_addr);
 	NEW_AUX_ENT(AT_FLAGS, 0);
 	NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
-	NEW_AUX_ENT(AT_UID, tsk->uid);
-	NEW_AUX_ENT(AT_EUID, tsk->euid);
-	NEW_AUX_ENT(AT_GID, tsk->gid);
-	NEW_AUX_ENT(AT_EGID, tsk->egid);
+	NEW_AUX_ENT(AT_UID, tsk->sec->uid);
+	NEW_AUX_ENT(AT_EUID, tsk->sec->euid);
+	NEW_AUX_ENT(AT_GID, tsk->sec->gid);
+	NEW_AUX_ENT(AT_EGID, tsk->sec->egid);
  	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
 	if (k_platform) {
 		NEW_AUX_ENT(AT_PLATFORM,
@@ -1440,8 +1440,8 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
 	psinfo->pr_zomb = psinfo->pr_sname == 'Z';
 	psinfo->pr_nice = task_nice(p);
 	psinfo->pr_flag = p->flags;
-	SET_UID(psinfo->pr_uid, p->uid);
-	SET_GID(psinfo->pr_gid, p->gid);
+	SET_UID(psinfo->pr_uid, p->sec->uid);
+	SET_GID(psinfo->pr_gid, p->sec->gid);
 	strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
 	
 	return 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index fd9147c..77b3e30 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -818,8 +818,9 @@ cifs_parse_mount_options(char *options, const char *devname,
 	/* null target name indicates to use *SMBSERVR default called name
 	   if we end up sending RFC1001 session initialize */
 	vol->target_rfc1001_name[0] = 0;
-	vol->linux_uid = current->uid;	/* current->euid instead? */
-	vol->linux_gid = current->gid;
+	vol->linux_uid = current->sec->uid;  /* use current->act_as->euid
+					      * instead? */
+	vol->linux_gid = current->sec->gid;
 	vol->dir_mode = S_IRWXUGO;
 	/* 2767 perms indicate mandatory locking support */
 	vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index d24fe68..bf61a78 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -65,7 +65,7 @@ int cifs_ioctl (struct inode *inode, struct file *filep,
 	switch (command) {
 		case CIFS_IOC_CHECKUMOUNT:
 			cFYI(1, ("User unmount attempted"));
-			if (cifs_sb->mnt_uid == current->uid)
+			if (cifs_sb->mnt_uid == current->sec->uid)
 				rc = 0;
 			else {
 				rc = -EACCES;
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index a96d341..8f78205 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -264,26 +264,27 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
 	}
 	msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];
 	mutex_lock(&msg_ctx->mux);
-	if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) {
+	if (ecryptfs_find_daemon_id(msg_ctx->task->sec->euid, &id)) {
 		rc = -EBADMSG;
 		ecryptfs_printk(KERN_WARNING, "User [%d] received a "
 				"message response from process [%d] but does "
 				"not have a registered daemon\n",
-				msg_ctx->task->euid, pid);
+				msg_ctx->task->sec->euid, pid);
 		goto wake_up;
 	}
-	if (msg_ctx->task->euid != uid) {
+	if (msg_ctx->task->sec->euid != uid) {
 		rc = -EBADMSG;
 		ecryptfs_printk(KERN_WARNING, "Received message from user "
 				"[%d]; expected message from user [%d]\n",
-				uid, msg_ctx->task->euid);
+				uid, msg_ctx->task->sec->euid);
 		goto unlock;
 	}
 	if (id->pid != pid) {
 		rc = -EBADMSG;
 		ecryptfs_printk(KERN_ERR, "User [%d] received a "
 				"message response from an unrecognized "
-				"process [%d]\n", msg_ctx->task->euid, pid);
+				"process [%d]\n",
+				msg_ctx->task->sec->euid, pid);
 		goto unlock;
 	}
 	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
@@ -331,11 +332,11 @@ int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
 	int rc;
 
 	mutex_lock(&ecryptfs_daemon_id_hash_mux);
-	if (ecryptfs_find_daemon_id(current->euid, &id)) {
+	if (ecryptfs_find_daemon_id(current->act_as->euid, &id)) {
 		mutex_unlock(&ecryptfs_daemon_id_hash_mux);
 		rc = -ENOTCONN;
 		ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon "
-				"registered\n", current->euid);
+				"registered\n", current->sec->euid);
 		goto out;
 	}
 	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
diff --git a/fs/exec.c b/fs/exec.c
index a09ce1b..da01655 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1000,7 +1000,8 @@ int flush_old_exec(struct linux_binprm * bprm)
 
 	current->sas_ss_sp = current->sas_ss_size = 0;
 
-	if (current->euid == current->uid && current->egid == current->gid)
+	if (current->sec->euid == current->sec->uid &&
+	    current->sec->egid == current->sec->gid)
 		set_dumpable(current->mm, 1);
 	else
 		set_dumpable(current->mm, suid_dumpable);
@@ -1027,7 +1028,8 @@ int flush_old_exec(struct linux_binprm * bprm)
 	 */
 	current->mm->task_size = TASK_SIZE;
 
-	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) {
+	if (bprm->e_uid != current->sec->euid ||
+	    bprm->e_gid != current->sec->egid) {
 		suid_keys(current);
 		set_dumpable(current->mm, suid_dumpable);
 		current->pdeath_signal = 0;
@@ -1069,8 +1071,8 @@ int prepare_binprm(struct linux_binprm *bprm)
 	if (bprm->file->f_op == NULL)
 		return -EACCES;
 
-	bprm->e_uid = current->euid;
-	bprm->e_gid = current->egid;
+	bprm->e_uid = current->sec->euid;
+	bprm->e_gid = current->sec->egid;
 
 	if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
 		/* Set-uid? */
@@ -1123,7 +1125,7 @@ void compute_creds(struct linux_binprm *bprm)
 {
 	int unsafe;
 
-	if (bprm->e_uid != current->uid) {
+	if (bprm->e_uid != current->sec->uid) {
 		suid_keys(current);
 		current->pdeath_signal = 0;
 	}
@@ -1441,7 +1443,7 @@ static int format_corename(char *corename, const char *pattern, long signr)
 			/* uid */
 			case 'u':
 				rc = snprintf(out_ptr, out_end - out_ptr,
-					      "%d", current->uid);
+					      "%d", current->sec->uid);
 				if (rc > out_end - out_ptr)
 					goto out;
 				out_ptr += rc;
@@ -1449,7 +1451,7 @@ static int format_corename(char *corename, const char *pattern, long signr)
 			/* gid */
 			case 'g':
 				rc = snprintf(out_ptr, out_end - out_ptr,
-					      "%d", current->gid);
+					      "%d", current->sec->gid);
 				if (rc > out_end - out_ptr)
 					goto out;
 				out_ptr += rc;
@@ -1707,7 +1709,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	 */
 	if (get_dumpable(mm) == 2) {	/* Setuid core dump mode */
 		flag = O_EXCL;		/* Stop rewrite attacks */
-		current->fsuid = 0;	/* Dump root private */
+		current->act_as->fsuid = 0;	/* Dump root private */
 	}
 
 	retval = coredump_wait(exit_code);
@@ -1803,7 +1805,7 @@ fail_unlock:
 	if (helper_argv)
 		argv_free(helper_argv);
 
-	current->fsuid = fsuid;
+	current->act_as->fsuid = fsuid;
 	complete_all(&mm->core_done);
 fail:
 	return retval;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 920a576..f49733f 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -934,8 +934,8 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
 
 	opts->isvfat = is_vfat;
 
-	opts->fs_uid = current->uid;
-	opts->fs_gid = current->gid;
+	opts->fs_uid = current->sec->uid;
+	opts->fs_gid = current->sec->gid;
 	opts->fs_fmask = opts->fs_dmask = current->fs->umask;
 	opts->codepage = fat_default_codepage;
 	opts->iocharset = fat_default_iocharset;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 8685263..35d8f74 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -276,7 +276,8 @@ int __f_setown(struct file *filp, struct pid *pid, enum pid_type type,
 	if (err)
 		return err;
 
-	f_modown(filp, pid, type, current->uid, current->euid, force);
+	f_modown(filp, pid, type, current->sec->uid, current->act_as->euid,
+		 force);
 	return 0;
 }
 EXPORT_SYMBOL(__f_setown);
@@ -461,8 +462,8 @@ static inline int sigio_perm(struct task_struct *p,
                              struct fown_struct *fown, int sig)
 {
 	return (((fown->euid == 0) ||
-		 (fown->euid == p->suid) || (fown->euid == p->uid) ||
-		 (fown->uid == p->suid) || (fown->uid == p->uid)) &&
+		 (fown->euid == p->sec->suid) || (fown->euid == p->sec->uid) ||
+		 (fown->uid == p->sec->suid) || (fown->uid == p->sec->uid)) &&
 		!security_file_send_sigiotask(p, fown, sig));
 }
 
diff --git a/fs/file_table.c b/fs/file_table.c
index 664e3f2..e559b50 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -114,8 +114,8 @@ struct file *get_empty_filp(void)
 	INIT_LIST_HEAD(&f->f_u.fu_list);
 	atomic_set(&f->f_count, 1);
 	rwlock_init(&f->f_owner.lock);
-	f->f_uid = tsk->fsuid;
-	f->f_gid = tsk->fsgid;
+	f->f_uid = tsk->act_as->fsuid;
+	f->f_gid = tsk->act_as->fsgid;
 	eventpoll_init_file(f);
 	/* f->f_version: 0 */
 	return f;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 80d2f52..0c78b97 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -830,12 +830,12 @@ int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
 	if (fc->flags & FUSE_ALLOW_OTHER)
 		return 1;
 
-	if (task->euid == fc->user_id &&
-	    task->suid == fc->user_id &&
-	    task->uid == fc->user_id &&
-	    task->egid == fc->group_id &&
-	    task->sgid == fc->group_id &&
-	    task->gid == fc->group_id)
+	if (task->sec->euid == fc->user_id &&
+	    task->sec->suid == fc->user_id &&
+	    task->sec->uid == fc->user_id &&
+	    task->sec->egid == fc->group_id &&
+	    task->sec->sgid == fc->group_id &&
+	    task->sec->gid == fc->group_id)
 		return 1;
 
 	return 0;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 16cbd90..54a1d32 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -210,8 +210,8 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
 	int tmp, token;
 
 	/* initialize the sb with defaults */
-	hsb->s_uid = current->uid;
-	hsb->s_gid = current->gid;
+	hsb->s_uid = current->sec->uid;
+	hsb->s_gid = current->sec->gid;
 	hsb->s_file_umask = 0133;
 	hsb->s_dir_umask = 0022;
 	hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f);	/* == '????' */
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index dc64fac..fa5e015 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -49,8 +49,8 @@ void hfsplus_fill_defaults(struct hfsplus_sb_info *opts)
 	opts->creator = HFSPLUS_DEF_CR_TYPE;
 	opts->type = HFSPLUS_DEF_CR_TYPE;
 	opts->umask = current->fs->umask;
-	opts->uid = current->uid;
-	opts->gid = current->gid;
+	opts->uid = current->sec->uid;
+	opts->gid = current->sec->gid;
 	opts->part = -1;
 	opts->session = -1;
 }
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 00971d9..cf4c6b5 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -464,8 +464,8 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
 	init_MUTEX(&sbi->hpfs_creation_de);
 
-	uid = current->uid;
-	gid = current->gid;
+	uid = current->sec->uid;
+	gid = current->sec->gid;
 	umask = current->fs->umask;
 	lowercase = 0;
 	conv = CONV_BINARY;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 39ad919..1e4d411 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -921,7 +921,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
 	if (!can_do_hugetlb_shm())
 		return ERR_PTR(-EPERM);
 
-	if (!user_shm_lock(size, current->user))
+	if (!user_shm_lock(size, current->sec->user))
 		return ERR_PTR(-ENOMEM);
 
 	root = hugetlbfs_vfsmount->mnt_root;
@@ -960,7 +960,7 @@ out_inode:
 out_dentry:
 	dput(dentry);
 out_shm_unlock:
-	user_shm_unlock(size, current->user);
+	user_shm_unlock(size, current->sec->user);
 	return ERR_PTR(error);
 }
 
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 5e00933..6d68f3e 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -558,7 +558,7 @@ asmlinkage long sys_inotify_init(void)
 		goto out_put_fd;
 	}
 
-	user = get_uid(current->user);
+	user = get_uid(current->sec->user);
 	if (unlikely(atomic_read(&user->inotify_devs) >=
 			inotify_max_user_instances)) {
 		ret = -EMFILE;
diff --git a/fs/ioprio.c b/fs/ioprio.c
index e4e01bc..5392a60 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -32,8 +32,8 @@ static int set_task_ioprio(struct task_struct *task, int ioprio)
 	int err;
 	struct io_context *ioc;
 
-	if (task->uid != current->euid &&
-	    task->uid != current->uid && !capable(CAP_SYS_NICE))
+	if (task->sec->uid != current->act_as->euid &&
+	    task->sec->uid != current->act_as->uid && !capable(CAP_SYS_NICE))
 		return -EPERM;
 
 	err = security_task_setioprio(task, ioprio);
@@ -115,7 +115,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
 			break;
 		case IOPRIO_WHO_USER:
 			if (!who)
-				user = current->user;
+				user = current->sec->user;
 			else
 				user = find_user(who);
 
@@ -123,7 +123,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
 				break;
 
 			do_each_thread(g, p) {
-				if (p->uid != who)
+				if (p->sec->uid != who)
 					continue;
 				ret = set_task_ioprio(p, ioprio);
 				if (ret)
@@ -206,7 +206,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
 			break;
 		case IOPRIO_WHO_USER:
 			if (!who)
-				user = current->user;
+				user = current->sec->user;
 			else
 				user = find_user(who);
 
@@ -214,7 +214,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
 				break;
 
 			do_each_thread(g, p) {
-				if (p->uid != user->uid)
+				if (p->sec->uid != user->uid)
 					continue;
 				tmpio = get_task_ioprio(p);
 				if (tmpio < 0)
diff --git a/fs/namei.c b/fs/namei.c
index 8963e91..428c195 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1433,11 +1433,13 @@ int fastcall __user_walk(const char __user *name, unsigned flags, struct nameida
  */
 static inline int check_sticky(struct inode *dir, struct inode *inode)
 {
+	uid_t fsuid = current->act_as->fsuid;
+
 	if (!(dir->i_mode & S_ISVTX))
 		return 0;
-	if (inode->i_uid == current_fsuid())
+	if (inode->i_uid == fsuid)
 		return 0;
-	if (dir->i_uid == current_fsuid())
+	if (dir->i_uid == fsuid)
 		return 0;
 	return !capable(CAP_FOWNER);
 }
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index c67b4bd..5f1adaf 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -40,7 +40,7 @@ ncp_get_fs_info(struct ncp_server * server, struct file *file,
 	struct ncp_fs_info info;
 
 	if ((file_permission(file, MAY_WRITE) != 0)
-	    && (current->uid != server->m.mounted_uid)) {
+	    && (current->act_as->uid != server->m.mounted_uid)) {
 		return -EACCES;
 	}
 	if (copy_from_user(&info, arg, sizeof(info)))
@@ -70,7 +70,7 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
 	struct ncp_fs_info_v2 info2;
 
 	if ((file_permission(file, MAY_WRITE) != 0)
-	    && (current->uid != server->m.mounted_uid)) {
+	    && (current->act_as->uid != server->m.mounted_uid)) {
 		return -EACCES;
 	}
 	if (copy_from_user(&info2, arg, sizeof(info2)))
@@ -141,7 +141,7 @@ ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
 	struct compat_ncp_fs_info_v2 info2;
 
 	if ((file_permission(file, MAY_WRITE) != 0)
-	    && (current->uid != server->m.mounted_uid)) {
+	    && (current->act_as->uid != server->m.mounted_uid)) {
 		return -EACCES;
 	}
 	if (copy_from_user(&info2, arg, sizeof(info2)))
@@ -276,7 +276,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
 #endif
 	case NCP_IOC_NCPREQUEST:
 		if ((file_permission(filp, MAY_WRITE) != 0)
-		    && (current->uid != server->m.mounted_uid)) {
+		    && (current->act_as->uid != server->m.mounted_uid)) {
 			return -EACCES;
 		}
 #ifdef CONFIG_COMPAT
@@ -356,7 +356,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
 	case NCP_IOC_GETMOUNTUID32:
 	case NCP_IOC_GETMOUNTUID64:
 		if ((file_permission(filp, MAY_READ) != 0)
-			&& (current->uid != server->m.mounted_uid)) {
+			&& (current->act_as->uid != server->m.mounted_uid)) {
 			return -EACCES;
 		}
 		if (cmd == NCP_IOC_GETMOUNTUID16) {
@@ -380,7 +380,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
 			struct ncp_setroot_ioctl sr;
 
 			if ((file_permission(filp, MAY_READ) != 0)
-			    && (current->uid != server->m.mounted_uid))
+			    && (current->act_as->uid != server->m.mounted_uid))
 			{
 				return -EACCES;
 			}
@@ -455,7 +455,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
 #ifdef CONFIG_NCPFS_PACKET_SIGNING	
 	case NCP_IOC_SIGN_INIT:
 		if ((file_permission(filp, MAY_WRITE) != 0)
-		    && (current->uid != server->m.mounted_uid))
+		    && (current->act_as->uid != server->m.mounted_uid))
 		{
 			return -EACCES;
 		}
@@ -478,7 +478,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
 		
         case NCP_IOC_SIGN_WANTED:
 		if ((file_permission(filp, MAY_READ) != 0)
-		    && (current->uid != server->m.mounted_uid))
+		    && (current->act_as->uid != server->m.mounted_uid))
 		{
 			return -EACCES;
 		}
@@ -491,7 +491,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
 			int newstate;
 
 			if ((file_permission(filp, MAY_WRITE) != 0)
-			    && (current->uid != server->m.mounted_uid))
+			    && (current->act_as->uid != server->m.mounted_uid))
 			{
 				return -EACCES;
 			}
@@ -512,7 +512,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
 	case NCP_IOC_LOCKUNLOCK:
 		if ((file_permission(filp, MAY_WRITE) != 0)
-		    && (current->uid != server->m.mounted_uid))
+		    && (current->act_as->uid != server->m.mounted_uid))
 		{
 			return -EACCES;
 		}
@@ -585,7 +585,7 @@ outrel:
 
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_GETOBJECTNAME_32:
-		if (current->uid != server->m.mounted_uid) {
+		if (current->act_as->uid != server->m.mounted_uid) {
 			return -EACCES;
 		}
 		{
@@ -610,7 +610,7 @@ outrel:
 		}
 #endif
 	case NCP_IOC_GETOBJECTNAME:
-		if (current->uid != server->m.mounted_uid) {
+		if (current->act_as->uid != server->m.mounted_uid) {
 			return -EACCES;
 		}
 		{
@@ -637,7 +637,7 @@ outrel:
 	case NCP_IOC_SETOBJECTNAME_32:
 #endif
 	case NCP_IOC_SETOBJECTNAME:
-		if (current->uid != server->m.mounted_uid) {
+		if (current->act_as->uid != server->m.mounted_uid) {
 			return -EACCES;
 		}
 		{
@@ -695,7 +695,7 @@ outrel:
 	case NCP_IOC_GETPRIVATEDATA_32:
 #endif
 	case NCP_IOC_GETPRIVATEDATA:
-		if (current->uid != server->m.mounted_uid) {
+		if (current->act_as->uid != server->m.mounted_uid) {
 			return -EACCES;
 		}
 		{
@@ -740,7 +740,7 @@ outrel:
 	case NCP_IOC_SETPRIVATEDATA_32:
 #endif
 	case NCP_IOC_SETPRIVATEDATA:
-		if (current->uid != server->m.mounted_uid) {
+		if (current->act_as->uid != server->m.mounted_uid) {
 			return -EACCES;
 		}
 		{
@@ -795,7 +795,7 @@ outrel:
 
 	case NCP_IOC_SETDENTRYTTL:
 		if ((file_permission(filp, MAY_WRITE) != 0) &&
-				 (current->uid != server->m.mounted_uid))
+		    current->act_as->uid != server->m.mounted_uid)
 			return -EACCES;
 		{
 			u_int32_t user;
diff --git a/fs/open.c b/fs/open.c
index 4932b4d..6d7a29c 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -428,12 +428,12 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
 		return -EINVAL;
 
-	old_fsuid = current->fsuid;
-	old_fsgid = current->fsgid;
-	old_cap = current->cap_effective;
+	old_fsuid = current->act_as->fsuid;
+	old_fsgid = current->act_as->fsgid;
+	old_cap = current->act_as->cap_effective;
 
-	current->fsuid = current->uid;
-	current->fsgid = current->gid;
+	current->act_as->fsuid = current->act_as->uid;
+	current->act_as->fsgid = current->act_as->gid;
 
 	/*
 	 * Clear the capabilities if we switch to a non-root user
@@ -443,10 +443,10 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 	 * value below.  We should hold task_capabilities_lock,
 	 * but we cannot because user_path_walk can sleep.
 	 */
-	if (current->uid)
-		cap_clear(current->cap_effective);
+	if (current->act_as->uid)
+		cap_clear(current->act_as->cap_effective);
 	else
-		current->cap_effective = current->cap_permitted;
+		current->act_as->cap_effective = current->act_as->cap_permitted;
 
 	res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
 	if (res)
@@ -464,9 +464,9 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 out_path_release:
 	path_release(&nd);
 out:
-	current->fsuid = old_fsuid;
-	current->fsgid = old_fsgid;
-	current->cap_effective = old_cap;
+	current->act_as->fsuid = old_fsuid;
+	current->act_as->fsgid = old_fsgid;
+	current->act_as->cap_effective = old_cap;
 
 	return res;
 }
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 65c62e1..94875ce 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -182,8 +182,8 @@ static inline char *task_state(struct task_struct *p, char *buffer)
 		task_tgid_nr_ns(p, ns),
 		task_pid_nr_ns(p, ns),
 		ppid, tpid,
-		p->uid, p->euid, p->suid, p->fsuid,
-		p->gid, p->egid, p->sgid, p->fsgid);
+		p->sec->uid, p->sec->euid, p->sec->suid, p->sec->fsuid,
+		p->sec->gid, p->sec->egid, p->sec->sgid, p->sec->fsgid);
 
 	task_lock(p);
 	if (p->files)
@@ -194,7 +194,7 @@ static inline char *task_state(struct task_struct *p, char *buffer)
 		fdt ? fdt->max_fds : 0);
 	rcu_read_unlock();
 
-	group_info = p->group_info;
+	group_info = p->sec->group_info;
 	get_group_info(group_info);
 	task_unlock(p);
 
@@ -267,7 +267,7 @@ static inline char *task_sig(struct task_struct *p, char *buffer)
 		blocked = p->blocked;
 		collect_sigign_sigcatch(p, &ignored, &caught);
 		num_threads = atomic_read(&p->signal->count);
-		qsize = atomic_read(&p->user->sigpending);
+		qsize = atomic_read(&p->sec->user->sigpending);
 		qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
 		unlock_task_sighand(p, &flags);
 	}
@@ -291,9 +291,9 @@ static inline char *task_cap(struct task_struct *p, char *buffer)
     return buffer + sprintf(buffer, "CapInh:\t%016x\n"
 			    "CapPrm:\t%016x\n"
 			    "CapEff:\t%016x\n",
-			    cap_t(p->cap_inheritable),
-			    cap_t(p->cap_permitted),
-			    cap_t(p->cap_effective));
+			    cap_t(p->sec->cap_inheritable),
+			    cap_t(p->sec->cap_permitted),
+			    cap_t(p->sec->cap_effective));
 }
 
 static inline char *task_context_switch_counts(struct task_struct *p,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 02a63ac..4e4482b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1181,8 +1181,8 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
 	inode->i_uid = 0;
 	inode->i_gid = 0;
 	if (task_dumpable(task)) {
-		inode->i_uid = task->euid;
-		inode->i_gid = task->egid;
+		inode->i_uid = task->sec->euid;
+		inode->i_gid = task->sec->egid;
 	}
 	security_task_to_inode(task, inode);
 
@@ -1207,8 +1207,8 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
 	if (task) {
 		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
 		    task_dumpable(task)) {
-			stat->uid = task->euid;
-			stat->gid = task->egid;
+			stat->uid = task->sec->euid;
+			stat->gid = task->sec->egid;
 		}
 	}
 	rcu_read_unlock();
@@ -1239,8 +1239,8 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
 	if (task) {
 		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
 		    task_dumpable(task)) {
-			inode->i_uid = task->euid;
-			inode->i_gid = task->egid;
+			inode->i_uid = task->sec->euid;
+			inode->i_gid = task->sec->egid;
 		} else {
 			inode->i_uid = 0;
 			inode->i_gid = 0;
@@ -1413,8 +1413,8 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
 				rcu_read_unlock();
 				put_files_struct(files);
 				if (task_dumpable(task)) {
-					inode->i_uid = task->euid;
-					inode->i_gid = task->egid;
+					inode->i_uid = task->sec->euid;
+					inode->i_gid = task->sec->egid;
 				} else {
 					inode->i_uid = 0;
 					inode->i_gid = 0;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 4e57fcf..e4ddfdb 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -393,9 +393,9 @@ static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *
 	error = -EACCES;
 	mode = inode->i_mode;
 
-	if (current->euid == 0)
+	if (current->act_as->euid == 0)
 		mode >>= 6;
-	else if (in_group_p(0))
+	else if (in_egroup_p(0))
 		mode >>= 3;
 
 	if ((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)
diff --git a/fs/quota.c b/fs/quota.c
index 99b24b5..ab4f1d9 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -80,7 +80,7 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid
 
 	/* Check privileges */
 	if (cmd == Q_GETQUOTA) {
-		if (((type == USRQUOTA && current->euid != id) ||
+		if (((type == USRQUOTA && current->act_as->euid != id) ||
 		     (type == GRPQUOTA && !in_egroup_p(id))) &&
 		    !capable(CAP_SYS_ADMIN))
 			return -EPERM;
@@ -131,7 +131,7 @@ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t i
 
 	/* Check privileges */
 	if (cmd == Q_XGETQUOTA) {
-		if (((type == XQM_USRQUOTA && current->euid != id) ||
+		if (((type == XQM_USRQUOTA && current->act_as->euid != id) ||
 		     (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
 		     !capable(CAP_SYS_ADMIN))
 			return -EPERM;
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 48da4fa..53e03a3 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -667,8 +667,8 @@ smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 
 	attr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID;
 	attr.ia_mode = mode;
-	attr.ia_uid = current->euid;
-	attr.ia_gid = current->egid;
+	attr.ia_uid = current->act_as->euid;
+	attr.ia_gid = current->act_as->egid;
 
 	if (!new_valid_dev(dev))
 		return -EINVAL;
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 9416ead..95a2455 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -579,7 +579,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
 		if (parse_options(mnt, raw_data))
 			goto out_bad_option;
 	}
-	mnt->mounted_uid = current->uid;
+	mnt->mounted_uid = current->act_as->uid;
 	smb_setcodepage(server, &mnt->codepage);
 
 	/*
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index d517a27..a55d9cd 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -865,7 +865,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
 		goto out;
 
 	error = -EACCES;
-	if (current->uid != server->mnt->mounted_uid && 
+	if (current->act_as->uid != server->mnt->mounted_uid &&
 	    !capable(CAP_SYS_ADMIN))
 		goto out;
 
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index cae35b6..6fa8413 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -114,6 +114,20 @@ extern struct group_info init_groups;
 	.pid = &init_struct_pid,				\
 }
 
+extern struct task_security init_task_security;
+
+#define INIT_TASK_SECURITY(p)					\
+{								\
+	.usage			= ATOMIC_INIT(3),		\
+	.keep_capabilities	= 0,				\
+	.cap_inheritable	= CAP_INIT_INH_SET,		\
+	.cap_permitted		= CAP_FULL_SET,			\
+	.cap_effective		= CAP_INIT_EFF_SET,		\
+	.user			= INIT_USER,			\
+	.group_info		= &init_groups,			\
+	.lock			= __SPIN_LOCK_UNLOCKED(p.lock),	\
+}
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -143,12 +157,9 @@ extern struct group_info init_groups;
 	.children	= LIST_HEAD_INIT(tsk.children),			\
 	.sibling	= LIST_HEAD_INIT(tsk.sibling),			\
 	.group_leader	= &tsk,						\
-	.group_info	= &init_groups,					\
-	.cap_effective	= CAP_INIT_EFF_SET,				\
-	.cap_inheritable = CAP_INIT_INH_SET,				\
-	.cap_permitted	= CAP_FULL_SET,					\
-	.keep_capabilities = 0,						\
-	.user		= INIT_USER,					\
+	.__temp_sec	= INIT_TASK_SECURITY(tsk.__temp_sec),		\
+	.sec		= &tsk.__temp_sec,				\
+	.act_as		= &tsk.__temp_sec,				\
 	.comm		= "swapper",					\
 	.thread		= INIT_THREAD,					\
 	.fs		= &init_fs,					\
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 88a5626..bcd785a 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -570,6 +570,63 @@ extern struct user_struct *find_user(uid_t);
 extern struct user_struct root_user;
 #define INIT_USER (&root_user)
 
+
+/*
+ * The security context of a task
+ *
+ * The parts of the context break down into two categories:
+ *
+ *  (1) The objective context of a task.  These parts are used when some other
+ *	task is attempting to affect this one.
+ *
+ *  (2) The subjective context.  These details are used when the task is acting
+ *	upon another object, be that a file, a task, a key or whatever.
+ *
+ * Note that some members of this structure belong to both categories - the
+ * LSM security pointer for instance.
+ *
+ * A task has two security pointers.  task->sec points to the objective context
+ * that defines that task's actual details.  The objective part of this context
+ * is used whenever that task is acted upon.
+ *
+ * task->act_as points to the subjective context that defines the details of
+ * how that task is going to act upon another object.  This may be overridden
+ * temporarily to point to another security context, but normally points to the
+ * same context as task->sec.
+ */
+struct task_security {
+	atomic_t	usage;
+	uid_t		uid;		/* real UID of the task */
+	gid_t		gid;		/* real GID of the task */
+	uid_t		suid;		/* saved UID of the task */
+	gid_t		sgid;		/* saved GID of the task */
+	uid_t		euid;		/* effective UID of the task */
+	gid_t		egid;		/* effective GID of the task */
+	uid_t		fsuid;		/* UID for VFS ops */
+	gid_t		fsgid;		/* GID for VFS ops */
+	unsigned	keep_capabilities:1;
+	kernel_cap_t	cap_inheritable; /* caps our children can inherit */
+	kernel_cap_t	cap_permitted;	/* caps we're permitted */
+	kernel_cap_t	cap_effective;	/* caps we can actually use */
+#ifdef CONFIG_KEYS
+	unsigned char	jit_keyring;	/* default keyring to attach requested
+					 * keys to */
+	struct key	*thread_keyring; /* keyring private to this thread */
+	struct key	*request_key_auth; /* assumed request_key authority */
+#endif
+#ifdef CONFIG_SECURITY
+	void		*security;	/* subjective LSM security */
+#endif
+	struct user_struct *user;	/* real user ID subscription */
+	struct group_info *group_info;	/* supplementary groups for euid/fsgid */
+	spinlock_t	lock;		/* lock for pointer changes */
+};
+
+#define current_fsuid() (current->act_as->fsuid)
+#define current_fsgid() (current->act_as->fsgid)
+#define current_cap()	(current->act_as->cap_effective)
+
+
 struct backing_dev_info;
 struct reclaim_state;
 
@@ -1025,17 +1082,10 @@ struct task_struct {
 	struct list_head cpu_timers[3];
 
 /* process credentials */
-	uid_t uid,euid,suid,fsuid;
-	gid_t gid,egid,sgid,fsgid;
-	struct group_info *group_info;
-	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
-	unsigned keep_capabilities:1;
-	struct user_struct *user;
-#ifdef CONFIG_KEYS
-	struct key *request_key_auth;	/* assumed request_key authority */
-	struct key *thread_keyring;	/* keyring private to this thread */
-	unsigned char jit_keyring;	/* default keyring to attach requested keys to */
-#endif
+	struct task_security __temp_sec __deprecated; /* temporary security to be removed */
+	struct task_security *sec;	/* actual/objective task security */
+	struct task_security *act_as;	/* effective/subjective task security */
+
 	char comm[TASK_COMM_LEN]; /* executable name excluding path
 				     - access with [gs]et_task_comm (which lock
 				       it with task_lock())
@@ -1067,9 +1117,6 @@ struct task_struct {
 	int (*notifier)(void *priv);
 	void *notifier_data;
 	sigset_t *notifier_mask;
-#ifdef CONFIG_SECURITY
-	void *security;
-#endif
 	struct audit_context *audit_context;
 	seccomp_t seccomp;
 
@@ -1180,9 +1227,6 @@ struct task_struct {
 	struct prop_local_single dirties;
 };
 
-#define current_fsuid() (current->fsuid)
-#define current_fsgid() (current->fsgid)
-
 /*
  * Priority of a process goes from 0..MAX_PRIO-1, valid RT
  * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
diff --git a/include/net/scm.h b/include/net/scm.h
index 06df126..b133114 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -54,8 +54,8 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
 			       struct scm_cookie *scm)
 {
 	struct task_struct *p = current;
-	scm->creds.uid = p->uid;
-	scm->creds.gid = p->gid;
+	scm->creds.uid = p->sec->uid;
+	scm->creds.gid = p->sec->gid;
 	scm->creds.pid = task_tgid_vnr(p);
 	scm->fp = NULL;
 	scm->seq = 0;
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 590045a..43a3228 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -118,7 +118,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
 		if (S_ISREG(mode)) {
 			struct mqueue_inode_info *info;
 			struct task_struct *p = current;
-			struct user_struct *u = p->user;
+			struct user_struct *u = p->sec->user;
 			unsigned long mq_bytes, mq_msg_tblsz;
 
 			inode->i_fop = &mqueue_file_operations;
@@ -511,7 +511,7 @@ static void __do_notify(struct mqueue_inode_info *info)
 			sig_i.si_code = SI_MESGQ;
 			sig_i.si_value = info->notify.sigev_value;
 			sig_i.si_pid = task_pid_vnr(current);
-			sig_i.si_uid = current->uid;
+			sig_i.si_uid = current->act_as->uid;
 
 			kill_pid_info(info->notify.sigev_signo,
 				      &sig_i, info->notify_owner);
diff --git a/ipc/msg.c b/ipc/msg.c
index fdf3db5..83c7a29 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -551,8 +551,8 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
 	}
 
 	err = -EPERM;
-	if (current->euid != ipcp->cuid &&
-	    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
+	if (current->act_as->euid != ipcp->cuid &&
+	    current->act_as->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
 		/* We _could_ check for CAP_CHOWN above, but we don't */
 		goto out_unlock_up;
 
diff --git a/ipc/sem.c b/ipc/sem.c
index 35952c0..35736f5 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -924,8 +924,8 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
 		if (err)
 			goto out_unlock;
 	}
-	if (current->euid != ipcp->cuid && 
-	    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
+	if (current->act_as->euid != ipcp->cuid &&
+	    current->act_as->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
 	    	err=-EPERM;
 		goto out_unlock;
 	}
diff --git a/ipc/shm.c b/ipc/shm.c
index 3818fae..89e232e 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -417,7 +417,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 	if (shmflg & SHM_HUGETLB) {
 		/* hugetlb_file_setup takes care of mlock user accounting */
 		file = hugetlb_file_setup(name, size);
-		shp->mlock_user = current->user;
+		shp->mlock_user = current->sec->user;
 	} else {
 		int acctflag = VM_ACCOUNT;
 		/*
@@ -770,8 +770,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
 
 		if (!capable(CAP_IPC_LOCK)) {
 			err = -EPERM;
-			if (current->euid != shp->shm_perm.uid &&
-			    current->euid != shp->shm_perm.cuid)
+			if (current->act_as->euid != shp->shm_perm.uid &&
+			    current->act_as->euid != shp->shm_perm.cuid)
 				goto out_unlock;
 			if (cmd == SHM_LOCK &&
 			    !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
@@ -783,7 +783,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
 			goto out_unlock;
 		
 		if(cmd==SHM_LOCK) {
-			struct user_struct * user = current->user;
+			struct user_struct *user = current->act_as->user;
 			if (!is_file_hugepages(shp->shm_file)) {
 				err = shmem_lock(shp->shm_file, 1, user);
 				if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
@@ -822,8 +822,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
 		if (err)
 			goto out_unlock_up;
 
-		if (current->euid != shp->shm_perm.uid &&
-		    current->euid != shp->shm_perm.cuid && 
+		if (current->act_as->euid != shp->shm_perm.uid &&
+		    current->act_as->euid != shp->shm_perm.cuid &&
 		    !capable(CAP_SYS_ADMIN)) {
 			err=-EPERM;
 			goto out_unlock_up;
@@ -862,8 +862,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
 		if (err)
 			goto out_unlock_up;
 		err=-EPERM;
-		if (current->euid != shp->shm_perm.uid &&
-		    current->euid != shp->shm_perm.cuid && 
+		if (current->act_as->euid != shp->shm_perm.uid &&
+		    current->act_as->euid != shp->shm_perm.cuid &&
 		    !capable(CAP_SYS_ADMIN)) {
 			goto out_unlock_up;
 		}
diff --git a/ipc/util.c b/ipc/util.c
index 1aa0ebf..fc22a9c 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -283,8 +283,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 
 	ids->in_use++;
 
-	new->cuid = new->uid = current->euid;
-	new->gid = new->cgid = current->egid;
+	new->cuid = new->uid = current->act_as->euid;
+	new->gid = new->cgid = current->act_as->egid;
 
 	new->seq = ids->seq++;
 	if(ids->seq > ids->seq_max)
@@ -632,7 +632,8 @@ int ipcperms (struct kern_ipc_perm *ipcp, short flag)
 		return err;
 	requested_mode = (flag >> 6) | (flag >> 3) | flag;
 	granted_mode = ipcp->mode;
-	if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
+	if (current->act_as->euid == ipcp->cuid ||
+	    current->act_as->euid == ipcp->uid)
 		granted_mode >>= 6;
 	else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
 		granted_mode >>= 3;
diff --git a/kernel/acct.c b/kernel/acct.c
index cf19547..d66a849 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -470,15 +470,15 @@ static void do_acct_process(struct file *file)
 	do_div(elapsed, AHZ);
 	ac.ac_btime = get_seconds() - elapsed;
 	/* we really need to bite the bullet and change layout */
-	ac.ac_uid = current->uid;
-	ac.ac_gid = current->gid;
+	ac.ac_uid = current->sec->uid;
+	ac.ac_gid = current->sec->gid;
 #if ACCT_VERSION==2
 	ac.ac_ahz = AHZ;
 #endif
 #if ACCT_VERSION==1 || ACCT_VERSION==2
 	/* backward-compatible 16 bit fields */
-	ac.ac_uid16 = current->uid;
-	ac.ac_gid16 = current->gid;
+	ac.ac_uid16 = current->sec->uid;
+	ac.ac_gid16 = current->sec->gid;
 #endif
 #if ACCT_VERSION==3
 	ac.ac_pid = current->tgid;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index bce9ecd..46fe72a 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -394,6 +394,7 @@ static int audit_filter_rules(struct task_struct *tsk,
 			      struct audit_names *name,
 			      enum audit_state *state)
 {
+	struct task_security *sec = tsk->sec;
 	int i, j, need_sid = 1;
 	u32 sid;
 
@@ -413,28 +414,28 @@ static int audit_filter_rules(struct task_struct *tsk,
 			}
 			break;
 		case AUDIT_UID:
-			result = audit_comparator(tsk->uid, f->op, f->val);
+			result = audit_comparator(sec->uid, f->op, f->val);
 			break;
 		case AUDIT_EUID:
-			result = audit_comparator(tsk->euid, f->op, f->val);
+			result = audit_comparator(sec->euid, f->op, f->val);
 			break;
 		case AUDIT_SUID:
-			result = audit_comparator(tsk->suid, f->op, f->val);
+			result = audit_comparator(sec->suid, f->op, f->val);
 			break;
 		case AUDIT_FSUID:
-			result = audit_comparator(tsk->fsuid, f->op, f->val);
+			result = audit_comparator(sec->fsuid, f->op, f->val);
 			break;
 		case AUDIT_GID:
-			result = audit_comparator(tsk->gid, f->op, f->val);
+			result = audit_comparator(sec->gid, f->op, f->val);
 			break;
 		case AUDIT_EGID:
-			result = audit_comparator(tsk->egid, f->op, f->val);
+			result = audit_comparator(sec->egid, f->op, f->val);
 			break;
 		case AUDIT_SGID:
-			result = audit_comparator(tsk->sgid, f->op, f->val);
+			result = audit_comparator(sec->sgid, f->op, f->val);
 			break;
 		case AUDIT_FSGID:
-			result = audit_comparator(tsk->fsgid, f->op, f->val);
+			result = audit_comparator(sec->fsgid, f->op, f->val);
 			break;
 		case AUDIT_PERS:
 			result = audit_comparator(tsk->personality, f->op, f->val);
@@ -997,6 +998,7 @@ static void audit_log_execve_info(struct audit_buffer *ab,
 
 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
 {
+	struct task_security *sec = tsk->sec;
 	int i, call_panic = 0;
 	struct audit_buffer *ab;
 	struct audit_aux_data *aux;
@@ -1006,14 +1008,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 	context->pid = tsk->pid;
 	if (!context->ppid)
 		context->ppid = sys_getppid();
-	context->uid = tsk->uid;
-	context->gid = tsk->gid;
-	context->euid = tsk->euid;
-	context->suid = tsk->suid;
-	context->fsuid = tsk->fsuid;
-	context->egid = tsk->egid;
-	context->sgid = tsk->sgid;
-	context->fsgid = tsk->fsgid;
+	context->uid = sec->uid;
+	context->gid = sec->gid;
+	context->euid = sec->euid;
+	context->suid = sec->suid;
+	context->fsuid = sec->fsuid;
+	context->egid = sec->egid;
+	context->sgid = sec->sgid;
+	context->fsgid = sec->fsgid;
 	context->personality = tsk->personality;
 
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
@@ -1788,7 +1790,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 			if (ab) {
 				audit_log_format(ab, "login pid=%d uid=%u "
 					"old auid=%u new auid=%u",
-					task->pid, task->uid,
+					task->pid, task->sec->uid,
 					context->loginuid, loginuid);
 				audit_log_end(ab);
 			}
@@ -2219,7 +2221,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
 			if (ctx)
 				audit_sig_uid = ctx->loginuid;
 			else
-				audit_sig_uid = tsk->uid;
+				audit_sig_uid = tsk->sec->uid;
 			selinux_get_task_sid(tsk, &audit_sig_sid);
 		}
 		if (!audit_signals || audit_dummy_context())
@@ -2274,7 +2276,7 @@ void audit_core_dumps(long signr)
 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
 	audit_log_format(ab, "auid=%u uid=%u gid=%u",
 			audit_get_loginuid(current->audit_context),
-			current->uid, current->gid);
+			current->sec->uid, current->sec->gid);
 	selinux_get_task_sid(current, &sid);
 	if (sid) {
 		char *ctx = NULL;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 1b85df5..0016012 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1247,8 +1247,9 @@ static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf)
 		get_task_struct(tsk);
 		rcu_read_unlock();
 
-		if ((current->euid) && (current->euid != tsk->uid)
-		    && (current->euid != tsk->suid)) {
+		if (current->act_as->euid &&
+		    current->act_as->euid != tsk->sec->uid &&
+		    current->act_as->euid != tsk->sec->suid) {
 			put_task_struct(tsk);
 			return -EACCES;
 		}
diff --git a/kernel/exit.c b/kernel/exit.c
index 549c055..d793e22 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -147,7 +147,7 @@ void release_task(struct task_struct * p)
 	struct task_struct *leader;
 	int zap_leader;
 repeat:
-	atomic_dec(&p->user->processes);
+	atomic_dec(&p->sec->user->processes);
 	proc_flush_task(p);
 	write_lock_irq(&tasklist_lock);
 	ptrace_unlink(p);
@@ -1198,7 +1198,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
 
 	if (unlikely(noreap)) {
 		pid_t pid = task_pid_nr_ns(p, ns);
-		uid_t uid = p->uid;
+		uid_t uid = p->sec->uid;
 		int exit_code = p->exit_code;
 		int why, status;
 
@@ -1318,7 +1318,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
 	if (!retval && infop)
 		retval = put_user(task_pid_nr_ns(p, ns), &infop->si_pid);
 	if (!retval && infop)
-		retval = put_user(p->uid, &infop->si_uid);
+		retval = put_user(p->sec->uid, &infop->si_uid);
 	if (!retval)
 		retval = task_pid_nr_ns(p, ns);
 
@@ -1381,7 +1381,7 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader,
 	read_unlock(&tasklist_lock);
 
 	if (unlikely(noreap)) {
-		uid_t uid = p->uid;
+		uid_t uid = p->sec->uid;
 		int why = (p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED;
 
 		exit_code = p->exit_code;
@@ -1452,7 +1452,7 @@ bail_ref:
 	if (!retval && infop)
 		retval = put_user(pid, &infop->si_pid);
 	if (!retval && infop)
-		retval = put_user(p->uid, &infop->si_uid);
+		retval = put_user(p->sec->uid, &infop->si_uid);
 	if (!retval)
 		retval = pid;
 	put_task_struct(p);
@@ -1491,7 +1491,7 @@ static int wait_task_continued(struct task_struct *p, int noreap,
 
 	ns = current->nsproxy->pid_ns;
 	pid = task_pid_nr_ns(p, ns);
-	uid = p->uid;
+	uid = p->sec->uid;
 	get_task_struct(p);
 	read_unlock(&tasklist_lock);
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 8ca1a14..2f267bd 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -122,8 +122,8 @@ void __put_task_struct(struct task_struct *tsk)
 	WARN_ON(tsk == current);
 
 	security_task_free(tsk);
-	free_uid(tsk->user);
-	put_group_info(tsk->group_info);
+	free_uid(tsk->__temp_sec.user);
+	put_group_info(tsk->__temp_sec.group_info);
 	delayacct_tsk_free(tsk);
 
 	if (!profile_handoff_task(tsk))
@@ -1014,17 +1014,18 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
 	DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
 #endif
+	p->act_as = p->sec = &p->__temp_sec;
 	retval = -EAGAIN;
-	if (atomic_read(&p->user->processes) >=
+	if (atomic_read(&p->sec->user->processes) >=
 			p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
 		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
-		    p->user != current->nsproxy->user_ns->root_user)
+		    p->sec->user != current->nsproxy->user_ns->root_user)
 			goto bad_fork_free;
 	}
 
-	atomic_inc(&p->user->__count);
-	atomic_inc(&p->user->processes);
-	get_group_info(p->group_info);
+	atomic_inc(&p->sec->user->__count);
+	atomic_inc(&p->sec->user->processes);
+	get_group_info(p->sec->group_info);
 
 	/*
 	 * If multiple threads are within copy_process(), then this check
@@ -1080,7 +1081,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	p->real_start_time = p->start_time;
 	monotonic_to_bootbased(&p->real_start_time);
 #ifdef CONFIG_SECURITY
-	p->security = NULL;
+	p->sec->security = NULL;
 #endif
 	p->io_context = NULL;
 	p->audit_context = NULL;
@@ -1359,9 +1360,9 @@ bad_fork_cleanup_cgroup:
 bad_fork_cleanup_put_domain:
 	module_put(task_thread_info(p)->exec_domain->module);
 bad_fork_cleanup_count:
-	put_group_info(p->group_info);
-	atomic_dec(&p->user->processes);
-	free_uid(p->user);
+	put_group_info(p->sec->group_info);
+	atomic_dec(&p->sec->user->processes);
+	free_uid(p->sec->user);
 bad_fork_free:
 	free_task(p);
 fork_out:
diff --git a/kernel/futex.c b/kernel/futex.c
index 9dc591a..cdaa691 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -444,7 +444,8 @@ static struct task_struct * futex_find_get_task(pid_t pid)
 
 	rcu_read_lock();
 	p = find_task_by_vpid(pid);
-	if (!p || ((current->euid != p->euid) && (current->euid != p->uid)))
+	if (!p || (current->act_as->euid != p->sec->euid &&
+		   current->act_as->euid != p->sec->uid))
 		p = ERR_PTR(-ESRCH);
 	else
 		get_task_struct(p);
@@ -1857,8 +1858,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
 		if (!p)
 			goto err_unlock;
 		ret = -EPERM;
-		if ((current->euid != p->euid) && (current->euid != p->uid) &&
-				!capable(CAP_SYS_PTRACE))
+		if (current->act_as->euid != p->sec->euid &&
+		    current->act_as->euid != p->sec->uid &&
+		    !capable(CAP_SYS_PTRACE))
 			goto err_unlock;
 		head = p->robust_list;
 		rcu_read_unlock();
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index 0a43def..ae41737 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -141,8 +141,9 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
 		if (!p)
 			goto err_unlock;
 		ret = -EPERM;
-		if ((current->euid != p->euid) && (current->euid != p->uid) &&
-				!capable(CAP_SYS_PTRACE))
+		if (current->act_as->euid != p->sec->euid &&
+		    current->act_as->euid != p->sec->uid &&
+		    !capable(CAP_SYS_PTRACE))
 			goto err_unlock;
 		head = p->compat_robust_list;
 		read_unlock(&tasklist_lock);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 7c76f2f..039b9d2 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -122,6 +122,8 @@ int ptrace_check_attach(struct task_struct *child, int kill)
 
 static int may_attach(struct task_struct *task)
 {
+	struct task_security *sec = current->act_as, *tsec = task->sec;
+
 	/* May we inspect the given task?
 	 * This check is used both for attaching with ptrace
 	 * and for allowing access to sensitive information in /proc.
@@ -134,12 +136,12 @@ static int may_attach(struct task_struct *task)
 	/* Don't let security modules deny introspection */
 	if (task == current)
 		return 0;
-	if (((current->uid != task->euid) ||
-	     (current->uid != task->suid) ||
-	     (current->uid != task->uid) ||
-	     (current->gid != task->egid) ||
-	     (current->gid != task->sgid) ||
-	     (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+	if (((sec->uid != tsec->euid) ||
+	     (sec->uid != tsec->suid) ||
+	     (sec->uid != tsec->uid) ||
+	     (sec->gid != tsec->egid) ||
+	     (sec->gid != tsec->sgid) ||
+	     (sec->gid != tsec->gid)) && !capable(CAP_SYS_PTRACE))
 		return -EPERM;
 	smp_rmb();
 	if (task->mm)
diff --git a/kernel/sched.c b/kernel/sched.c
index b062856..ff69615 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4300,8 +4300,8 @@ recheck:
 			return -EPERM;
 
 		/* can't change other user's priorities */
-		if ((current->euid != p->euid) &&
-		    (current->euid != p->uid))
+		if ((current->act_as->euid != p->sec->euid) &&
+		    (current->act_as->euid != p->sec->uid))
 			return -EPERM;
 	}
 
@@ -4498,8 +4498,9 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
 	read_unlock(&tasklist_lock);
 
 	retval = -EPERM;
-	if ((current->euid != p->euid) && (current->euid != p->uid) &&
-			!capable(CAP_SYS_NICE))
+	if ((current->act_as->euid != p->sec->euid) &&
+	    (current->act_as->euid != p->sec->uid) &&
+	    !capable(CAP_SYS_NICE))
 		goto out_unlock;
 
 	retval = security_task_setscheduler(p, 0, NULL);
diff --git a/kernel/signal.c b/kernel/signal.c
index afa4f78..5c093a0 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -174,7 +174,7 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
 	 * In order to avoid problems with "switch_user()", we want to make
 	 * sure that the compiler doesn't re-load "t->user"
 	 */
-	user = t->user;
+	user = t->sec->user;
 	barrier();
 	atomic_inc(&user->sigpending);
 	if (override_rlimit ||
@@ -537,8 +537,10 @@ static int check_kill_permission(int sig, struct siginfo *info,
 		error = -EPERM;
 		if (((sig != SIGCONT) ||
 			(task_session_nr(current) != task_session_nr(t)))
-		    && (current->euid ^ t->suid) && (current->euid ^ t->uid)
-		    && (current->uid ^ t->suid) && (current->uid ^ t->uid)
+		    && (current->act_as->euid ^ t->sec->suid)
+		    && (current->act_as->euid ^ t->sec->uid)
+		    && (current->act_as->uid ^ t->sec->suid)
+		    && (current->act_as->uid ^ t->sec->uid)
 		    && !capable(CAP_KILL))
 		return error;
 	}
@@ -695,7 +697,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
 			q->info.si_errno = 0;
 			q->info.si_code = SI_USER;
 			q->info.si_pid = task_pid_vnr(current);
-			q->info.si_uid = current->uid;
+			q->info.si_uid = current->act_as->uid;
 			break;
 		case (unsigned long) SEND_SIG_PRIV:
 			q->info.si_signo = sig;
@@ -1111,8 +1113,8 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
 		goto out_unlock;
 	}
 	if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
-	    && (euid != p->suid) && (euid != p->uid)
-	    && (uid != p->suid) && (uid != p->uid)) {
+	    && (euid != p->sec->suid) && (euid != p->sec->uid)
+	    && (uid != p->sec->suid) && (uid != p->sec->uid)) {
 		ret = -EPERM;
 		goto out_unlock;
 	}
@@ -1464,7 +1466,7 @@ void do_notify_parent(struct task_struct *tsk, int sig)
 	info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
 	rcu_read_unlock();
 
-	info.si_uid = tsk->uid;
+	info.si_uid = tsk->sec->uid;
 
 	/* FIXME: find out whether or not this is supposed to be c*time. */
 	info.si_utime = cputime_to_jiffies(cputime_add(tsk->utime,
@@ -1535,7 +1537,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
 	info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
 	rcu_read_unlock();
 
-	info.si_uid = tsk->uid;
+	info.si_uid = tsk->sec->uid;
 
 	/* FIXME: find out whether or not this is supposed to be c*time. */
 	info.si_utime = cputime_to_jiffies(tsk->utime);
@@ -1661,7 +1663,7 @@ void ptrace_notify(int exit_code)
 	info.si_signo = SIGTRAP;
 	info.si_code = exit_code;
 	info.si_pid = task_pid_vnr(current);
-	info.si_uid = current->uid;
+	info.si_uid = current->sec->uid;
 
 	/* Let the debugger run.  */
 	spin_lock_irq(&current->sighand->siglock);
@@ -1831,7 +1833,7 @@ relock:
 				info->si_errno = 0;
 				info->si_code = SI_USER;
 				info->si_pid = task_pid_vnr(current->parent);
-				info->si_uid = current->parent->uid;
+				info->si_uid = current->parent->sec->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -2218,7 +2220,7 @@ sys_kill(int pid, int sig)
 	info.si_errno = 0;
 	info.si_code = SI_USER;
 	info.si_pid = task_tgid_vnr(current);
-	info.si_uid = current->uid;
+	info.si_uid = current->act_as->uid;
 
 	return kill_something_info(sig, &info, pid);
 }
@@ -2234,7 +2236,7 @@ static int do_tkill(int tgid, int pid, int sig)
 	info.si_errno = 0;
 	info.si_code = SI_TKILL;
 	info.si_pid = task_tgid_vnr(current);
-	info.si_uid = current->uid;
+	info.si_uid = current->act_as->uid;
 
 	read_lock(&tasklist_lock);
 	p = find_task_by_vpid(pid);
diff --git a/kernel/sys.c b/kernel/sys.c
index d1fe71e..14acc1b 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -110,8 +110,8 @@ static int set_one_prio(struct task_struct *p, int niceval, int error)
 {
 	int no_nice;
 
-	if (p->uid != current->euid &&
-		p->euid != current->euid && !capable(CAP_SYS_NICE)) {
+	if (p->sec->uid != current->act_as->euid &&
+	    p->sec->euid != current->act_as->euid && !capable(CAP_SYS_NICE)) {
 		error = -EPERM;
 		goto out;
 	}
@@ -168,18 +168,19 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
 			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
-			user = current->user;
+			user = current->sec->user;
 			if (!who)
-				who = current->uid;
+				who = current->sec->uid;
 			else
-				if ((who != current->uid) && !(user = find_user(who)))
+				if ((who != current->sec->uid) &&
+				    !(user = find_user(who)))
 					goto out_unlock;	/* No processes for this user */
 
 			do_each_thread(g, p)
-				if (p->uid == who)
+				if (p->sec->uid == who)
 					error = set_one_prio(p, niceval, error);
 			while_each_thread(g, p);
-			if (who != current->uid)
+			if (who != current->sec->uid)
 				free_uid(user);		/* For find_user() */
 			break;
 	}
@@ -230,21 +231,22 @@ asmlinkage long sys_getpriority(int which, int who)
 			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
-			user = current->user;
+			user = current->sec->user;
 			if (!who)
-				who = current->uid;
+				who = current->sec->uid;
 			else
-				if ((who != current->uid) && !(user = find_user(who)))
+				if ((who != current->sec->uid) &&
+				    !(user = find_user(who)))
 					goto out_unlock;	/* No processes for this user */
 
 			do_each_thread(g, p)
-				if (p->uid == who) {
+				if (p->sec->uid == who) {
 					niceval = 20 - task_nice(p);
 					if (niceval > retval)
 						retval = niceval;
 				}
 			while_each_thread(g, p);
-			if (who != current->uid)
+			if (who != current->sec->uid)
 				free_uid(user);		/* for find_user() */
 			break;
 	}
@@ -481,8 +483,9 @@ void ctrl_alt_del(void)
  */
 asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
 {
-	int old_rgid = current->gid;
-	int old_egid = current->egid;
+	struct task_security *sec = current->sec;
+	int old_rgid = sec->gid;
+	int old_egid = sec->egid;
 	int new_rgid = old_rgid;
 	int new_egid = old_egid;
 	int retval;
@@ -493,7 +496,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
 
 	if (rgid != (gid_t) -1) {
 		if ((old_rgid == rgid) ||
-		    (current->egid==rgid) ||
+		    (sec->egid == rgid) ||
 		    capable(CAP_SETGID))
 			new_rgid = rgid;
 		else
@@ -501,8 +504,8 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
 	}
 	if (egid != (gid_t) -1) {
 		if ((old_rgid == egid) ||
-		    (current->egid == egid) ||
-		    (current->sgid == egid) ||
+		    (sec->egid == egid) ||
+		    (sec->sgid == egid) ||
 		    capable(CAP_SETGID))
 			new_egid = egid;
 		else
@@ -514,10 +517,10 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
 	}
 	if (rgid != (gid_t) -1 ||
 	    (egid != (gid_t) -1 && egid != old_rgid))
-		current->sgid = new_egid;
-	current->fsgid = new_egid;
-	current->egid = new_egid;
-	current->gid = new_rgid;
+		sec->sgid = new_egid;
+	sec->fsgid = new_egid;
+	sec->egid = new_egid;
+	sec->gid = new_rgid;
 	key_fsgid_changed(current);
 	proc_id_connector(current, PROC_EVENT_GID);
 	return 0;
@@ -530,7 +533,8 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
  */
 asmlinkage long sys_setgid(gid_t gid)
 {
-	int old_egid = current->egid;
+	struct task_security *sec = current->sec;
+	int old_egid = sec->egid;
 	int retval;
 
 	retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
@@ -542,13 +546,13 @@ asmlinkage long sys_setgid(gid_t gid)
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->gid = current->egid = current->sgid = current->fsgid = gid;
-	} else if ((gid == current->gid) || (gid == current->sgid)) {
+		sec->gid = sec->egid = sec->sgid = sec->fsgid = gid;
+	} else if ((gid == sec->gid) || (gid == sec->sgid)) {
 		if (old_egid != gid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->egid = current->fsgid = gid;
+		sec->egid = sec->fsgid = gid;
 	}
 	else
 		return -EPERM;
@@ -579,7 +583,7 @@ static int set_user(uid_t new_ruid, int dumpclear)
 		set_dumpable(current->mm, suid_dumpable);
 		smp_wmb();
 	}
-	current->uid = new_ruid;
+	current->sec->uid = new_ruid;
 	return 0;
 }
 
@@ -600,6 +604,7 @@ static int set_user(uid_t new_ruid, int dumpclear)
  */
 asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 {
+	struct task_security *sec = current->sec;
 	int old_ruid, old_euid, old_suid, new_ruid, new_euid;
 	int retval;
 
@@ -607,14 +612,14 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 	if (retval)
 		return retval;
 
-	new_ruid = old_ruid = current->uid;
-	new_euid = old_euid = current->euid;
-	old_suid = current->suid;
+	new_ruid = old_ruid = sec->uid;
+	new_euid = old_euid = sec->euid;
+	old_suid = sec->suid;
 
 	if (ruid != (uid_t) -1) {
 		new_ruid = ruid;
 		if ((old_ruid != ruid) &&
-		    (current->euid != ruid) &&
+		    (sec->euid != ruid) &&
 		    !capable(CAP_SETUID))
 			return -EPERM;
 	}
@@ -622,8 +627,8 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 	if (euid != (uid_t) -1) {
 		new_euid = euid;
 		if ((old_ruid != euid) &&
-		    (current->euid != euid) &&
-		    (current->suid != euid) &&
+		    (sec->euid != euid) &&
+		    (sec->suid != euid) &&
 		    !capable(CAP_SETUID))
 			return -EPERM;
 	}
@@ -635,11 +640,11 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 		set_dumpable(current->mm, suid_dumpable);
 		smp_wmb();
 	}
-	current->fsuid = current->euid = new_euid;
+	sec->fsuid = sec->euid = new_euid;
 	if (ruid != (uid_t) -1 ||
 	    (euid != (uid_t) -1 && euid != old_ruid))
-		current->suid = current->euid;
-	current->fsuid = current->euid;
+		sec->suid = sec->euid;
+	sec->fsuid = sec->euid;
 
 	key_fsuid_changed(current);
 	proc_id_connector(current, PROC_EVENT_UID);
@@ -662,7 +667,8 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
  */
 asmlinkage long sys_setuid(uid_t uid)
 {
-	int old_euid = current->euid;
+	struct task_security *sec = current->sec;
+	int old_euid = sec->euid;
 	int old_ruid, old_suid, new_suid;
 	int retval;
 
@@ -670,23 +676,23 @@ asmlinkage long sys_setuid(uid_t uid)
 	if (retval)
 		return retval;
 
-	old_ruid = current->uid;
-	old_suid = current->suid;
+	old_ruid = sec->uid;
+	old_suid = sec->suid;
 	new_suid = old_suid;
 	
 	if (capable(CAP_SETUID)) {
 		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
 			return -EAGAIN;
 		new_suid = uid;
-	} else if ((uid != current->uid) && (uid != new_suid))
+	} else if ((uid != sec->uid) && (uid != new_suid))
 		return -EPERM;
 
 	if (old_euid != uid) {
 		set_dumpable(current->mm, suid_dumpable);
 		smp_wmb();
 	}
-	current->fsuid = current->euid = uid;
-	current->suid = new_suid;
+	sec->fsuid = sec->euid = uid;
+	sec->suid = new_suid;
 
 	key_fsuid_changed(current);
 	proc_id_connector(current, PROC_EVENT_UID);
@@ -701,9 +707,10 @@ asmlinkage long sys_setuid(uid_t uid)
  */
 asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 {
-	int old_ruid = current->uid;
-	int old_euid = current->euid;
-	int old_suid = current->suid;
+	struct task_security *sec = current->sec;
+	int old_ruid = sec->uid;
+	int old_euid = sec->euid;
+	int old_suid = sec->suid;
 	int retval;
 
 	retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
@@ -711,30 +718,31 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 		return retval;
 
 	if (!capable(CAP_SETUID)) {
-		if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
-		    (ruid != current->euid) && (ruid != current->suid))
+		if ((ruid != (uid_t) -1) && (ruid != sec->uid) &&
+		    (ruid != sec->euid) && (ruid != sec->suid))
 			return -EPERM;
-		if ((euid != (uid_t) -1) && (euid != current->uid) &&
-		    (euid != current->euid) && (euid != current->suid))
+		if ((euid != (uid_t) -1) && (euid != sec->uid) &&
+		    (euid != sec->euid) && (euid != sec->suid))
 			return -EPERM;
-		if ((suid != (uid_t) -1) && (suid != current->uid) &&
-		    (suid != current->euid) && (suid != current->suid))
+		if ((suid != (uid_t) -1) && (suid != sec->uid) &&
+		    (suid != sec->euid) && (suid != sec->suid))
 			return -EPERM;
 	}
 	if (ruid != (uid_t) -1) {
-		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
+		if (ruid != sec->uid &&
+		    set_user(ruid, euid != sec->euid) < 0)
 			return -EAGAIN;
 	}
 	if (euid != (uid_t) -1) {
-		if (euid != current->euid) {
+		if (euid != sec->euid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->euid = euid;
+		sec->euid = euid;
 	}
-	current->fsuid = current->euid;
+	sec->fsuid = sec->euid;
 	if (suid != (uid_t) -1)
-		current->suid = suid;
+		sec->suid = suid;
 
 	key_fsuid_changed(current);
 	proc_id_connector(current, PROC_EVENT_UID);
@@ -744,11 +752,12 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 
 asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid)
 {
+	struct task_security *sec = current->sec;
 	int retval;
 
-	if (!(retval = put_user(current->uid, ruid)) &&
-	    !(retval = put_user(current->euid, euid)))
-		retval = put_user(current->suid, suid);
+	if (!(retval = put_user(sec->uid, ruid)) &&
+	    !(retval = put_user(sec->euid, euid)))
+		retval = put_user(sec->suid, suid);
 
 	return retval;
 }
@@ -758,6 +767,7 @@ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __us
  */
 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 {
+	struct task_security *sec = current->sec;
 	int retval;
 
 	retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
@@ -765,28 +775,28 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 		return retval;
 
 	if (!capable(CAP_SETGID)) {
-		if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
-		    (rgid != current->egid) && (rgid != current->sgid))
+		if ((rgid != (gid_t) -1) && (rgid != sec->gid) &&
+		    (rgid != sec->egid) && (rgid != sec->sgid))
 			return -EPERM;
-		if ((egid != (gid_t) -1) && (egid != current->gid) &&
-		    (egid != current->egid) && (egid != current->sgid))
+		if ((egid != (gid_t) -1) && (egid != sec->gid) &&
+		    (egid != sec->egid) && (egid != sec->sgid))
 			return -EPERM;
-		if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
-		    (sgid != current->egid) && (sgid != current->sgid))
+		if ((sgid != (gid_t) -1) && (sgid != sec->gid) &&
+		    (sgid != sec->egid) && (sgid != sec->sgid))
 			return -EPERM;
 	}
 	if (egid != (gid_t) -1) {
-		if (egid != current->egid) {
+		if (egid != sec->egid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->egid = egid;
+		sec->egid = egid;
 	}
-	current->fsgid = current->egid;
+	sec->fsgid = sec->egid;
 	if (rgid != (gid_t) -1)
-		current->gid = rgid;
+		sec->gid = rgid;
 	if (sgid != (gid_t) -1)
-		current->sgid = sgid;
+		sec->sgid = sgid;
 
 	key_fsgid_changed(current);
 	proc_id_connector(current, PROC_EVENT_GID);
@@ -795,11 +805,12 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 
 asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)
 {
+	struct task_security *sec = current->sec;
 	int retval;
 
-	if (!(retval = put_user(current->gid, rgid)) &&
-	    !(retval = put_user(current->egid, egid)))
-		retval = put_user(current->sgid, sgid);
+	if (!(retval = put_user(sec->gid, rgid)) &&
+	    !(retval = put_user(sec->egid, egid)))
+		retval = put_user(sec->sgid, sgid);
 
 	return retval;
 }
@@ -813,20 +824,21 @@ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __us
  */
 asmlinkage long sys_setfsuid(uid_t uid)
 {
+	struct task_security *sec = current->sec;
 	int old_fsuid;
 
-	old_fsuid = current->fsuid;
+	old_fsuid = sec->fsuid;
 	if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))
 		return old_fsuid;
 
-	if (uid == current->uid || uid == current->euid ||
-	    uid == current->suid || uid == current->fsuid || 
+	if (uid == sec->uid || uid == sec->euid ||
+	    uid == sec->suid || uid == sec->fsuid ||
 	    capable(CAP_SETUID)) {
 		if (uid != old_fsuid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->fsuid = uid;
+		sec->fsuid = uid;
 	}
 
 	key_fsuid_changed(current);
@@ -842,20 +854,21 @@ asmlinkage long sys_setfsuid(uid_t uid)
  */
 asmlinkage long sys_setfsgid(gid_t gid)
 {
+	struct task_security *sec = current->sec;
 	int old_fsgid;
 
-	old_fsgid = current->fsgid;
+	old_fsgid = sec->fsgid;
 	if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
 		return old_fsgid;
 
-	if (gid == current->gid || gid == current->egid ||
-	    gid == current->sgid || gid == current->fsgid || 
+	if (gid == sec->gid || gid == sec->egid ||
+	    gid == sec->sgid || gid == sec->fsgid ||
 	    capable(CAP_SETGID)) {
 		if (gid != old_fsgid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->fsgid = gid;
+		sec->fsgid = gid;
 		key_fsgid_changed(current);
 		proc_id_connector(current, PROC_EVENT_GID);
 	}
@@ -1235,6 +1248,7 @@ int groups_search(struct group_info *group_info, gid_t grp)
 /* validate and set current->group_info */
 int set_current_groups(struct group_info *group_info)
 {
+	struct task_security *sec = current->sec;
 	int retval;
 	struct group_info *old_info;
 
@@ -1245,10 +1259,10 @@ int set_current_groups(struct group_info *group_info)
 	groups_sort(group_info);
 	get_group_info(group_info);
 
-	task_lock(current);
-	old_info = current->group_info;
-	current->group_info = group_info;
-	task_unlock(current);
+	spin_lock(&sec->lock);
+	old_info = sec->group_info;
+	sec->group_info = group_info;
+	spin_unlock(&sec->lock);
 
 	put_group_info(old_info);
 
@@ -1259,6 +1273,7 @@ EXPORT_SYMBOL(set_current_groups);
 
 asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
 {
+	struct task_security *sec = current->sec;
 	int i = 0;
 
 	/*
@@ -1270,13 +1285,13 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
 		return -EINVAL;
 
 	/* no need to grab task_lock here; it cannot change */
-	i = current->group_info->ngroups;
+	i = sec->group_info->ngroups;
 	if (gidsetsize) {
 		if (i > gidsetsize) {
 			i = -EINVAL;
 			goto out;
 		}
-		if (groups_to_user(grouplist, current->group_info)) {
+		if (groups_to_user(grouplist, sec->group_info)) {
 			i = -EFAULT;
 			goto out;
 		}
@@ -1320,9 +1335,10 @@ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
  */
 int in_group_p(gid_t grp)
 {
+	struct task_security *act_as = current->act_as;
 	int retval = 1;
-	if (grp != current->fsgid)
-		retval = groups_search(current->group_info, grp);
+	if (grp != act_as->fsgid)
+		retval = groups_search(act_as->group_info, grp);
 	return retval;
 }
 
@@ -1330,9 +1346,10 @@ EXPORT_SYMBOL(in_group_p);
 
 int in_egroup_p(gid_t grp)
 {
+	struct task_security *act_as = current->act_as;
 	int retval = 1;
-	if (grp != current->egid)
-		retval = groups_search(current->group_info, grp);
+	if (grp != act_as->egid)
+		retval = groups_search(act_as->group_info, grp);
 	return retval;
 }
 
@@ -1641,6 +1658,9 @@ asmlinkage long sys_umask(int mask)
 asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 			  unsigned long arg4, unsigned long arg5)
 {
+	struct task_struct *me = current;
+	struct task_security *sec = me->sec;
+	unsigned char comm[sizeof(me->comm)];
 	long error;
 
 	error = security_task_prctl(option, arg2, arg3, arg4, arg5);
@@ -1653,39 +1673,39 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 				error = -EINVAL;
 				break;
 			}
-			current->pdeath_signal = arg2;
+			me->pdeath_signal = arg2;
 			break;
 		case PR_GET_PDEATHSIG:
-			error = put_user(current->pdeath_signal, (int __user *)arg2);
+			error = put_user(me->pdeath_signal, (int __user *)arg2);
 			break;
 		case PR_GET_DUMPABLE:
-			error = get_dumpable(current->mm);
+			error = get_dumpable(me->mm);
 			break;
 		case PR_SET_DUMPABLE:
 			if (arg2 < 0 || arg2 > 1) {
 				error = -EINVAL;
 				break;
 			}
-			set_dumpable(current->mm, arg2);
+			set_dumpable(me->mm, arg2);
 			break;
 
 		case PR_SET_UNALIGN:
-			error = SET_UNALIGN_CTL(current, arg2);
+			error = SET_UNALIGN_CTL(me, arg2);
 			break;
 		case PR_GET_UNALIGN:
-			error = GET_UNALIGN_CTL(current, arg2);
+			error = GET_UNALIGN_CTL(me, arg2);
 			break;
 		case PR_SET_FPEMU:
-			error = SET_FPEMU_CTL(current, arg2);
+			error = SET_FPEMU_CTL(me, arg2);
 			break;
 		case PR_GET_FPEMU:
-			error = GET_FPEMU_CTL(current, arg2);
+			error = GET_FPEMU_CTL(me, arg2);
 			break;
 		case PR_SET_FPEXC:
-			error = SET_FPEXC_CTL(current, arg2);
+			error = SET_FPEXC_CTL(me, arg2);
 			break;
 		case PR_GET_FPEXC:
-			error = GET_FPEXC_CTL(current, arg2);
+			error = GET_FPEXC_CTL(me, arg2);
 			break;
 		case PR_GET_TIMING:
 			error = PR_TIMING_STATISTICAL;
@@ -1698,7 +1718,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 			break;
 
 		case PR_GET_KEEPCAPS:
-			if (current->keep_capabilities)
+			if (sec->keep_capabilities)
 				error = 1;
 			break;
 		case PR_SET_KEEPCAPS:
@@ -1706,33 +1726,26 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 				error = -EINVAL;
 				break;
 			}
-			current->keep_capabilities = arg2;
+			sec->keep_capabilities = arg2;
 			break;
-		case PR_SET_NAME: {
-			struct task_struct *me = current;
-			unsigned char ncomm[sizeof(me->comm)];
-
-			ncomm[sizeof(me->comm)-1] = 0;
-			if (strncpy_from_user(ncomm, (char __user *)arg2,
+		case PR_SET_NAME:
+			comm[sizeof(me->comm)-1] = 0;
+			if (strncpy_from_user(comm, (char __user *)arg2,
 						sizeof(me->comm)-1) < 0)
 				return -EFAULT;
-			set_task_comm(me, ncomm);
+			set_task_comm(me, comm);
 			return 0;
-		}
-		case PR_GET_NAME: {
-			struct task_struct *me = current;
-			unsigned char tcomm[sizeof(me->comm)];
-
-			get_task_comm(tcomm, me);
-			if (copy_to_user((char __user *)arg2, tcomm, sizeof(tcomm)))
+		case PR_GET_NAME:
+			get_task_comm(comm, me);
+			if (copy_to_user((char __user *)arg2, comm,
+					 sizeof(comm)))
 				return -EFAULT;
 			return 0;
-		}
 		case PR_GET_ENDIAN:
-			error = GET_ENDIAN(current, arg2);
+			error = GET_ENDIAN(me, arg2);
 			break;
 		case PR_SET_ENDIAN:
-			error = SET_ENDIAN(current, arg2);
+			error = SET_ENDIAN(me, arg2);
 			break;
 
 		case PR_GET_SECCOMP:
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 0deed82..d3863df 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1382,7 +1382,7 @@ out:
 
 static int test_perm(int mode, int op)
 {
-	if (!current->euid)
+	if (!current->act_as->euid)
 		mode >>= 6;
 	else if (in_egroup_p(0))
 		mode >>= 3;
diff --git a/kernel/timer.c b/kernel/timer.c
index a05817c..5710255 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -987,25 +987,25 @@ asmlinkage long sys_getppid(void)
 asmlinkage long sys_getuid(void)
 {
 	/* Only we change this so SMP safe */
-	return current->uid;
+	return current->sec->uid;
 }
 
 asmlinkage long sys_geteuid(void)
 {
 	/* Only we change this so SMP safe */
-	return current->euid;
+	return current->sec->euid;
 }
 
 asmlinkage long sys_getgid(void)
 {
 	/* Only we change this so SMP safe */
-	return current->gid;
+	return current->sec->gid;
 }
 
 asmlinkage long sys_getegid(void)
 {
 	/* Only we change this so SMP safe */
-	return  current->egid;
+	return  current->sec->egid;
 }
 
 #endif
diff --git a/kernel/uid16.c b/kernel/uid16.c
index dd308ba..c56f6fe 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -86,9 +86,9 @@ asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid,
 {
 	int retval;
 
-	if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
-	    !(retval = put_user(high2lowuid(current->euid), euid)))
-		retval = put_user(high2lowuid(current->suid), suid);
+	if (!(retval = put_user(high2lowuid(current->sec->uid), ruid)) &&
+	    !(retval = put_user(high2lowuid(current->sec->euid), euid)))
+		retval = put_user(high2lowuid(current->sec->suid), suid);
 
 	return retval;
 }
@@ -106,9 +106,9 @@ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid,
 {
 	int retval;
 
-	if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
-	    !(retval = put_user(high2lowgid(current->egid), egid)))
-		retval = put_user(high2lowgid(current->sgid), sgid);
+	if (!(retval = put_user(high2lowgid(current->sec->gid), rgid)) &&
+	    !(retval = put_user(high2lowgid(current->sec->egid), egid)))
+		retval = put_user(high2lowgid(current->sec->sgid), sgid);
 
 	return retval;
 }
@@ -166,20 +166,20 @@ asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist)
 	if (gidsetsize < 0)
 		return -EINVAL;
 
-	get_group_info(current->group_info);
-	i = current->group_info->ngroups;
+	get_group_info(current->sec->group_info);
+	i = current->sec->group_info->ngroups;
 	if (gidsetsize) {
 		if (i > gidsetsize) {
 			i = -EINVAL;
 			goto out;
 		}
-		if (groups16_to_user(grouplist, current->group_info)) {
+		if (groups16_to_user(grouplist, current->sec->group_info)) {
 			i = -EFAULT;
 			goto out;
 		}
 	}
 out:
-	put_group_info(current->group_info);
+	put_group_info(current->sec->group_info);
 	return i;
 }
 
@@ -210,20 +210,20 @@ asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist)
 
 asmlinkage long sys_getuid16(void)
 {
-	return high2lowuid(current->uid);
+	return high2lowuid(current->sec->uid);
 }
 
 asmlinkage long sys_geteuid16(void)
 {
-	return high2lowuid(current->euid);
+	return high2lowuid(current->sec->euid);
 }
 
 asmlinkage long sys_getgid16(void)
 {
-	return high2lowgid(current->gid);
+	return high2lowgid(current->sec->gid);
 }
 
 asmlinkage long sys_getegid16(void)
 {
-	return high2lowgid(current->egid);
+	return high2lowgid(current->sec->egid);
 }
diff --git a/kernel/user.c b/kernel/user.c
index 8320a87..d9a84b1 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -416,11 +416,11 @@ void switch_uid(struct user_struct *new_user)
 	 * cheaply with the new uid cache, so if it matters
 	 * we should be checking for it.  -DaveM
 	 */
-	old_user = current->user;
+	old_user = current->sec->user;
 	atomic_inc(&new_user->processes);
 	atomic_dec(&old_user->processes);
 	switch_uid_keyring(new_user);
-	current->user = new_user;
+	current->sec->user = new_user;
 	sched_switch_user(current);
 
 	/*
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 7af90fc..fef8023 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -49,7 +49,7 @@ static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
 	}
 
 	/* Reset current->user with a new one */
-	new_user = alloc_uid(ns, current->uid);
+	new_user = alloc_uid(ns, current->sec->uid);
 	if (!new_user) {
 		free_uid(ns->root_user);
 		kfree(ns);
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 91a081a..917a90e 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -125,8 +125,8 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
 	 * Superuser processes are usually more important, so we make it
 	 * less likely that we kill those.
 	 */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
-				p->uid == 0 || p->euid == 0)
+	if (cap_t(p->sec->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
+				p->sec->uid == 0 || p->sec->euid == 0)
 		points /= 4;
 
 	/*
@@ -135,7 +135,7 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
 	 * tend to only have this flag set on applications they think
 	 * of as important.
 	 */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
+	if (cap_t(p->sec->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
 		points /= 4;
 
 	/*
diff --git a/net/core/scm.c b/net/core/scm.c
index 100ba6d..c5b076b 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -44,11 +44,13 @@
 
 static __inline__ int scm_check_creds(struct ucred *creds)
 {
+	struct task_security *sec = current->act_as;
+
 	if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) &&
-	    ((creds->uid == current->uid || creds->uid == current->euid ||
-	      creds->uid == current->suid) || capable(CAP_SETUID)) &&
-	    ((creds->gid == current->gid || creds->gid == current->egid ||
-	      creds->gid == current->sgid) || capable(CAP_SETGID))) {
+	    ((creds->uid == sec->uid || creds->uid == sec->euid ||
+	      creds->uid == sec->suid) || capable(CAP_SETUID)) &&
+	    ((creds->gid == sec->gid || creds->gid == sec->egid ||
+	      creds->gid == sec->sgid) || capable(CAP_SETGID))) {
 	       return 0;
 	}
 	return -EPERM;
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 390a1ec..e254e56 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -339,7 +339,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags)
 	struct auth_cred acred = {
 		.uid = current_fsuid(),
 		.gid = current_fsgid(),
-		.group_info = current->group_info,
+		.group_info = current->act_as->group_info,
 	};
 	struct rpc_cred *ret;
 
@@ -375,7 +375,7 @@ rpcauth_bindcred(struct rpc_task *task)
 	struct auth_cred acred = {
 		.uid = current_fsuid(),
 		.gid = current_fsgid(),
-		.group_info = current->group_info,
+		.group_info = current->act_as->group_info,
 	};
 	struct rpc_cred *ret;
 	int flags = 0;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 060bba4..974037d 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -484,8 +484,8 @@ static int unix_listen(struct socket *sock, int backlog)
 	sk->sk_state		= TCP_LISTEN;
 	/* set credentials so connect can copy them */
 	sk->sk_peercred.pid	= task_tgid_vnr(current);
-	sk->sk_peercred.uid	= current->euid;
-	sk->sk_peercred.gid	= current->egid;
+	sk->sk_peercred.uid	= current->act_as->euid;
+	sk->sk_peercred.gid	= current->act_as->egid;
 	err = 0;
 
 out_unlock:
@@ -1135,8 +1135,8 @@ restart:
 	newsk->sk_state		= TCP_ESTABLISHED;
 	newsk->sk_type		= sk->sk_type;
 	newsk->sk_peercred.pid	= task_tgid_vnr(current);
-	newsk->sk_peercred.uid	= current->euid;
-	newsk->sk_peercred.gid	= current->egid;
+	newsk->sk_peercred.uid	= current->act_as->euid;
+	newsk->sk_peercred.gid	= current->act_as->egid;
 	newu = unix_sk(newsk);
 	newsk->sk_sleep		= &newu->peer_wait;
 	otheru = unix_sk(other);
@@ -1196,8 +1196,8 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb)
 	unix_peer(ska)=skb;
 	unix_peer(skb)=ska;
 	ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current);
-	ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid;
-	ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid;
+	ska->sk_peercred.uid = skb->sk_peercred.uid = current->act_as->euid;
+	ska->sk_peercred.gid = skb->sk_peercred.gid = current->act_as->egid;
 
 	if (ska->sk_type != SOCK_DGRAM) {
 		ska->sk_state = TCP_ESTABLISHED;
diff --git a/security/dummy.c b/security/dummy.c
index 7993b30..287f3ec 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -37,11 +37,11 @@ static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
 			 kernel_cap_t * inheritable, kernel_cap_t * permitted)
 {
 	*effective = *inheritable = *permitted = 0;
-	if (target->euid == 0) {
+	if (target->sec->euid == 0) {
 		*permitted |= (~0 & ~CAP_FS_MASK);
 		*effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
 	}
-	if (target->fsuid == 0) {
+	if (target->sec->fsuid == 0) {
 		*permitted |= CAP_FS_MASK;
 		*effective |= CAP_FS_MASK;
 	}
@@ -71,7 +71,7 @@ static int dummy_acct (struct file *file)
 
 static int dummy_capable (struct task_struct *tsk, int cap)
 {
-	if (cap_raised (tsk->cap_effective, cap))
+	if (cap_raised(tsk->act_as->cap_effective, cap))
 		return 0;
 	return -EPERM;
 }
@@ -93,7 +93,7 @@ static int dummy_quota_on (struct dentry *dentry)
 
 static int dummy_syslog (int type)
 {
-	if ((type != 3 && type != 10) && current->euid)
+	if ((type != 3 && type != 10) && current->act_as->euid)
 		return -EPERM;
 	return 0;
 }
@@ -126,19 +126,24 @@ static void dummy_bprm_free_security (struct linux_binprm *bprm)
 
 static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
 {
-	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
+	struct task_security *sec = current->sec;
+
+	if (bprm->e_uid != sec->uid || bprm->e_gid != sec->gid) {
 		set_dumpable(current->mm, suid_dumpable);
 
 		if ((unsafe & ~LSM_UNSAFE_PTRACE_CAP) && !capable(CAP_SETUID)) {
-			bprm->e_uid = current->uid;
-			bprm->e_gid = current->gid;
+			bprm->e_uid = sec->uid;
+			bprm->e_gid = sec->gid;
 		}
 	}
 
-	current->suid = current->euid = current->fsuid = bprm->e_uid;
-	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+	sec->suid = sec->euid = sec->fsuid = bprm->e_uid;
+	sec->sgid = sec->egid = sec->fsgid = bprm->e_gid;
 
-	dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
+	dummy_capget(current,
+		     &sec->cap_effective,
+		     &sec->cap_inheritable,
+		     &sec->cap_permitted);
 }
 
 static void dummy_bprm_post_apply_creds (struct linux_binprm *bprm)
@@ -162,8 +167,8 @@ static int dummy_bprm_secureexec (struct linux_binprm *bprm)
 	   in the AT_SECURE field to decide whether secure mode
 	   is required.  Hence, this logic is required to preserve
 	   the legacy decision algorithm used by the old userland. */
-	return (current->euid != current->uid ||
-		current->egid != current->gid);
+	return (current->sec->euid != current->sec->uid ||
+		current->sec->egid != current->sec->gid);
 }
 
 static int dummy_sb_alloc_security (struct super_block *sb)
@@ -492,7 +497,12 @@ static int dummy_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
 
 static int dummy_task_post_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
 {
-	dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
+	struct task_security *sec = current->sec;
+
+	dummy_capget(current,
+		     &sec->cap_effective,
+		     &sec->cap_inheritable,
+		     &sec->cap_permitted);
 	return 0;
 }
 
@@ -579,7 +589,7 @@ static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
 
 static void dummy_task_reparent_to_init (struct task_struct *p)
 {
-	p->euid = p->fsuid = 0;
+	p->sec->euid = p->sec->fsuid = 0;
 	return;
 }
 
@@ -689,7 +699,7 @@ static int dummy_sem_semop (struct sem_array *sma,
 
 static int dummy_netlink_send (struct sock *sk, struct sk_buff *skb)
 {
-	NETLINK_CB(skb).eff_cap = current->cap_effective;
+	NETLINK_CB(skb).eff_cap = current->act_as->cap_effective;
 	return 0;
 }
 
diff --git a/security/keys/key.c b/security/keys/key.c
index 48fabb1..1692988 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -817,7 +817,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 		perm |= KEY_USR_WRITE;
 
 	/* allocate a new key */
-	key = key_alloc(ktype, description, current_fsuid(), current->fsgid,
+	key = key_alloc(ktype, description, current_fsuid(), current_fsgid(),
 			current, perm, flags);
 	if (IS_ERR(key)) {
 		key_ref = ERR_PTR(PTR_ERR(key));
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index b3a63dd..4051948 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -846,7 +846,7 @@ long keyctl_instantiate_key(key_serial_t id,
 	/* the appropriate instantiation authorisation key must have been
 	 * assumed before calling this */
 	ret = -EPERM;
-	instkey = current->request_key_auth;
+	instkey = current->sec->request_key_auth;
 	if (!instkey)
 		goto error;
 
@@ -895,8 +895,8 @@ long keyctl_instantiate_key(key_serial_t id,
 	/* discard the assumed authority if it's just been disabled by
 	 * instantiation of the key */
 	if (ret == 0) {
-		key_put(current->request_key_auth);
-		current->request_key_auth = NULL;
+		key_put(current->sec->request_key_auth);
+		current->sec->request_key_auth = NULL;
 	}
 
 error2:
@@ -924,7 +924,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
 	/* the appropriate instantiation authorisation key must have been
 	 * assumed before calling this */
 	ret = -EPERM;
-	instkey = current->request_key_auth;
+	instkey = current->sec->request_key_auth;
 	if (!instkey)
 		goto error;
 
@@ -952,8 +952,8 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
 	/* discard the assumed authority if it's just been disabled by
 	 * instantiation of the key */
 	if (ret == 0) {
-		key_put(current->request_key_auth);
-		current->request_key_auth = NULL;
+		key_put(current->sec->request_key_auth);
+		current->sec->request_key_auth = NULL;
 	}
 
 error:
@@ -968,6 +968,7 @@ error:
  */
 long keyctl_set_reqkey_keyring(int reqkey_defl)
 {
+	struct task_security *sec = current->sec;
 	int ret;
 
 	switch (reqkey_defl) {
@@ -987,10 +988,10 @@ long keyctl_set_reqkey_keyring(int reqkey_defl)
 	case KEY_REQKEY_DEFL_USER_KEYRING:
 	case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
 	set:
-		current->jit_keyring = reqkey_defl;
+		sec->jit_keyring = reqkey_defl;
 
 	case KEY_REQKEY_DEFL_NO_CHANGE:
-		return current->jit_keyring;
+		return sec->jit_keyring;
 
 	case KEY_REQKEY_DEFL_GROUP_KEYRING:
 	default:
@@ -1055,8 +1056,8 @@ long keyctl_assume_authority(key_serial_t id)
 
 	/* we divest ourselves of authority if given an ID of 0 */
 	if (id == 0) {
-		key_put(current->request_key_auth);
-		current->request_key_auth = NULL;
+		key_put(current->sec->request_key_auth);
+		current->sec->request_key_auth = NULL;
 		ret = 0;
 		goto error;
 	}
@@ -1072,8 +1073,8 @@ long keyctl_assume_authority(key_serial_t id)
 		goto error;
 	}
 
-	key_put(current->request_key_auth);
-	current->request_key_auth = authkey;
+	key_put(current->sec->request_key_auth);
+	current->sec->request_key_auth = authkey;
 	ret = authkey->serial;
 
 error:
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 3b41f9b..07898bd 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -22,6 +22,7 @@ int key_task_permission(const key_ref_t key_ref,
 			struct task_struct *context,
 			key_perm_t perm)
 {
+	struct task_security *sec = context->act_as;
 	struct key *key;
 	key_perm_t kperm;
 	int ret;
@@ -29,7 +30,7 @@ int key_task_permission(const key_ref_t key_ref,
 	key = key_ref_to_ptr(key_ref);
 
 	/* use the second 8-bits of permissions for keys the caller owns */
-	if (key->uid == context->fsuid) {
+	if (key->uid == sec->fsuid) {
 		kperm = key->perm >> 16;
 		goto use_these_perms;
 	}
@@ -37,14 +38,14 @@ int key_task_permission(const key_ref_t key_ref,
 	/* use the third 8-bits of permissions for keys the caller has a group
 	 * membership in common with */
 	if (key->gid != -1 && key->perm & KEY_GRP_ALL) {
-		if (key->gid == context->fsgid) {
+		if (key->gid == sec->fsgid) {
 			kperm = key->perm >> 8;
 			goto use_these_perms;
 		}
 
-		task_lock(context);
-		ret = groups_search(context->group_info, key->gid);
-		task_unlock(context);
+		spin_lock(&sec->lock);
+		ret = groups_search(sec->group_info, key->gid);
+		spin_unlock(&sec->lock);
 
 		if (ret) {
 			kperm = key->perm >> 8;
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 2a0eb94..98854b2 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -145,7 +145,7 @@ int install_thread_keyring(struct task_struct *tsk)
 
 	sprintf(buf, "_tid.%u", tsk->pid);
 
-	keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+	keyring = keyring_alloc(buf, tsk->sec->uid, tsk->sec->gid, tsk,
 				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
@@ -153,8 +153,8 @@ int install_thread_keyring(struct task_struct *tsk)
 	}
 
 	task_lock(tsk);
-	old = tsk->thread_keyring;
-	tsk->thread_keyring = keyring;
+	old = tsk->sec->thread_keyring;
+	tsk->sec->thread_keyring = keyring;
 	task_unlock(tsk);
 
 	ret = 0;
@@ -180,7 +180,7 @@ int install_process_keyring(struct task_struct *tsk)
 	if (!tsk->signal->process_keyring) {
 		sprintf(buf, "_pid.%u", tsk->tgid);
 
-		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+		keyring = keyring_alloc(buf, tsk->sec->uid, tsk->sec->gid, tsk,
 					KEY_ALLOC_QUOTA_OVERRUN, NULL);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
@@ -226,7 +226,7 @@ static int install_session_keyring(struct task_struct *tsk,
 		if (tsk->signal->session_keyring)
 			flags = KEY_ALLOC_IN_QUOTA;
 
-		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+		keyring = keyring_alloc(buf, tsk->sec->uid, tsk->sec->gid, tsk,
 					flags, NULL);
 		if (IS_ERR(keyring))
 			return PTR_ERR(keyring);
@@ -280,14 +280,14 @@ int copy_thread_group_keys(struct task_struct *tsk)
  */
 int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
 {
-	key_check(tsk->thread_keyring);
-	key_check(tsk->request_key_auth);
+	key_check(tsk->sec->thread_keyring);
+	key_check(tsk->sec->request_key_auth);
 
 	/* no thread keyring yet */
-	tsk->thread_keyring = NULL;
+	tsk->sec->thread_keyring = NULL;
 
 	/* copy the request_key() authorisation for this thread */
-	key_get(tsk->request_key_auth);
+	key_get(tsk->sec->request_key_auth);
 
 	return 0;
 
@@ -310,8 +310,8 @@ void exit_thread_group_keys(struct signal_struct *tg)
  */
 void exit_keys(struct task_struct *tsk)
 {
-	key_put(tsk->thread_keyring);
-	key_put(tsk->request_key_auth);
+	key_put(tsk->sec->thread_keyring);
+	key_put(tsk->sec->request_key_auth);
 
 } /* end exit_keys() */
 
@@ -325,8 +325,8 @@ int exec_keys(struct task_struct *tsk)
 
 	/* newly exec'd tasks don't get a thread keyring */
 	task_lock(tsk);
-	old = tsk->thread_keyring;
-	tsk->thread_keyring = NULL;
+	old = tsk->sec->thread_keyring;
+	tsk->sec->thread_keyring = NULL;
 	task_unlock(tsk);
 
 	key_put(old);
@@ -361,10 +361,11 @@ int suid_keys(struct task_struct *tsk)
 void key_fsuid_changed(struct task_struct *tsk)
 {
 	/* update the ownership of the thread keyring */
-	if (tsk->thread_keyring) {
-		down_write(&tsk->thread_keyring->sem);
-		tsk->thread_keyring->uid = tsk->fsuid;
-		up_write(&tsk->thread_keyring->sem);
+	BUG_ON(!tsk->sec);
+	if (tsk->sec->thread_keyring) {
+		down_write(&tsk->sec->thread_keyring->sem);
+		tsk->sec->thread_keyring->uid = tsk->sec->fsuid;
+		up_write(&tsk->sec->thread_keyring->sem);
 	}
 
 } /* end key_fsuid_changed() */
@@ -376,10 +377,11 @@ void key_fsuid_changed(struct task_struct *tsk)
 void key_fsgid_changed(struct task_struct *tsk)
 {
 	/* update the ownership of the thread keyring */
-	if (tsk->thread_keyring) {
-		down_write(&tsk->thread_keyring->sem);
-		tsk->thread_keyring->gid = tsk->fsgid;
-		up_write(&tsk->thread_keyring->sem);
+	BUG_ON(!tsk->sec);
+	if (tsk->sec->thread_keyring) {
+		down_write(&tsk->sec->thread_keyring->sem);
+		tsk->sec->thread_keyring->gid = tsk->sec->fsgid;
+		up_write(&tsk->sec->thread_keyring->sem);
 	}
 
 } /* end key_fsgid_changed() */
@@ -414,9 +416,9 @@ key_ref_t search_process_keyrings(struct key_type *type,
 	err = ERR_PTR(-EAGAIN);
 
 	/* search the thread keyring first */
-	if (context->thread_keyring) {
+	if (context->sec->thread_keyring) {
 		key_ref = keyring_search_aux(
-			make_key_ref(context->thread_keyring, 1),
+			make_key_ref(context->sec->thread_keyring, 1),
 			context, type, description, match);
 		if (!IS_ERR(key_ref))
 			goto found;
@@ -483,7 +485,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
 	/* or search the user-session keyring */
 	else {
 		key_ref = keyring_search_aux(
-			make_key_ref(context->user->session_keyring, 1),
+			make_key_ref(context->sec->user->session_keyring, 1),
 			context, type, description, match);
 		if (!IS_ERR(key_ref))
 			goto found;
@@ -505,20 +507,20 @@ key_ref_t search_process_keyrings(struct key_type *type,
 	 * search the keyrings of the process mentioned there
 	 * - we don't permit access to request_key auth keys via this method
 	 */
-	if (context->request_key_auth &&
+	if (context->sec->request_key_auth &&
 	    context == current &&
 	    type != &key_type_request_key_auth
 	    ) {
 		/* defend against the auth key being revoked */
-		down_read(&context->request_key_auth->sem);
+		down_read(&context->sec->request_key_auth->sem);
 
-		if (key_validate(context->request_key_auth) == 0) {
-			rka = context->request_key_auth->payload.data;
+		if (key_validate(context->sec->request_key_auth) == 0) {
+			rka = context->sec->request_key_auth->payload.data;
 
 			key_ref = search_process_keyrings(type, description,
 							  match, rka->context);
 
-			up_read(&context->request_key_auth->sem);
+			up_read(&context->sec->request_key_auth->sem);
 
 			if (!IS_ERR(key_ref))
 				goto found;
@@ -535,7 +537,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
 				break;
 			}
 		} else {
-			up_read(&context->request_key_auth->sem);
+			up_read(&context->sec->request_key_auth->sem);
 		}
 	}
 
@@ -577,7 +579,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
 
 	switch (id) {
 	case KEY_SPEC_THREAD_KEYRING:
-		if (!context->thread_keyring) {
+		if (!context->sec->thread_keyring) {
 			if (!create)
 				goto error;
 
@@ -588,7 +590,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
 			}
 		}
 
-		key = context->thread_keyring;
+		key = context->sec->thread_keyring;
 		atomic_inc(&key->usage);
 		key_ref = make_key_ref(key, 1);
 		break;
@@ -615,7 +617,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
 			/* always install a session keyring upon access if one
 			 * doesn't exist yet */
 			ret = install_session_keyring(
-				context, context->user->session_keyring);
+				context, context->sec->user->session_keyring);
 			if (ret < 0)
 				goto error;
 		}
@@ -628,13 +630,13 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
 		break;
 
 	case KEY_SPEC_USER_KEYRING:
-		key = context->user->uid_keyring;
+		key = context->sec->user->uid_keyring;
 		atomic_inc(&key->usage);
 		key_ref = make_key_ref(key, 1);
 		break;
 
 	case KEY_SPEC_USER_SESSION_KEYRING:
-		key = context->user->session_keyring;
+		key = context->sec->user->session_keyring;
 		atomic_inc(&key->usage);
 		key_ref = make_key_ref(key, 1);
 		break;
@@ -645,7 +647,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
 		goto error;
 
 	case KEY_SPEC_REQKEY_AUTH_KEY:
-		key = context->request_key_auth;
+		key = context->sec->request_key_auth;
 		if (!key)
 			goto error;
 
@@ -747,7 +749,7 @@ long join_session_keyring(const char *name)
 	keyring = find_keyring_by_name(name, 0);
 	if (PTR_ERR(keyring) == -ENOKEY) {
 		/* not found - try and create a new one */
-		keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,
+		keyring = keyring_alloc(name, tsk->sec->uid, tsk->sec->gid, tsk,
 					KEY_ALLOC_IN_QUOTA, NULL);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 6d25911..54b03bb 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -76,7 +76,7 @@ static int call_sbin_request_key(struct key_construction *cons,
 	/* allocate a new session keyring */
 	sprintf(desc, "_req.%u", key->serial);
 
-	keyring = keyring_alloc(desc, current_fsuid(), current->fsgid, current,
+	keyring = keyring_alloc(desc, current_fsuid(), current_fsgid(), current,
 				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
@@ -97,7 +97,8 @@ static int call_sbin_request_key(struct key_construction *cons,
 
 	/* we specify the process's default keyrings */
 	sprintf(keyring_str[0], "%d",
-		tsk->thread_keyring ? tsk->thread_keyring->serial : 0);
+		tsk->act_as->thread_keyring ?
+		tsk->act_as->thread_keyring->serial : 0);
 
 	prkey = 0;
 	if (tsk->signal->process_keyring)
@@ -110,7 +111,7 @@ static int call_sbin_request_key(struct key_construction *cons,
 		sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
 		rcu_read_unlock();
 	} else {
-		sskey = tsk->user->session_keyring->serial;
+		sskey = tsk->act_as->user->session_keyring->serial;
 	}
 
 	sprintf(keyring_str[2], "%d", sskey);
@@ -216,10 +217,10 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring)
 
 	/* find the appropriate keyring */
 	if (!dest_keyring) {
-		switch (tsk->jit_keyring) {
+		switch (tsk->act_as->jit_keyring) {
 		case KEY_REQKEY_DEFL_DEFAULT:
 		case KEY_REQKEY_DEFL_THREAD_KEYRING:
-			dest_keyring = tsk->thread_keyring;
+			dest_keyring = tsk->act_as->thread_keyring;
 			if (dest_keyring)
 				break;
 
@@ -239,11 +240,11 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring)
 				break;
 
 		case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
-			dest_keyring = tsk->user->session_keyring;
+			dest_keyring = tsk->act_as->user->session_keyring;
 			break;
 
 		case KEY_REQKEY_DEFL_USER_KEYRING:
-			dest_keyring = tsk->user->uid_keyring;
+			dest_keyring = tsk->act_as->user->uid_keyring;
 			break;
 
 		case KEY_REQKEY_DEFL_GROUP_KEYRING:
@@ -278,7 +279,7 @@ static int construct_alloc_key(struct key_type *type,
 	mutex_lock(&user->cons_lock);
 
 	key = key_alloc(type, description,
-			current_fsuid(), current->fsgid, current, KEY_POS_ALL,
+			current_fsuid(), current_fsgid(), current, KEY_POS_ALL,
 			flags);
 	if (IS_ERR(key))
 		goto alloc_failed;
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index cce6b4d..9598670 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -162,22 +162,22 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 
 	/* see if the calling process is already servicing the key request of
 	 * another process */
-	if (current->request_key_auth) {
+	if (current->act_as->request_key_auth) {
 		/* it is - use that instantiation context here too */
-		down_read(&current->request_key_auth->sem);
+		down_read(&current->act_as->request_key_auth->sem);
 
 		/* if the auth key has been revoked, then the key we're
 		 * servicing is already instantiated */
 		if (test_bit(KEY_FLAG_REVOKED,
-			     &current->request_key_auth->flags))
+			     &current->act_as->request_key_auth->flags))
 			goto auth_key_revoked;
 
-		irka = current->request_key_auth->payload.data;
+		irka = current->act_as->request_key_auth->payload.data;
 		rka->context = irka->context;
 		rka->pid = irka->pid;
 		get_task_struct(rka->context);
 
-		up_read(&current->request_key_auth->sem);
+		up_read(&current->act_as->request_key_auth->sem);
 	}
 	else {
 		/* it isn't - use this process as the context */
@@ -194,7 +194,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 	sprintf(desc, "%x", target->serial);
 
 	authkey = key_alloc(&key_type_request_key_auth, desc,
-			    current_fsuid(), current->fsgid, current,
+			    current_fsuid(), current_fsgid(), current,
 			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
 			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
 	if (IS_ERR(authkey)) {
@@ -211,7 +211,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 	return authkey;
 
 auth_key_revoked:
-	up_read(&current->request_key_auth->sem);
+	up_read(&current->act_as->request_key_auth->sem);
 	kfree(rka->callout_info);
 	kfree(rka);
 	kleave("= -EKEYREVOKED");
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
index b6f9694..f660690 100644
--- a/security/selinux/exports.c
+++ b/security/selinux/exports.c
@@ -56,7 +56,7 @@ void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
 void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
 {
 	if (selinux_enabled) {
-		struct task_security_struct *tsec = tsk->security;
+		struct task_security_struct *tsec = tsk->sec->security;
 		*sid = tsec->sid;
 		return;
 	}
@@ -77,7 +77,7 @@ EXPORT_SYMBOL_GPL(selinux_string_to_sid);
 int selinux_relabel_packet_permission(u32 sid)
 {
 	if (selinux_enabled) {
-		struct task_security_struct *tsec = current->security;
+		struct task_security_struct *tsec = current->act_as->security;
 
 		return avc_has_perm(tsec->sid, sid, SECCLASS_PACKET,
 				    PACKET__RELABELTO, NULL);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index bd4cfab..e56529f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -165,21 +165,21 @@ static int task_alloc_security(struct task_struct *task)
 
 	tsec->task = task;
 	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
-	task->security = tsec;
+	task->sec->security = tsec;
 
 	return 0;
 }
 
 static void task_free_security(struct task_struct *task)
 {
-	struct task_security_struct *tsec = task->security;
-	task->security = NULL;
+	struct task_security_struct *tsec = task->sec->security;
+	task->sec->security = NULL;
 	kfree(tsec);
 }
 
 static int inode_alloc_security(struct inode *inode)
 {
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec = current->act_as->security;
 	struct inode_security_struct *isec;
 
 	isec = kmem_cache_zalloc(sel_inode_cache, GFP_KERNEL);
@@ -213,7 +213,7 @@ static void inode_free_security(struct inode *inode)
 
 static int file_alloc_security(struct file *file)
 {
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec = current->act_as->security;
 	struct file_security_struct *fsec;
 
 	fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
@@ -373,7 +373,7 @@ static int try_context_mount(struct super_block *sb, void *data)
 	const char *name;
 	u32 sid;
 	int alloc = 0, rc = 0, seen = 0;
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec = current->act_as->security;
 	struct superblock_security_struct *sbsec = sb->s_security;
 
 	if (!data)
@@ -1033,8 +1033,8 @@ static int task_has_perm(struct task_struct *tsk1,
 {
 	struct task_security_struct *tsec1, *tsec2;
 
-	tsec1 = tsk1->security;
-	tsec2 = tsk2->security;
+	tsec1 = tsk1->act_as->security;
+	tsec2 = tsk2->sec->security;
 	return avc_has_perm(tsec1->sid, tsec2->sid,
 			    SECCLASS_PROCESS, perms, NULL);
 }
@@ -1046,7 +1046,7 @@ static int task_has_capability(struct task_struct *tsk,
 	struct task_security_struct *tsec;
 	struct avc_audit_data ad;
 
-	tsec = tsk->security;
+	tsec = tsk->sec->security;
 
 	AVC_AUDIT_DATA_INIT(&ad,CAP);
 	ad.tsk = tsk;
@@ -1062,7 +1062,7 @@ static int task_has_system(struct task_struct *tsk,
 {
 	struct task_security_struct *tsec;
 
-	tsec = tsk->security;
+	tsec = tsk->sec->security;
 
 	return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
 			    SECCLASS_SYSTEM, perms, NULL);
@@ -1083,7 +1083,7 @@ static int inode_has_perm(struct task_struct *tsk,
 	if (unlikely (IS_PRIVATE (inode)))
 		return 0;
 
-	tsec = tsk->security;
+	tsec = tsk->sec->security;
 	isec = inode->i_security;
 
 	if (!adp) {
@@ -1123,7 +1123,7 @@ static int file_has_perm(struct task_struct *tsk,
 				struct file *file,
 				u32 av)
 {
-	struct task_security_struct *tsec = tsk->security;
+	struct task_security_struct *tsec = tsk->sec->security;
 	struct file_security_struct *fsec = file->f_security;
 	struct vfsmount *mnt = file->f_path.mnt;
 	struct dentry *dentry = file->f_path.dentry;
@@ -1163,7 +1163,7 @@ static int may_create(struct inode *dir,
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	dsec = dir->i_security;
 	sbsec = dir->i_sb->s_security;
 
@@ -1200,7 +1200,7 @@ static int may_create_key(u32 ksid,
 {
 	struct task_security_struct *tsec;
 
-	tsec = ctx->security;
+	tsec = ctx->sec->security;
 
 	return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
 }
@@ -1221,7 +1221,7 @@ static int may_link(struct inode *dir,
 	u32 av;
 	int rc;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	dsec = dir->i_security;
 	isec = dentry->d_inode->i_security;
 
@@ -1265,7 +1265,7 @@ static inline int may_rename(struct inode *old_dir,
 	int old_is_dir, new_is_dir;
 	int rc;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	old_dsec = old_dir->i_security;
 	old_isec = old_dentry->d_inode->i_security;
 	old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
@@ -1318,7 +1318,7 @@ static int superblock_has_perm(struct task_struct *tsk,
 	struct task_security_struct *tsec;
 	struct superblock_security_struct *sbsec;
 
-	tsec = tsk->security;
+	tsec = tsk->act_as->security;
 	sbsec = sb->s_security;
 	return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
 			    perms, ad);
@@ -1373,8 +1373,8 @@ static inline u32 file_to_av(struct file *file)
 
 static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
 {
-	struct task_security_struct *psec = parent->security;
-	struct task_security_struct *csec = child->security;
+	struct task_security_struct *psec = parent->act_as->security;
+	struct task_security_struct *csec = child->sec->security;
 	int rc;
 
 	rc = secondary_ops->ptrace(parent,child);
@@ -1482,7 +1482,7 @@ static int selinux_sysctl(ctl_table *table, int op)
 	if (rc)
 		return rc;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 
 	rc = selinux_sysctl_get_sid(table, (op == 0001) ?
 				    SECCLASS_DIR : SECCLASS_FILE, &tsid);
@@ -1591,7 +1591,7 @@ static int selinux_syslog(int type)
 static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
 {
 	int rc, cap_sys_admin = 0;
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec = current->act_as->security;
 
 	rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
 	if (rc == 0)
@@ -1644,7 +1644,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
 	if (bsec->set)
 		return 0;
 
-	tsec = current->security;
+	tsec = current->sec->security;
 	isec = inode->i_security;
 
 	/* Default to the current task SID. */
@@ -1710,7 +1710,7 @@ static int selinux_bprm_check_security (struct linux_binprm *bprm)
 
 static int selinux_bprm_secureexec (struct linux_binprm *bprm)
 {
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec = current->sec->security;
 	int atsecure = 0;
 
 	if (tsec->osid != tsec->sid) {
@@ -1833,7 +1833,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
 
 	secondary_ops->bprm_apply_creds(bprm, unsafe);
 
-	tsec = current->security;
+	tsec = current->sec->security;
 
 	bsec = bprm->security;
 	sid = bsec->sid;
@@ -1878,7 +1878,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
 	struct bprm_security_struct *bsec;
 	int rc, i;
 
-	tsec = current->security;
+	tsec = current->sec->security;
 	bsec = bprm->security;
 
 	if (bsec->unsafe) {
@@ -2133,7 +2133,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 	int rc;
 	char *namep = NULL, *context;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	dsec = dir->i_security;
 	sbsec = dir->i_sb->s_security;
 
@@ -2318,7 +2318,7 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
 
 static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
 {
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec = current->act_as->security;
 	struct inode *inode = dentry->d_inode;
 	struct inode_security_struct *isec = inode->i_security;
 	struct superblock_security_struct *sbsec;
@@ -2492,7 +2492,7 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
 static int selinux_file_permission(struct file *file, int mask)
 {
 	struct inode *inode = file->f_path.dentry->d_inode;
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec = current->act_as->security;
 	struct file_security_struct *fsec = file->f_security;
 	struct inode_security_struct *isec = inode->i_security;
 
@@ -2600,7 +2600,8 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
 			     unsigned long addr, unsigned long addr_only)
 {
 	int rc = 0;
-	u32 sid = ((struct task_security_struct*)(current->security))->sid;
+	u32 sid = ((struct task_security_struct *)
+		   (current->act_as->security))->sid;
 
 	if (addr < mmap_min_addr)
 		rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
@@ -2712,7 +2713,7 @@ static int selinux_file_set_fowner(struct file *file)
 	struct task_security_struct *tsec;
 	struct file_security_struct *fsec;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	fsec = file->f_security;
 	fsec->fown_sid = tsec->sid;
 
@@ -2730,7 +2731,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
 	/* struct fown_struct is never outside the context of a struct file */
         file = container_of(fown, struct file, f_owner);
 
-	tsec = tsk->security;
+	tsec = tsk->sec->security;
 	fsec = file->f_security;
 
 	if (!signum)
@@ -2793,12 +2794,12 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
 	struct task_security_struct *tsec1, *tsec2;
 	int rc;
 
-	tsec1 = current->security;
+	tsec1 = current->act_as->security;
 
 	rc = task_alloc_security(tsk);
 	if (rc)
 		return rc;
-	tsec2 = tsk->security;
+	tsec2 = tsk->sec->security;
 
 	tsec2->osid = tsec1->osid;
 	tsec2->sid = tsec1->sid;
@@ -2955,7 +2956,7 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
 		perm = PROCESS__SIGNULL; /* null signal; existence test */
 	else
 		perm = signal_to_av(sig);
-	tsec = p->security;
+	tsec = p->sec->security;
 	if (secid)
 		rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
 	else
@@ -2986,7 +2987,7 @@ static void selinux_task_reparent_to_init(struct task_struct *p)
 
 	secondary_ops->task_reparent_to_init(p);
 
-	tsec = p->security;
+	tsec = p->sec->security;
 	tsec->osid = tsec->sid;
 	tsec->sid = SECINITSID_KERNEL;
 	return;
@@ -2995,7 +2996,7 @@ static void selinux_task_reparent_to_init(struct task_struct *p)
 static void selinux_task_to_inode(struct task_struct *p,
 				  struct inode *inode)
 {
-	struct task_security_struct *tsec = p->security;
+	struct task_security_struct *tsec = p->sec->security;
 	struct inode_security_struct *isec = inode->i_security;
 
 	isec->sid = tsec->sid;
@@ -3227,7 +3228,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
 	struct avc_audit_data ad;
 	int err = 0;
 
-	tsec = task->security;
+	tsec = task->act_as->security;
 	isec = SOCK_INODE(sock)->i_security;
 
 	if (isec->sid == SECINITSID_KERNEL)
@@ -3251,7 +3252,7 @@ static int selinux_socket_create(int family, int type,
 	if (kern)
 		goto out;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	newsid = tsec->sockcreate_sid ? : tsec->sid;
 	err = avc_has_perm(tsec->sid, newsid,
 			   socket_type_to_security_class(family, type,
@@ -3272,7 +3273,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
 
 	isec = SOCK_INODE(sock)->i_security;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	newsid = tsec->sockcreate_sid ? : tsec->sid;
 	isec->sclass = socket_type_to_security_class(family, type, protocol);
 	isec->sid = kern ? SECINITSID_KERNEL : newsid;
@@ -3317,7 +3318,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 		struct sock *sk = sock->sk;
 		u32 sid, node_perm, addrlen;
 
-		tsec = current->security;
+		tsec = current->act_as->security;
 		isec = SOCK_INODE(sock)->i_security;
 
 		if (family == PF_INET) {
@@ -4091,7 +4092,7 @@ static int ipc_alloc_security(struct task_struct *task,
 			      struct kern_ipc_perm *perm,
 			      u16 sclass)
 {
-	struct task_security_struct *tsec = task->security;
+	struct task_security_struct *tsec = task->act_as->security;
 	struct ipc_security_struct *isec;
 
 	isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
@@ -4143,7 +4144,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	isec = ipc_perms->security;
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
@@ -4174,7 +4175,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
 	if (rc)
 		return rc;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	isec = msq->q_perm.security;
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
@@ -4200,7 +4201,7 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	isec = msq->q_perm.security;
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
@@ -4246,7 +4247,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	isec = msq->q_perm.security;
 	msec = msg->security;
 
@@ -4294,7 +4295,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = target->security;
+	tsec = target->act_as->security;
 	isec = msq->q_perm.security;
 	msec = msg->security;
 
@@ -4321,7 +4322,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
 	if (rc)
 		return rc;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	isec = shp->shm_perm.security;
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
@@ -4347,7 +4348,7 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	isec = shp->shm_perm.security;
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
@@ -4420,7 +4421,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
 	if (rc)
 		return rc;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	isec = sma->sem_perm.security;
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
@@ -4446,7 +4447,7 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = current->security;
+	tsec = current->act_as->security;
 	isec = sma->sem_perm.security;
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
@@ -4565,7 +4566,7 @@ static int selinux_getprocattr(struct task_struct *p,
 			return error;
 	}
 
-	tsec = p->security;
+	tsec = p->sec->security;
 
 	if (!strcmp(name, "current"))
 		sid = tsec->sid;
@@ -4642,7 +4643,7 @@ static int selinux_setprocattr(struct task_struct *p,
 	   operation.  See selinux_bprm_set_security for the execve
 	   checks and may_create for the file creation checks. The
 	   operation will then fail if the context is not permitted. */
-	tsec = p->security;
+	tsec = p->sec->security;
 	if (!strcmp(name, "exec"))
 		tsec->exec_sid = sid;
 	else if (!strcmp(name, "fscreate"))
@@ -4720,7 +4721,7 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
 static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
 			     unsigned long flags)
 {
-	struct task_security_struct *tsec = tsk->security;
+	struct task_security_struct *tsec = tsk->sec->security;
 	struct key_security_struct *ksec;
 
 	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
@@ -4755,7 +4756,7 @@ static int selinux_key_permission(key_ref_t key_ref,
 
 	key = key_ref_to_ptr(key_ref);
 
-	tsec = ctx->security;
+	tsec = ctx->sec->security;
 	ksec = key->security;
 
 	/* if no specific permissions are requested, we skip the
@@ -4978,7 +4979,7 @@ static __init int selinux_init(void)
 	/* Set the security state for the initial task. */
 	if (task_alloc_security(current))
 		panic("SELinux:  Failed to initialize initial task.\n");
-	tsec = current->security;
+	tsec = current->sec->security;
 	tsec->osid = tsec->sid = SECINITSID_KERNEL;
 
 	sel_inode_cache = kmem_cache_create("selinux_inode_security",
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index f5f3e6d..ee7d535 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -79,7 +79,7 @@ static int task_has_security(struct task_struct *tsk,
 {
 	struct task_security_struct *tsec;
 
-	tsec = tsk->security;
+	tsec = tsk->act_as->security;
 	if (!tsec)
 		return -EACCES;
 


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

* [PATCH 7/7] SECURITY: De-embed task security record from task and use refcounting
  2007-12-05 19:37 [PATCH 0/7] Permit filesystem local caching David Howells
                   ` (5 preceding siblings ...)
  2007-12-05 19:37 ` [PATCH 6/7] SECURITY: Separate task security context from task_struct David Howells
@ 2007-12-05 19:37 ` David Howells
  6 siblings, 0 replies; 14+ messages in thread
From: David Howells @ 2007-12-05 19:37 UTC (permalink / raw)
  To: viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells

Remove the temporarily embedded task security record from task_struct.  Instead
it is made to dangle from the task_struct::sec and task_struct::act_as pointers
with references counted for each.

do_coredump() is made to create a copy of the security record, modify it and
then use that to override the main one for a task.  sys_faccessat() is made to
do the same.

The process and session keyrings are moved from signal_struct into a new
thread_group_security struct.  This is then refcounted, with pointers coming
from the task_security struct instead of from signal_struct.

The keyring functions then take pointers to task_security structs rather than
task_structs for their security contexts.  This is so that request_key() can
proceed asynchronously without having to worry about the initiator task's
act_as pointer changing.

The LSM hooks for dealing with task security are modified to deal with the task
security struct directly rather than going via the task_struct as appopriate.

This permits the subjective security context of a task to be overridden by
changing its act_as pointer without altering its objective security pointer,
and thus not breaking signalling, ptrace, etc. whilst the override is in force.

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

 fs/exec.c                        |   15 +-
 fs/open.c                        |   37 ++---
 include/linux/init_task.h        |   17 --
 include/linux/key-ui.h           |   10 +
 include/linux/key.h              |   31 +---
 include/linux/sched.h            |   40 ++++-
 include/linux/security.h         |   43 ++++--
 kernel/Makefile                  |    2 
 kernel/cred.c                    |  139 ++++++++++++++++++
 kernel/exit.c                    |    1 
 kernel/fork.c                    |   40 ++---
 kernel/kmod.c                    |   10 +
 kernel/sys.c                     |   16 +-
 kernel/user.c                    |    2 
 net/rxrpc/ar-key.c               |    4 -
 security/dummy.c                 |   14 +-
 security/keys/internal.h         |   10 +
 security/keys/key.c              |    6 -
 security/keys/keyctl.c           |    6 -
 security/keys/keyring.c          |   14 +-
 security/keys/permission.c       |    5 -
 security/keys/proc.c             |    2 
 security/keys/process_keys.c     |  290 +++++++++++++++++---------------------
 security/keys/request_key.c      |   59 ++++----
 security/keys/request_key_auth.c |   38 ++---
 security/security.c              |   20 ++-
 security/selinux/hooks.c         |   46 +++++-
 27 files changed, 526 insertions(+), 391 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index da01655..f10e3fd 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1674,13 +1674,13 @@ int get_dumpable(struct mm_struct *mm)
 
 int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 {
+	struct task_security *sec, *old_act_as;
 	char corename[CORENAME_MAX_SIZE + 1];
 	struct mm_struct *mm = current->mm;
 	struct linux_binfmt * binfmt;
 	struct inode * inode;
 	struct file * file;
 	int retval = 0;
-	int fsuid = current_fsuid();
 	int flag = 0;
 	int ispipe = 0;
 	unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
@@ -1692,7 +1692,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
-		goto fail;
+		goto fail_nosubj;
+	sec = dup_task_security(current->sec);
+	if (!sec)
+		goto fail_nosubj;
 	down_write(&mm->mmap_sem);
 	/*
 	 * If another thread got here first, or we are not dumpable, bail out.
@@ -1707,9 +1710,11 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	 *	process nor do we know its entire history. We only know it
 	 *	was tainted so we dump it as root in mode 2.
 	 */
+	old_act_as = current->act_as;
 	if (get_dumpable(mm) == 2) {	/* Setuid core dump mode */
 		flag = O_EXCL;		/* Stop rewrite attacks */
-		current->act_as->fsuid = 0;	/* Dump root private */
+		sec->fsuid = 0;		/* Dump root private */
+		current->act_as = sec;
 	}
 
 	retval = coredump_wait(exit_code);
@@ -1805,8 +1810,10 @@ fail_unlock:
 	if (helper_argv)
 		argv_free(helper_argv);
 
-	current->act_as->fsuid = fsuid;
+	current->act_as = old_act_as;
 	complete_all(&mm->core_done);
 fail:
+	put_task_security(sec);
+fail_nosubj:
 	return retval;
 }
diff --git a/fs/open.c b/fs/open.c
index 6d7a29c..710102a 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -420,34 +420,27 @@ out:
  */
 asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 {
+	struct task_security *sec, *old_act_as;
 	struct nameidata nd;
-	int old_fsuid, old_fsgid;
-	kernel_cap_t old_cap;
 	int res;
 
 	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
 		return -EINVAL;
 
-	old_fsuid = current->act_as->fsuid;
-	old_fsgid = current->act_as->fsgid;
-	old_cap = current->act_as->cap_effective;
+	sec = dup_task_security(current->sec);
+	if (!sec)
+		return -ENOMEM;
+	sec->fsuid = current->sec->uid;
+	sec->fsgid = current->sec->gid;
 
-	current->act_as->fsuid = current->act_as->uid;
-	current->act_as->fsgid = current->act_as->gid;
-
-	/*
-	 * Clear the capabilities if we switch to a non-root user
-	 *
-	 * FIXME: There is a race here against sys_capset.  The
-	 * capabilities can change yet we will restore the old
-	 * value below.  We should hold task_capabilities_lock,
-	 * but we cannot because user_path_walk can sleep.
-	 */
-	if (current->act_as->uid)
-		cap_clear(current->act_as->cap_effective);
+	/* Clear the capabilities if we switch to a non-root user */
+	if (current->sec->uid)
+		cap_clear(sec->cap_effective);
 	else
-		current->act_as->cap_effective = current->act_as->cap_permitted;
+		sec->cap_effective = current->sec->cap_permitted;
 
+	old_act_as = current->act_as;
+	current->act_as = sec;
 	res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
 	if (res)
 		goto out;
@@ -464,10 +457,8 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 out_path_release:
 	path_release(&nd);
 out:
-	current->act_as->fsuid = old_fsuid;
-	current->act_as->fsgid = old_fsgid;
-	current->act_as->cap_effective = old_cap;
-
+	current->act_as = old_act_as;
+	put_task_security(sec);
 	return res;
 }
 
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 6fa8413..380cc6a 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -116,18 +116,6 @@ extern struct group_info init_groups;
 
 extern struct task_security init_task_security;
 
-#define INIT_TASK_SECURITY(p)					\
-{								\
-	.usage			= ATOMIC_INIT(3),		\
-	.keep_capabilities	= 0,				\
-	.cap_inheritable	= CAP_INIT_INH_SET,		\
-	.cap_permitted		= CAP_FULL_SET,			\
-	.cap_effective		= CAP_INIT_EFF_SET,		\
-	.user			= INIT_USER,			\
-	.group_info		= &init_groups,			\
-	.lock			= __SPIN_LOCK_UNLOCKED(p.lock),	\
-}
-
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -157,9 +145,8 @@ extern struct task_security init_task_security;
 	.children	= LIST_HEAD_INIT(tsk.children),			\
 	.sibling	= LIST_HEAD_INIT(tsk.sibling),			\
 	.group_leader	= &tsk,						\
-	.__temp_sec	= INIT_TASK_SECURITY(tsk.__temp_sec),		\
-	.sec		= &tsk.__temp_sec,				\
-	.act_as		= &tsk.__temp_sec,				\
+	.sec		= &init_task_security,				\
+	.act_as		= &init_task_security,				\
 	.comm		= "swapper",					\
 	.thread		= INIT_THREAD,					\
 	.fs		= &init_fs,					\
diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h
index e8b8a7a..f15ea9d 100644
--- a/include/linux/key-ui.h
+++ b/include/linux/key-ui.h
@@ -43,15 +43,13 @@ struct keyring_list {
  * check to see whether permission is granted to use a key in the desired way
  */
 extern int key_task_permission(const key_ref_t key_ref,
-			       struct task_struct *context,
+			       struct task_security *sec,
 			       key_perm_t perm);
 
-static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
-{
-	return key_task_permission(key_ref, current, perm);
-}
+#define key_permission(key_ref, perm) \
+	key_task_permission((key_ref), current->act_as, (perm))
 
-extern key_ref_t lookup_user_key(struct task_struct *context,
+extern key_ref_t lookup_user_key(struct task_security *sec,
 				 key_serial_t id, int create, int partial,
 				 key_perm_t perm);
 
diff --git a/include/linux/key.h b/include/linux/key.h
index 4a6021a..f5edd89 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -70,6 +70,8 @@ struct key;
 struct seq_file;
 struct user_struct;
 struct signal_struct;
+struct task_security;
+struct thread_group_security;
 
 struct key_type;
 struct key_owner;
@@ -178,7 +180,7 @@ struct key {
 extern struct key *key_alloc(struct key_type *type,
 			     const char *desc,
 			     uid_t uid, gid_t gid,
-			     struct task_struct *ctx,
+			     struct task_security *sec,
 			     key_perm_t perm,
 			     unsigned long flags);
 
@@ -245,7 +247,7 @@ extern int key_unlink(struct key *keyring,
 		      struct key *key);
 
 extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
-				 struct task_struct *ctx,
+				 struct task_security *sec,
 				 unsigned long flags,
 				 struct key *dest);
 
@@ -267,24 +269,16 @@ extern struct key *key_lookup(key_serial_t id);
  */
 extern struct key root_user_keyring, root_session_keyring;
 extern int alloc_uid_keyring(struct user_struct *user,
-			     struct task_struct *ctx);
+			     struct task_security *sec);
 extern void switch_uid_keyring(struct user_struct *new_user);
-extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk);
-extern int copy_thread_group_keys(struct task_struct *tsk);
-extern void exit_keys(struct task_struct *tsk);
-extern void exit_thread_group_keys(struct signal_struct *tg);
+extern int copy_thread_group_keys(struct thread_group_security *tgsec);
 extern int suid_keys(struct task_struct *tsk);
 extern int exec_keys(struct task_struct *tsk);
-extern void key_fsuid_changed(struct task_struct *tsk);
-extern void key_fsgid_changed(struct task_struct *tsk);
+extern void key_fsuid_changed(struct task_security *sec);
+extern void key_fsgid_changed(struct task_security *sec);
 extern void key_init(void);
-
-#define __install_session_keyring(tsk, keyring)			\
-({								\
-	struct key *old_session = tsk->signal->session_keyring;	\
-	tsk->signal->session_keyring = keyring;			\
-	old_session;						\
-})
+extern void __install_session_keyring(struct task_struct *tsk,
+				      struct key *keyring);
 
 #else /* CONFIG_KEYS */
 
@@ -298,11 +292,8 @@ extern void key_init(void);
 #define is_key_possessed(k)		0
 #define alloc_uid_keyring(u,c)		0
 #define switch_uid_keyring(u)		do { } while(0)
-#define __install_session_keyring(t, k)	({ NULL; })
-#define copy_keys(f,t)			0
+#define __install_session_keyring(t, k)	do {} while (0)
 #define copy_thread_group_keys(t)	0
-#define exit_keys(t)			do { } while(0)
-#define exit_thread_group_keys(tg)	do { } while(0)
 #define suid_keys(t)			do { } while(0)
 #define exec_keys(t)			do { } while(0)
 #define key_fsuid_changed(t)		do { } while(0)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index bcd785a..f6df115 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -491,12 +491,6 @@ struct signal_struct {
 
 	struct list_head cpu_timers[3];
 
-	/* keep the process-shared keyrings here so that they do the right
-	 * thing in threads created with CLONE_THREAD */
-#ifdef CONFIG_KEYS
-	struct key *session_keyring;	/* keyring inherited over fork */
-	struct key *process_keyring;	/* keyring private to this process */
-#endif
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	struct pacct_struct pacct;	/* per-process accounting information */
 #endif
@@ -572,6 +566,20 @@ extern struct user_struct root_user;
 
 
 /*
+ * The common security details for a thread group
+ * - shared by CLONE_THREAD
+ */
+#ifdef CONFIG_KEYS
+struct thread_group_security {
+	atomic_t	usage;
+	pid_t		tgid;			/* thread group process ID */
+	spinlock_t	lock;
+	struct key	*session_keyring;	/* keyring inherited over fork */
+	struct key	*process_keyring;	/* keyring private to this process */
+};
+#endif
+
+/*
  * The security context of a task
  *
  * The parts of the context break down into two categories:
@@ -613,6 +621,7 @@ struct task_security {
 					 * keys to */
 	struct key	*thread_keyring; /* keyring private to this thread */
 	struct key	*request_key_auth; /* assumed request_key authority */
+	struct thread_group_security *tgsec;
 #endif
 #ifdef CONFIG_SECURITY
 	void		*security;	/* subjective LSM security */
@@ -622,10 +631,28 @@ struct task_security {
 	spinlock_t	lock;		/* lock for pointer changes */
 };
 
+extern struct task_security *dup_task_security(struct task_security *);
+extern int copy_task_security(struct task_struct *, unsigned long);
+extern void put_task_security(struct task_security *);
+
 #define current_fsuid() (current->act_as->fsuid)
 #define current_fsgid() (current->act_as->fsgid)
 #define current_cap()	(current->act_as->cap_effective)
 
+/**
+ * get_task_security - Get an extra reference on a task security record
+ * @sec: The security record to get the reference on
+ *
+ * Get an extra reference on a task security record.  The caller must arrange
+ * for this to be released.
+ */
+static inline
+struct task_security *get_task_security(struct task_security *sec)
+{
+	atomic_inc(&sec->usage);
+	return sec;
+}
+
 
 struct backing_dev_info;
 struct reclaim_state;
@@ -1082,7 +1109,6 @@ struct task_struct {
 	struct list_head cpu_timers[3];
 
 /* process credentials */
-	struct task_security __temp_sec __deprecated; /* temporary security to be removed */
 	struct task_security *sec;	/* actual/objective task security */
 	struct task_security *act_as;	/* effective/subjective task security */
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 8d9e946..b7ba073 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -550,8 +550,13 @@ struct request_sock;
  *	allocated.
  *	Return 0 if operation was successful.
  * @task_free_security:
- *	@p contains the task_struct for process.
+ *	@p points to the task_security struct to be freed.
  *	Deallocate and clear the p->security field.
+ * @task_dup_security:
+ *	@p points to the task_security struct to be copied
+ *	Duplicate and attach the security structure currently attached to the
+ *	p->security field.
+ *	Return 0 if operation was successful.
  * @task_setuid:
  *	Check permission before setting one or more of the user identity
  *	attributes of the current process.  The @flags parameter indicates
@@ -944,6 +949,7 @@ struct request_sock;
  *	Permit allocation of a key and assign security data. Note that key does
  *	not have a serial number assigned at this point.
  *	@key points to the key.
+ *	@sec points to the task security record to use.
  *	@flags is the allocation flags
  *	Return 0 if permission is granted, -ve error otherwise.
  * @key_free:
@@ -954,8 +960,8 @@ struct request_sock;
  *	See whether a specific operational right is granted to a process on a
  *      key.
  *	@key_ref refers to the key (key pointer + possession attribute bit).
- *	@context points to the process to provide the context against which to
- *       evaluate the security data on the key.
+ *	@sec points to the process's security recored to provide the context
+ *       against which to evaluate the security data on the key.
  *	@perm describes the combination of permissions required of this key.
  *	Return 1 if permission granted, 0 if permission denied and -ve it the
  *      normal permissions model should be effected.
@@ -1312,8 +1318,9 @@ struct security_operations {
 	int (*dentry_open)  (struct file *file);
 
 	int (*task_create) (unsigned long clone_flags);
-	int (*task_alloc_security) (struct task_struct * p);
-	void (*task_free_security) (struct task_struct * p);
+	int (*task_alloc_security) (struct task_struct *p);
+	void (*task_free_security) (struct task_security *p);
+	int (*task_dup_security) (struct task_security *p);
 	int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags);
 	int (*task_post_setuid) (uid_t old_ruid /* or fsuid */ ,
 				 uid_t old_euid, uid_t old_suid, int flags);
@@ -1443,10 +1450,11 @@ struct security_operations {
 
 	/* key management security hooks */
 #ifdef CONFIG_KEYS
-	int (*key_alloc)(struct key *key, struct task_struct *tsk, unsigned long flags);
+	int (*key_alloc)(struct key *key, struct task_security *context,
+			 unsigned long flags);
 	void (*key_free)(struct key *key);
 	int (*key_permission)(key_ref_t key_ref,
-			      struct task_struct *context,
+			      struct task_security *context,
 			      key_perm_t perm);
 	int (*key_getsecurity)(struct key *key, char **_buffer);
 #endif	/* CONFIG_KEYS */
@@ -1561,7 +1569,8 @@ int security_file_receive(struct file *file);
 int security_dentry_open(struct file *file);
 int security_task_create(unsigned long clone_flags);
 int security_task_alloc(struct task_struct *p);
-void security_task_free(struct task_struct *p);
+void security_task_free(struct task_security *p);
+int security_task_dup(struct task_security *p);
 int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags);
 int security_task_post_setuid(uid_t old_ruid, uid_t old_euid,
 			       uid_t old_suid, int flags);
@@ -2032,14 +2041,19 @@ static inline int security_task_create (unsigned long clone_flags)
 	return 0;
 }
 
-static inline int security_task_alloc (struct task_struct *p)
+static inline int security_task_alloc(struct task_struct *p)
 {
 	return 0;
 }
 
-static inline void security_task_free (struct task_struct *p)
+static inline void security_task_free(struct task_security *p)
 { }
 
+static inline int security_task_dup(struct task_security *p)
+{
+	return 0;
+}
+
 static inline int security_task_setuid (uid_t id0, uid_t id1, uid_t id2,
 					int flags)
 {
@@ -2574,16 +2588,17 @@ static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi
 #ifdef CONFIG_KEYS
 #ifdef CONFIG_SECURITY
 
-int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long flags);
+int security_key_alloc(struct key *key, struct task_security *sec,
+		       unsigned long flags);
 void security_key_free(struct key *key);
 int security_key_permission(key_ref_t key_ref,
-			    struct task_struct *context, key_perm_t perm);
+			    struct task_security *sec, key_perm_t perm);
 int security_key_getsecurity(struct key *key, char **_buffer);
 
 #else
 
 static inline int security_key_alloc(struct key *key,
-				     struct task_struct *tsk,
+				     struct task_security *sec,
 				     unsigned long flags)
 {
 	return 0;
@@ -2594,7 +2609,7 @@ static inline void security_key_free(struct key *key)
 }
 
 static inline int security_key_permission(key_ref_t key_ref,
-					  struct task_struct *context,
+					  struct task_security *sec,
 					  key_perm_t perm)
 {
 	return 0;
diff --git a/kernel/Makefile b/kernel/Makefile
index dfa9695..eb2af05 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -9,7 +9,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
 	    rcupdate.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o \
-	    utsname.o notifier.o
+	    utsname.o notifier.o cred.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_check.o
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/kernel/cred.c b/kernel/cred.c
new file mode 100644
index 0000000..ddf98c6
--- /dev/null
+++ b/kernel/cred.c
@@ -0,0 +1,139 @@
+/* Tasks security and credentials management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/key.h>
+#include <linux/init_task.h>
+#include <linux/security.h>
+
+#ifdef CONFIG_KEYS
+static struct thread_group_security init_thread_group_security = {
+	.usage	= ATOMIC_INIT(2),
+	.lock	= __SPIN_LOCK_UNLOCKED(init_thread_group_security.lock),
+};
+#endif
+
+struct task_security init_task_security = {
+	.usage			= ATOMIC_INIT(3),
+	.keep_capabilities	= 0,
+	.cap_inheritable	= CAP_INIT_INH_SET,
+	.cap_permitted		= CAP_FULL_SET,
+	.cap_effective		= CAP_INIT_EFF_SET,
+	.user			= INIT_USER,
+#ifdef CONFIG_KEYS
+	.tgsec			= &init_thread_group_security,
+#endif
+	.group_info		= &init_groups,
+	.lock			= __SPIN_LOCK_UNLOCKED(init_task_security.lock),
+};
+
+/**
+ * dup_task_security - Duplicate task security record
+ * @sec: The record to duplicate
+ *
+ * Returns a duplicate of a task security record or NULL if out of memory.
+ */
+struct task_security *dup_task_security(struct task_security *_sec)
+{
+	struct task_security *sec;
+
+	sec = kmemdup(_sec, sizeof(*sec), GFP_KERNEL);
+	if (sec) {
+		atomic_set(&sec->usage, 1);
+		get_uid(sec->user);
+		get_group_info(sec->group_info);
+		key_get(sec->thread_keyring);
+		key_get(sec->request_key_auth);
+		security_task_dup(sec);
+	}
+	return sec;
+}
+EXPORT_SYMBOL(dup_task_security);
+
+/**
+ * copy_task_security - Copy the task security records for fork
+ * @p: The new task
+ * @clone_flags: The details of what the new process shares of the old
+ *
+ * Copy the task security records on a task so that it can affect objects
+ * in the same way as its parent.  Returns 0 if successful or -ENOMEM if out of
+ * memory.
+ */
+int copy_task_security(struct task_struct *p, unsigned long clone_flags)
+{
+	struct task_security *sec;
+
+	sec = kmemdup(p->sec, sizeof(*sec), GFP_KERNEL);
+	if (!sec)
+		return -ENOMEM;
+
+	atomic_set(&sec->usage, 2);
+	spin_lock_init(&sec->lock);
+	get_group_info(sec->group_info);
+	get_uid(p->sec->user);
+
+#ifdef CONFIG_KEYS
+	if (clone_flags & CLONE_THREAD) {
+		atomic_inc(&sec->tgsec->usage);
+	} else {
+		struct thread_group_security *tgsec;
+
+		tgsec = kmalloc(sizeof(*tgsec), GFP_KERNEL);
+		if (!tgsec) {
+			kfree(sec);
+			return -ENOMEM;
+		}
+		atomic_set(&tgsec->usage, 1);
+		spin_lock_init(&tgsec->lock);
+		tgsec->tgid = p->tgid;
+		copy_thread_group_keys(tgsec);
+		sec->tgsec = tgsec;
+	}
+	key_get(sec->request_key_auth);
+	sec->thread_keyring = NULL;
+#endif
+
+#ifdef CONFIG_SECURITY
+	sec->security = NULL;
+#endif
+
+	p->act_as = p->sec = sec;
+	return 0;
+}
+EXPORT_SYMBOL(copy_task_security);
+
+/**
+ * put_task_security - Release a ref on a task security record
+ * @sec: The record to release
+ *
+ * Release a reference to a task security record and destroy it when
+ * there are no references remaining.
+ */
+void put_task_security(struct task_security *sec)
+{
+	if (sec && atomic_dec_and_test(&sec->usage)) {
+		security_task_free(sec);
+		key_put(sec->thread_keyring);
+		key_put(sec->request_key_auth);
+		put_group_info(sec->group_info);
+		free_uid(sec->user);
+
+#ifdef CONFIG_KEYS
+		if (atomic_dec_and_test(&sec->tgsec->usage)) {
+			key_put(sec->tgsec->session_keyring);
+			key_put(sec->tgsec->process_keyring);
+		}
+#endif
+
+		kfree(sec);
+	}
+}
+EXPORT_SYMBOL(put_task_security);
diff --git a/kernel/exit.c b/kernel/exit.c
index d793e22..507b54b 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1000,7 +1000,6 @@ fastcall NORET_TYPE void do_exit(long code)
 	check_stack_usage();
 	exit_thread();
 	cgroup_exit(tsk, 1);
-	exit_keys(tsk);
 
 	if (group_dead && tsk->signal->leader)
 		disassociate_ctty(1);
diff --git a/kernel/fork.c b/kernel/fork.c
index 2f267bd..e4572b0 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -121,9 +121,8 @@ void __put_task_struct(struct task_struct *tsk)
 	WARN_ON(atomic_read(&tsk->usage));
 	WARN_ON(tsk == current);
 
-	security_task_free(tsk);
-	free_uid(tsk->__temp_sec.user);
-	put_group_info(tsk->__temp_sec.group_info);
+	put_task_security(tsk->sec);
+	put_task_security(tsk->act_as);
 	delayacct_tsk_free(tsk);
 
 	if (!profile_handoff_task(tsk))
@@ -845,7 +844,6 @@ void __cleanup_sighand(struct sighand_struct *sighand)
 static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 {
 	struct signal_struct *sig;
-	int ret;
 
 	if (clone_flags & CLONE_THREAD) {
 		atomic_inc(&current->signal->count);
@@ -857,12 +855,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 	if (!sig)
 		return -ENOMEM;
 
-	ret = copy_thread_group_keys(tsk);
-	if (ret < 0) {
-		kmem_cache_free(signal_cachep, sig);
-		return ret;
-	}
-
 	atomic_set(&sig->count, 1);
 	atomic_set(&sig->live, 1);
 	init_waitqueue_head(&sig->wait_chldexit);
@@ -920,7 +912,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 
 void __cleanup_signal(struct signal_struct *sig)
 {
-	exit_thread_group_keys(sig);
 	kmem_cache_free(signal_cachep, sig);
 }
 
@@ -1014,18 +1005,19 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
 	DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
 #endif
-	p->act_as = p->sec = &p->__temp_sec;
+	retval = copy_task_security(p, clone_flags);
+	if (retval < 0)
+		goto bad_fork_free;
+
 	retval = -EAGAIN;
 	if (atomic_read(&p->sec->user->processes) >=
 			p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
 		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
 		    p->sec->user != current->nsproxy->user_ns->root_user)
-			goto bad_fork_free;
+			goto bad_fork_cleanup_put_task_sec;
 	}
 
-	atomic_inc(&p->sec->user->__count);
 	atomic_inc(&p->sec->user->processes);
-	get_group_info(p->sec->group_info);
 
 	/*
 	 * If multiple threads are within copy_process(), then this check
@@ -1080,9 +1072,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	do_posix_clock_monotonic_gettime(&p->start_time);
 	p->real_start_time = p->start_time;
 	monotonic_to_bootbased(&p->real_start_time);
-#ifdef CONFIG_SECURITY
-	p->sec->security = NULL;
-#endif
 	p->io_context = NULL;
 	p->audit_context = NULL;
 	cgroup_fork(p);
@@ -1130,7 +1119,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	if ((retval = security_task_alloc(p)))
 		goto bad_fork_cleanup_policy;
 	if ((retval = audit_alloc(p)))
-		goto bad_fork_cleanup_security;
+		goto bad_fork_cleanup_policy;
 	/* copy all the process information */
 	if ((retval = copy_semundo(clone_flags, p)))
 		goto bad_fork_cleanup_audit;
@@ -1144,10 +1133,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 		goto bad_fork_cleanup_sighand;
 	if ((retval = copy_mm(clone_flags, p)))
 		goto bad_fork_cleanup_signal;
-	if ((retval = copy_keys(clone_flags, p)))
-		goto bad_fork_cleanup_mm;
 	if ((retval = copy_namespaces(clone_flags, p)))
-		goto bad_fork_cleanup_keys;
+		goto bad_fork_cleanup_mm;
 	retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
 	if (retval)
 		goto bad_fork_cleanup_namespaces;
@@ -1329,8 +1316,6 @@ bad_fork_free_pid:
 		free_pid(pid);
 bad_fork_cleanup_namespaces:
 	exit_task_namespaces(p);
-bad_fork_cleanup_keys:
-	exit_keys(p);
 bad_fork_cleanup_mm:
 	if (p->mm)
 		mmput(p->mm);
@@ -1346,8 +1331,6 @@ bad_fork_cleanup_semundo:
 	exit_sem(p);
 bad_fork_cleanup_audit:
 	audit_free(p);
-bad_fork_cleanup_security:
-	security_task_free(p);
 bad_fork_cleanup_policy:
 #ifdef CONFIG_NUMA
 	mpol_free(p->mempolicy);
@@ -1360,9 +1343,10 @@ bad_fork_cleanup_cgroup:
 bad_fork_cleanup_put_domain:
 	module_put(task_thread_info(p)->exec_domain->module);
 bad_fork_cleanup_count:
-	put_group_info(p->sec->group_info);
 	atomic_dec(&p->sec->user->processes);
-	free_uid(p->sec->user);
+bad_fork_cleanup_put_task_sec:
+	put_task_security(p->act_as);
+	put_task_security(p->sec);
 bad_fork_free:
 	free_task(p);
 fork_out:
diff --git a/kernel/kmod.c b/kernel/kmod.c
index c6a4f8a..7e34d46 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -133,20 +133,18 @@ struct subprocess_info {
 static int ____call_usermodehelper(void *data)
 {
 	struct subprocess_info *sub_info = data;
-	struct key *new_session, *old_session;
 	int retval;
 
-	/* Unblock all signals and set the session keyring. */
-	new_session = key_get(sub_info->ring);
+	/* Set the session keyring. */
+	__install_session_keyring(current, sub_info->ring);
+
+	/* Unblock all signals. */
 	spin_lock_irq(&current->sighand->siglock);
-	old_session = __install_session_keyring(current, new_session);
 	flush_signal_handlers(current, 1);
 	sigemptyset(&current->blocked);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	key_put(old_session);
-
 	/* Install input pipe when needed */
 	if (sub_info->stdin) {
 		struct files_struct *f = current->files;
diff --git a/kernel/sys.c b/kernel/sys.c
index 14acc1b..e331b6f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -521,7 +521,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
 	sec->fsgid = new_egid;
 	sec->egid = new_egid;
 	sec->gid = new_rgid;
-	key_fsgid_changed(current);
+	key_fsgid_changed(sec);
 	proc_id_connector(current, PROC_EVENT_GID);
 	return 0;
 }
@@ -557,7 +557,7 @@ asmlinkage long sys_setgid(gid_t gid)
 	else
 		return -EPERM;
 
-	key_fsgid_changed(current);
+	key_fsgid_changed(sec);
 	proc_id_connector(current, PROC_EVENT_GID);
 	return 0;
 }
@@ -646,7 +646,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 		sec->suid = sec->euid;
 	sec->fsuid = sec->euid;
 
-	key_fsuid_changed(current);
+	key_fsuid_changed(sec);
 	proc_id_connector(current, PROC_EVENT_UID);
 
 	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
@@ -694,7 +694,7 @@ asmlinkage long sys_setuid(uid_t uid)
 	sec->fsuid = sec->euid = uid;
 	sec->suid = new_suid;
 
-	key_fsuid_changed(current);
+	key_fsuid_changed(sec);
 	proc_id_connector(current, PROC_EVENT_UID);
 
 	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
@@ -744,7 +744,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 	if (suid != (uid_t) -1)
 		sec->suid = suid;
 
-	key_fsuid_changed(current);
+	key_fsuid_changed(sec);
 	proc_id_connector(current, PROC_EVENT_UID);
 
 	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
@@ -798,7 +798,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 	if (sgid != (gid_t) -1)
 		sec->sgid = sgid;
 
-	key_fsgid_changed(current);
+	key_fsgid_changed(sec);
 	proc_id_connector(current, PROC_EVENT_GID);
 	return 0;
 }
@@ -841,7 +841,7 @@ asmlinkage long sys_setfsuid(uid_t uid)
 		sec->fsuid = uid;
 	}
 
-	key_fsuid_changed(current);
+	key_fsuid_changed(sec);
 	proc_id_connector(current, PROC_EVENT_UID);
 
 	security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
@@ -869,7 +869,7 @@ asmlinkage long sys_setfsgid(gid_t gid)
 			smp_wmb();
 		}
 		sec->fsgid = gid;
-		key_fsgid_changed(current);
+		key_fsgid_changed(sec);
 		proc_id_connector(current, PROC_EVENT_GID);
 	}
 	return old_fsgid;
diff --git a/kernel/user.c b/kernel/user.c
index d9a84b1..0555576 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -356,7 +356,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
 #endif
 		new->locked_shm = 0;
 
-		if (alloc_uid_keyring(new, current) < 0) {
+		if (alloc_uid_keyring(new, current->sec) < 0) {
 			kmem_cache_free(uid_cachep, new);
 			uids_mutex_unlock();
 			return NULL;
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index 9a8ff68..14979a5 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -297,7 +297,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
 
 	_enter("");
 
-	key = key_alloc(&key_type_rxrpc, "x", 0, 0, current, 0,
+	key = key_alloc(&key_type_rxrpc, "x", 0, 0, current->act_as, 0,
 			KEY_ALLOC_NOT_IN_QUOTA);
 	if (IS_ERR(key)) {
 		_leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
@@ -343,7 +343,7 @@ struct key *rxrpc_get_null_key(const char *keyname)
 	struct key *key;
 	int ret;
 
-	key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current,
+	key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current->act_as,
 			KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
 	if (IS_ERR(key))
 		return key;
diff --git a/security/dummy.c b/security/dummy.c
index 287f3ec..526549d 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -480,16 +480,21 @@ static int dummy_task_create (unsigned long clone_flags)
 	return 0;
 }
 
-static int dummy_task_alloc_security (struct task_struct *p)
+static int dummy_task_alloc_security(struct task_struct *p)
 {
 	return 0;
 }
 
-static void dummy_task_free_security (struct task_struct *p)
+static void dummy_task_free_security(struct task_security *sec)
 {
 	return;
 }
 
+static int dummy_task_dup_security(struct task_security *p)
+{
+	return 0;
+}
+
 static int dummy_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
 {
 	return 0;
@@ -943,7 +948,7 @@ static void dummy_release_secctx(char *secdata, u32 seclen)
 }
 
 #ifdef CONFIG_KEYS
-static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx,
+static inline int dummy_key_alloc(struct key *key, struct task_security *sec,
 				  unsigned long flags)
 {
 	return 0;
@@ -954,7 +959,7 @@ static inline void dummy_key_free(struct key *key)
 }
 
 static inline int dummy_key_permission(key_ref_t key_ref,
-				       struct task_struct *context,
+				       struct task_security *sec,
 				       key_perm_t perm)
 {
 	return 0;
@@ -1057,6 +1062,7 @@ void security_fixup_ops (struct security_operations *ops)
 	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);
+	set_to_dummy_if_null(ops, task_dup_security);
 	set_to_dummy_if_null(ops, task_setuid);
 	set_to_dummy_if_null(ops, task_post_setuid);
 	set_to_dummy_if_null(ops, task_setgid);
diff --git a/security/keys/internal.h b/security/keys/internal.h
index f004835..a439889 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -92,7 +92,7 @@ extern struct key *keyring_search_instkey(struct key *keyring,
 typedef int (*key_match_func_t)(const struct key *, const void *);
 
 extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
-				    struct task_struct *tsk,
+				    struct task_security *sec,
 				    struct key_type *type,
 				    const void *description,
 				    key_match_func_t match);
@@ -100,12 +100,12 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
 extern key_ref_t search_process_keyrings(struct key_type *type,
 					 const void *description,
 					 key_match_func_t match,
-					 struct task_struct *tsk);
+					 struct task_security *sec);
 
 extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
 
-extern int install_thread_keyring(struct task_struct *tsk);
-extern int install_process_keyring(struct task_struct *tsk);
+extern int install_thread_keyring(struct task_security *sec);
+extern int install_process_keyring(struct task_security *sec);
 
 extern struct key *request_key_and_link(struct key_type *type,
 					const char *description,
@@ -120,7 +120,7 @@ extern struct key *request_key_and_link(struct key_type *type,
  */
 struct request_key_auth {
 	struct key		*target_key;
-	struct task_struct	*context;
+	struct task_security	*sec;
 	void			*callout_info;
 	size_t			callout_len;
 	pid_t			pid;
diff --git a/security/keys/key.c b/security/keys/key.c
index 1692988..68483d7 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -243,7 +243,7 @@ serial_exists:
  *   instantiate the key or discard it before returning
  */
 struct key *key_alloc(struct key_type *type, const char *desc,
-		      uid_t uid, gid_t gid, struct task_struct *ctx,
+		      uid_t uid, gid_t gid, struct task_security *sec,
 		      key_perm_t perm, unsigned long flags)
 {
 	struct key_user *user = NULL;
@@ -314,7 +314,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
 #endif
 
 	/* let the security module know about the key */
-	ret = security_key_alloc(key, ctx, flags);
+	ret = security_key_alloc(key, sec, flags);
 	if (ret < 0)
 		goto security_error;
 
@@ -818,7 +818,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 
 	/* allocate a new key */
 	key = key_alloc(ktype, description, current_fsuid(), current_fsgid(),
-			current, perm, flags);
+			current->act_as, perm, flags);
 	if (IS_ERR(key)) {
 		key_ref = ERR_PTR(PTR_ERR(key));
 		goto error_3;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 4051948..2900451 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -878,7 +878,7 @@ long keyctl_instantiate_key(key_serial_t id,
 	 * requesting task */
 	keyring_ref = NULL;
 	if (ringid) {
-		keyring_ref = lookup_user_key(rka->context, ringid, 1, 0,
+		keyring_ref = lookup_user_key(rka->sec, ringid, 1, 0,
 					      KEY_WRITE);
 		if (IS_ERR(keyring_ref)) {
 			ret = PTR_ERR(keyring_ref);
@@ -973,13 +973,13 @@ long keyctl_set_reqkey_keyring(int reqkey_defl)
 
 	switch (reqkey_defl) {
 	case KEY_REQKEY_DEFL_THREAD_KEYRING:
-		ret = install_thread_keyring(current);
+		ret = install_thread_keyring(sec);
 		if (ret < 0)
 			return ret;
 		goto set;
 
 	case KEY_REQKEY_DEFL_PROCESS_KEYRING:
-		ret = install_process_keyring(current);
+		ret = install_process_keyring(sec);
 		if (ret < 0)
 			return ret;
 
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 76b89b2..6ccd8f8 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -244,14 +244,14 @@ static long keyring_read(const struct key *keyring,
  * allocate a keyring and link into the destination keyring
  */
 struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
-			  struct task_struct *ctx, unsigned long flags,
+			  struct task_security *sec, unsigned long flags,
 			  struct key *dest)
 {
 	struct key *keyring;
 	int ret;
 
 	keyring = key_alloc(&key_type_keyring, description,
-			    uid, gid, ctx,
+			    uid, gid, sec,
 			    (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
 			    flags);
 
@@ -280,7 +280,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
  * - we propagate the possession attribute from the keyring ref to the key ref
  */
 key_ref_t keyring_search_aux(key_ref_t keyring_ref,
-			     struct task_struct *context,
+			     struct task_security *sec,
 			     struct key_type *type,
 			     const void *description,
 			     key_match_func_t match)
@@ -303,7 +303,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
 	key_check(keyring);
 
 	/* top keyring must have search permission to begin the search */
-        err = key_task_permission(keyring_ref, context, KEY_SEARCH);
+	err = key_task_permission(keyring_ref, sec, KEY_SEARCH);
 	if (err < 0) {
 		key_ref = ERR_PTR(err);
 		goto error;
@@ -376,7 +376,7 @@ descend:
 
 		/* key must have search permissions */
 		if (key_task_permission(make_key_ref(key, possessed),
-					context, KEY_SEARCH) < 0)
+					sec, KEY_SEARCH) < 0)
 			continue;
 
 		/* we set a different error code if we pass a negative key */
@@ -403,7 +403,7 @@ ascend:
 			continue;
 
 		if (key_task_permission(make_key_ref(key, possessed),
-					context, KEY_SEARCH) < 0)
+					sec, KEY_SEARCH) < 0)
 			continue;
 
 		/* stack the current position */
@@ -458,7 +458,7 @@ key_ref_t keyring_search(key_ref_t keyring,
 	if (!type->match)
 		return ERR_PTR(-ENOKEY);
 
-	return keyring_search_aux(keyring, current,
+	return keyring_search_aux(keyring, current->sec,
 				  type, description, type->match);
 
 } /* end keyring_search() */
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 07898bd..eff3e29 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -19,10 +19,9 @@
  * but permit the security modules to override
  */
 int key_task_permission(const key_ref_t key_ref,
-			struct task_struct *context,
+			struct task_security *sec,
 			key_perm_t perm)
 {
-	struct task_security *sec = context->act_as;
 	struct key *key;
 	key_perm_t kperm;
 	int ret;
@@ -69,7 +68,7 @@ use_these_perms:
 		return -EACCES;
 
 	/* let LSM be the final arbiter */
-	return security_key_permission(key_ref, context, perm);
+	return security_key_permission(key_ref, sec, perm);
 
 } /* end key_task_permission() */
 
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 3e0d0a6..91e6df2 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -141,7 +141,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
 
 	/* check whether the current task is allowed to view the key (assuming
 	 * non-possession) */
-	rc = key_task_permission(make_key_ref(key, 0), current, KEY_VIEW);
+	rc = key_task_permission(make_key_ref(key, 0), current->sec, KEY_VIEW);
 	if (rc < 0)
 		return 0;
 
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 98854b2..f51a08c 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -68,7 +68,7 @@ struct key root_session_keyring = {
  * allocate the keyrings to be associated with a UID
  */
 int alloc_uid_keyring(struct user_struct *user,
-		      struct task_struct *ctx)
+		      struct task_security *sec)
 {
 	struct key *uid_keyring, *session_keyring;
 	char buf[20];
@@ -77,7 +77,7 @@ int alloc_uid_keyring(struct user_struct *user,
 	/* concoct a default session keyring */
 	sprintf(buf, "_uid_ses.%u", user->uid);
 
-	session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+	session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, sec,
 					KEY_ALLOC_IN_QUOTA, NULL);
 	if (IS_ERR(session_keyring)) {
 		ret = PTR_ERR(session_keyring);
@@ -88,7 +88,7 @@ int alloc_uid_keyring(struct user_struct *user,
 	 * keyring */
 	sprintf(buf, "_uid.%u", user->uid);
 
-	uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+	uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, sec,
 				    KEY_ALLOC_IN_QUOTA, session_keyring);
 	if (IS_ERR(uid_keyring)) {
 		key_put(session_keyring);
@@ -135,33 +135,29 @@ void switch_uid_keyring(struct user_struct *new_user)
 
 /*****************************************************************************/
 /*
- * install a fresh thread keyring, discarding the old one
+ * make sure a thread keyring is installed
  */
-int install_thread_keyring(struct task_struct *tsk)
+int install_thread_keyring(struct task_security *sec)
 {
-	struct key *keyring, *old;
+	struct key *keyring;
 	char buf[20];
-	int ret;
 
-	sprintf(buf, "_tid.%u", tsk->pid);
+	sprintf(buf, "_tid.%u", current->pid);
 
-	keyring = keyring_alloc(buf, tsk->sec->uid, tsk->sec->gid, tsk,
+	keyring = keyring_alloc(buf, sec->uid, sec->gid, sec,
 				KEY_ALLOC_QUOTA_OVERRUN, NULL);
-	if (IS_ERR(keyring)) {
-		ret = PTR_ERR(keyring);
-		goto error;
-	}
-
-	task_lock(tsk);
-	old = tsk->sec->thread_keyring;
-	tsk->sec->thread_keyring = keyring;
-	task_unlock(tsk);
+	if (IS_ERR(keyring))
+		return PTR_ERR(keyring);
 
-	ret = 0;
+	spin_lock(&sec->lock);
+	if (!sec->thread_keyring) {
+		sec->thread_keyring = keyring;
+		keyring = NULL;
+	}
+	spin_unlock(&sec->lock);
 
-	key_put(old);
-error:
-	return ret;
+	key_put(keyring);
+	return 0;
 
 } /* end install_thread_keyring() */
 
@@ -169,38 +165,36 @@ error:
 /*
  * make sure a process keyring is installed
  */
-int install_process_keyring(struct task_struct *tsk)
+int install_process_keyring(struct task_security *sec)
 {
+	struct thread_group_security *tgsec;
 	struct key *keyring;
 	char buf[20];
-	int ret;
 
 	might_sleep();
+	sec = current->sec;
+	tgsec = sec->tgsec;
 
-	if (!tsk->signal->process_keyring) {
-		sprintf(buf, "_pid.%u", tsk->tgid);
+	if (!tgsec->process_keyring) {
+		sprintf(buf, "_pid.%u", tgsec->tgid);
 
-		keyring = keyring_alloc(buf, tsk->sec->uid, tsk->sec->gid, tsk,
+		keyring = keyring_alloc(buf, sec->uid, sec->gid, sec,
 					KEY_ALLOC_QUOTA_OVERRUN, NULL);
-		if (IS_ERR(keyring)) {
-			ret = PTR_ERR(keyring);
-			goto error;
-		}
+		if (IS_ERR(keyring))
+			return PTR_ERR(keyring);
 
 		/* attach keyring */
-		spin_lock_irq(&tsk->sighand->siglock);
-		if (!tsk->signal->process_keyring) {
-			tsk->signal->process_keyring = keyring;
+		spin_lock(&tgsec->lock);
+		if (!tgsec->process_keyring) {
+			tgsec->process_keyring = keyring;
 			keyring = NULL;
 		}
-		spin_unlock_irq(&tsk->sighand->siglock);
+		spin_unlock(&tgsec->lock);
 
 		key_put(keyring);
 	}
 
-	ret = 0;
-error:
-	return ret;
+	return 0;
 
 } /* end install_process_keyring() */
 
@@ -209,37 +203,38 @@ error:
  * install a session keyring, discarding the old one
  * - if a keyring is not supplied, an empty one is invented
  */
-static int install_session_keyring(struct task_struct *tsk,
+static int install_session_keyring(struct task_security *sec,
 				   struct key *keyring)
 {
+	struct thread_group_security *tgsec;
 	unsigned long flags;
 	struct key *old;
 	char buf[20];
 
 	might_sleep();
+	tgsec = sec->tgsec;
 
 	/* create an empty session keyring */
 	if (!keyring) {
-		sprintf(buf, "_ses.%u", tsk->tgid);
+		sprintf(buf, "_ses.%u", tgsec->tgid);
 
 		flags = KEY_ALLOC_QUOTA_OVERRUN;
-		if (tsk->signal->session_keyring)
+		if (tgsec->session_keyring)
 			flags = KEY_ALLOC_IN_QUOTA;
 
-		keyring = keyring_alloc(buf, tsk->sec->uid, tsk->sec->gid, tsk,
+		keyring = keyring_alloc(buf, sec->uid, sec->gid, sec,
 					flags, NULL);
 		if (IS_ERR(keyring))
 			return PTR_ERR(keyring);
-	}
-	else {
+	} else {
 		atomic_inc(&keyring->usage);
 	}
 
 	/* install the keyring */
-	spin_lock_irq(&tsk->sighand->siglock);
-	old = tsk->signal->session_keyring;
-	rcu_assign_pointer(tsk->signal->session_keyring, keyring);
-	spin_unlock_irq(&tsk->sighand->siglock);
+	spin_lock_irq(&tgsec->lock);
+	old = tgsec->session_keyring;
+	rcu_assign_pointer(tgsec->session_keyring, keyring);
+	spin_unlock_irq(&tgsec->lock);
 
 	/* we're using RCU on the pointer, but there's no point synchronising
 	 * on it if it didn't previously point to anything */
@@ -252,68 +247,49 @@ static int install_session_keyring(struct task_struct *tsk,
 
 } /* end install_session_keyring() */
 
-/*****************************************************************************/
 /*
- * copy the keys in a thread group for fork without CLONE_THREAD
+ * install a session keyring for kmod
  */
-int copy_thread_group_keys(struct task_struct *tsk)
+void __install_session_keyring(struct task_struct *tsk, struct key *keyring)
 {
-	key_check(current->thread_group->session_keyring);
-	key_check(current->thread_group->process_keyring);
-
-	/* no process keyring yet */
-	tsk->signal->process_keyring = NULL;
+	struct thread_group_security *tgsec = tsk->sec->tgsec;
+	struct key *old;
 
-	/* same session keyring */
-	rcu_read_lock();
-	tsk->signal->session_keyring =
-		key_get(rcu_dereference(current->signal->session_keyring));
-	rcu_read_unlock();
+	key_get(keyring);
 
-	return 0;
+	spin_lock(&tgsec->lock);
+	old = tgsec->session_keyring;
+	rcu_assign_pointer(tgsec->session_keyring, keyring);
+	spin_unlock(&tgsec->lock);
 
-} /* end copy_thread_group_keys() */
+	/* we're using RCU on the pointer, but there's no point synchronising
+	 * on it if it didn't previously point to anything */
+	if (old) {
+		synchronize_rcu();
+		key_put(old);
+	}
+}
 
 /*****************************************************************************/
 /*
- * copy the keys for fork
+ * copy the keys in a thread group for fork without CLONE_THREAD
  */
-int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
+int copy_thread_group_keys(struct thread_group_security *tgsec)
 {
-	key_check(tsk->sec->thread_keyring);
-	key_check(tsk->sec->request_key_auth);
+	key_check(tgsec->session_keyring);
+	key_check(tgsec->process_keyring);
 
-	/* no thread keyring yet */
-	tsk->sec->thread_keyring = NULL;
+	/* no process keyring yet */
+	tgsec->process_keyring = NULL;
 
-	/* copy the request_key() authorisation for this thread */
-	key_get(tsk->sec->request_key_auth);
+	/* same session keyring */
+	rcu_read_lock();
+	tgsec->session_keyring =
+		key_get(rcu_dereference(current->sec->tgsec->session_keyring));
+	rcu_read_unlock();
 
 	return 0;
-
-} /* end copy_keys() */
-
-/*****************************************************************************/
-/*
- * dispose of thread group keys upon thread group destruction
- */
-void exit_thread_group_keys(struct signal_struct *tg)
-{
-	key_put(tg->session_keyring);
-	key_put(tg->process_keyring);
-
-} /* end exit_thread_group_keys() */
-
-/*****************************************************************************/
-/*
- * dispose of per-thread keys upon thread exit
- */
-void exit_keys(struct task_struct *tsk)
-{
-	key_put(tsk->sec->thread_keyring);
-	key_put(tsk->sec->request_key_auth);
-
-} /* end exit_keys() */
+}
 
 /*****************************************************************************/
 /*
@@ -321,21 +297,23 @@ void exit_keys(struct task_struct *tsk)
  */
 int exec_keys(struct task_struct *tsk)
 {
+	struct thread_group_security *tgsec = tsk->sec->tgsec;
+	struct task_security *sec = tsk->sec;
 	struct key *old;
 
 	/* newly exec'd tasks don't get a thread keyring */
-	task_lock(tsk);
-	old = tsk->sec->thread_keyring;
-	tsk->sec->thread_keyring = NULL;
-	task_unlock(tsk);
+	spin_lock(&sec->lock);
+	old = sec->thread_keyring;
+	sec->thread_keyring = NULL;
+	spin_unlock(&sec->lock);
 
 	key_put(old);
 
 	/* discard the process keyring from a newly exec'd task */
-	spin_lock_irq(&tsk->sighand->siglock);
-	old = tsk->signal->process_keyring;
-	tsk->signal->process_keyring = NULL;
-	spin_unlock_irq(&tsk->sighand->siglock);
+	spin_lock(&tgsec->lock);
+	old = tgsec->process_keyring;
+	tgsec->process_keyring = NULL;
+	spin_unlock(&tgsec->lock);
 
 	key_put(old);
 
@@ -358,14 +336,13 @@ int suid_keys(struct task_struct *tsk)
 /*
  * the filesystem user ID changed
  */
-void key_fsuid_changed(struct task_struct *tsk)
+void key_fsuid_changed(struct task_security *sec)
 {
 	/* update the ownership of the thread keyring */
-	BUG_ON(!tsk->sec);
-	if (tsk->sec->thread_keyring) {
-		down_write(&tsk->sec->thread_keyring->sem);
-		tsk->sec->thread_keyring->uid = tsk->sec->fsuid;
-		up_write(&tsk->sec->thread_keyring->sem);
+	if (sec->thread_keyring) {
+		down_write(&sec->thread_keyring->sem);
+		sec->thread_keyring->uid = sec->fsuid;
+		up_write(&sec->thread_keyring->sem);
 	}
 
 } /* end key_fsuid_changed() */
@@ -374,14 +351,13 @@ void key_fsuid_changed(struct task_struct *tsk)
 /*
  * the filesystem group ID changed
  */
-void key_fsgid_changed(struct task_struct *tsk)
+void key_fsgid_changed(struct task_security *sec)
 {
 	/* update the ownership of the thread keyring */
-	BUG_ON(!tsk->sec);
-	if (tsk->sec->thread_keyring) {
-		down_write(&tsk->sec->thread_keyring->sem);
-		tsk->sec->thread_keyring->gid = tsk->sec->fsgid;
-		up_write(&tsk->sec->thread_keyring->sem);
+	if (sec->thread_keyring) {
+		down_write(&sec->thread_keyring->sem);
+		sec->thread_keyring->gid = sec->fsgid;
+		up_write(&sec->thread_keyring->sem);
 	}
 
 } /* end key_fsgid_changed() */
@@ -397,7 +373,7 @@ void key_fsgid_changed(struct task_struct *tsk)
 key_ref_t search_process_keyrings(struct key_type *type,
 				  const void *description,
 				  key_match_func_t match,
-				  struct task_struct *context)
+				  struct task_security *sec)
 {
 	struct request_key_auth *rka;
 	key_ref_t key_ref, ret, err;
@@ -416,10 +392,10 @@ key_ref_t search_process_keyrings(struct key_type *type,
 	err = ERR_PTR(-EAGAIN);
 
 	/* search the thread keyring first */
-	if (context->sec->thread_keyring) {
+	if (sec->thread_keyring) {
 		key_ref = keyring_search_aux(
-			make_key_ref(context->sec->thread_keyring, 1),
-			context, type, description, match);
+			make_key_ref(sec->thread_keyring, 1),
+			sec, type, description, match);
 		if (!IS_ERR(key_ref))
 			goto found;
 
@@ -437,10 +413,10 @@ key_ref_t search_process_keyrings(struct key_type *type,
 	}
 
 	/* search the process keyring second */
-	if (context->signal->process_keyring) {
+	if (sec->tgsec->process_keyring) {
 		key_ref = keyring_search_aux(
-			make_key_ref(context->signal->process_keyring, 1),
-			context, type, description, match);
+			make_key_ref(sec->tgsec->process_keyring, 1),
+			sec, type, description, match);
 		if (!IS_ERR(key_ref))
 			goto found;
 
@@ -458,13 +434,13 @@ key_ref_t search_process_keyrings(struct key_type *type,
 	}
 
 	/* search the session keyring */
-	if (context->signal->session_keyring) {
+	if (sec->tgsec->session_keyring) {
 		rcu_read_lock();
 		key_ref = keyring_search_aux(
 			make_key_ref(rcu_dereference(
-					     context->signal->session_keyring),
+					     sec->tgsec->session_keyring),
 				     1),
-			context, type, description, match);
+			sec, type, description, match);
 		rcu_read_unlock();
 
 		if (!IS_ERR(key_ref))
@@ -485,8 +461,8 @@ key_ref_t search_process_keyrings(struct key_type *type,
 	/* or search the user-session keyring */
 	else {
 		key_ref = keyring_search_aux(
-			make_key_ref(context->sec->user->session_keyring, 1),
-			context, type, description, match);
+			make_key_ref(sec->user->session_keyring, 1),
+			sec, type, description, match);
 		if (!IS_ERR(key_ref))
 			goto found;
 
@@ -507,20 +483,20 @@ key_ref_t search_process_keyrings(struct key_type *type,
 	 * search the keyrings of the process mentioned there
 	 * - we don't permit access to request_key auth keys via this method
 	 */
-	if (context->sec->request_key_auth &&
-	    context == current &&
+	if (sec->request_key_auth &&
+	    sec == current->sec &&
 	    type != &key_type_request_key_auth
 	    ) {
 		/* defend against the auth key being revoked */
-		down_read(&context->sec->request_key_auth->sem);
+		down_read(&sec->request_key_auth->sem);
 
-		if (key_validate(context->sec->request_key_auth) == 0) {
-			rka = context->sec->request_key_auth->payload.data;
+		if (key_validate(sec->request_key_auth) == 0) {
+			rka = sec->request_key_auth->payload.data;
 
 			key_ref = search_process_keyrings(type, description,
-							  match, rka->context);
+							  match, rka->sec);
 
-			up_read(&context->sec->request_key_auth->sem);
+			up_read(&sec->request_key_auth->sem);
 
 			if (!IS_ERR(key_ref))
 				goto found;
@@ -537,7 +513,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
 				break;
 			}
 		} else {
-			up_read(&context->sec->request_key_auth->sem);
+			up_read(&sec->request_key_auth->sem);
 		}
 	}
 
@@ -565,78 +541,78 @@ static int lookup_user_key_possessed(const struct key *key, const void *target)
  * - don't create special keyrings unless so requested
  * - partially constructed keys aren't found unless requested
  */
-key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
+key_ref_t lookup_user_key(struct task_security *sec, key_serial_t id,
 			  int create, int partial, key_perm_t perm)
 {
 	key_ref_t key_ref, skey_ref;
 	struct key *key;
 	int ret;
 
-	if (!context)
-		context = current;
+	if (!sec)
+		sec = current->act_as;
 
 	key_ref = ERR_PTR(-ENOKEY);
 
 	switch (id) {
 	case KEY_SPEC_THREAD_KEYRING:
-		if (!context->sec->thread_keyring) {
+		if (!sec->thread_keyring) {
 			if (!create)
 				goto error;
 
-			ret = install_thread_keyring(context);
+			ret = install_thread_keyring(sec);
 			if (ret < 0) {
 				key = ERR_PTR(ret);
 				goto error;
 			}
 		}
 
-		key = context->sec->thread_keyring;
+		key = sec->thread_keyring;
 		atomic_inc(&key->usage);
 		key_ref = make_key_ref(key, 1);
 		break;
 
 	case KEY_SPEC_PROCESS_KEYRING:
-		if (!context->signal->process_keyring) {
+		if (!sec->tgsec->process_keyring) {
 			if (!create)
 				goto error;
 
-			ret = install_process_keyring(context);
+			ret = install_process_keyring(sec);
 			if (ret < 0) {
 				key = ERR_PTR(ret);
 				goto error;
 			}
 		}
 
-		key = context->signal->process_keyring;
+		key = sec->tgsec->process_keyring;
 		atomic_inc(&key->usage);
 		key_ref = make_key_ref(key, 1);
 		break;
 
 	case KEY_SPEC_SESSION_KEYRING:
-		if (!context->signal->session_keyring) {
+		if (!sec->tgsec->session_keyring) {
 			/* always install a session keyring upon access if one
 			 * doesn't exist yet */
 			ret = install_session_keyring(
-				context, context->sec->user->session_keyring);
+				sec, sec->user->session_keyring);
 			if (ret < 0)
 				goto error;
 		}
 
 		rcu_read_lock();
-		key = rcu_dereference(context->signal->session_keyring);
+		key = rcu_dereference(sec->tgsec->session_keyring);
 		atomic_inc(&key->usage);
 		rcu_read_unlock();
 		key_ref = make_key_ref(key, 1);
 		break;
 
 	case KEY_SPEC_USER_KEYRING:
-		key = context->sec->user->uid_keyring;
+		key = sec->user->uid_keyring;
 		atomic_inc(&key->usage);
 		key_ref = make_key_ref(key, 1);
 		break;
 
 	case KEY_SPEC_USER_SESSION_KEYRING:
-		key = context->sec->user->session_keyring;
+		key = sec->user->session_keyring;
 		atomic_inc(&key->usage);
 		key_ref = make_key_ref(key, 1);
 		break;
@@ -647,7 +623,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
 		goto error;
 
 	case KEY_SPEC_REQKEY_AUTH_KEY:
-		key = context->sec->request_key_auth;
+		key = sec->request_key_auth;
 		if (!key)
 			goto error;
 
@@ -671,7 +647,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
 		/* check to see if we possess the key */
 		skey_ref = search_process_keyrings(key->type, key,
 						   lookup_user_key_possessed,
-						   current);
+						   sec);
 
 		if (!IS_ERR(skey_ref)) {
 			key_put(key);
@@ -703,7 +679,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
 		goto invalid_key;
 
 	/* check the permissions */
-	ret = key_task_permission(key_ref, context, perm);
+	ret = key_task_permission(key_ref, sec, perm);
 	if (ret < 0)
 		goto invalid_key;
 
@@ -726,18 +702,18 @@ invalid_key:
  */
 long join_session_keyring(const char *name)
 {
-	struct task_struct *tsk = current;
+	struct task_security *sec = current->sec;
 	struct key *keyring;
 	long ret;
 
 	/* if no name is provided, install an anonymous keyring */
 	if (!name) {
-		ret = install_session_keyring(tsk, NULL);
+		ret = install_session_keyring(sec, NULL);
 		if (ret < 0)
 			goto error;
 
 		rcu_read_lock();
-		ret = rcu_dereference(tsk->signal->session_keyring)->serial;
+		ret = rcu_dereference(sec->tgsec->session_keyring)->serial;
 		rcu_read_unlock();
 		goto error;
 	}
@@ -749,7 +725,7 @@ long join_session_keyring(const char *name)
 	keyring = find_keyring_by_name(name, 0);
 	if (PTR_ERR(keyring) == -ENOKEY) {
 		/* not found - try and create a new one */
-		keyring = keyring_alloc(name, tsk->sec->uid, tsk->sec->gid, tsk,
+		keyring = keyring_alloc(name, sec->uid, sec->gid, sec,
 					KEY_ALLOC_IN_QUOTA, NULL);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
@@ -762,7 +738,7 @@ long join_session_keyring(const char *name)
 	}
 
 	/* we've got a keyring - now to install it */
-	ret = install_session_keyring(tsk, keyring);
+	ret = install_session_keyring(sec, keyring);
 	if (ret < 0)
 		goto error2;
 
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 54b03bb..be88aeb 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -63,7 +63,7 @@ static int call_sbin_request_key(struct key_construction *cons,
 				 const char *op,
 				 void *aux)
 {
-	struct task_struct *tsk = current;
+	struct task_security *sec = current->act_as;
 	key_serial_t prkey, sskey;
 	struct key *key = cons->key, *authkey = cons->authkey, *keyring;
 	char *argv[9], *envp[3], uid_str[12], gid_str[12];
@@ -76,7 +76,7 @@ static int call_sbin_request_key(struct key_construction *cons,
 	/* allocate a new session keyring */
 	sprintf(desc, "_req.%u", key->serial);
 
-	keyring = keyring_alloc(desc, current_fsuid(), current_fsgid(), current,
+	keyring = keyring_alloc(desc, sec->fsuid, sec->fsgid, sec,
 				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
@@ -89,29 +89,27 @@ static int call_sbin_request_key(struct key_construction *cons,
 		goto error_link;
 
 	/* record the UID and GID */
-	sprintf(uid_str, "%d", current_fsuid());
-	sprintf(gid_str, "%d", current_fsgid());
+	sprintf(uid_str, "%d", sec->fsuid);
+	sprintf(gid_str, "%d", sec->fsgid);
 
 	/* we say which key is under construction */
 	sprintf(key_str, "%d", key->serial);
 
 	/* we specify the process's default keyrings */
-	sprintf(keyring_str[0], "%d",
-		tsk->act_as->thread_keyring ?
-		tsk->act_as->thread_keyring->serial : 0);
+	sprintf(keyring_str[0], "%d", key_serial(sec->thread_keyring));
 
 	prkey = 0;
-	if (tsk->signal->process_keyring)
-		prkey = tsk->signal->process_keyring->serial;
+	if (sec->tgsec->process_keyring)
+		prkey = sec->tgsec->process_keyring->serial;
 
 	sprintf(keyring_str[1], "%d", prkey);
 
-	if (tsk->signal->session_keyring) {
+	if (sec->tgsec->session_keyring) {
 		rcu_read_lock();
-		sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
+		sskey = rcu_dereference(sec->tgsec->session_keyring)->serial;
 		rcu_read_unlock();
 	} else {
-		sskey = tsk->act_as->user->session_keyring->serial;
+		sskey = sec->user->session_keyring->serial;
 	}
 
 	sprintf(keyring_str[2], "%d", sskey);
@@ -210,29 +208,29 @@ static int construct_key(struct key *key, const void *callout_info,
  */
 static void construct_key_make_link(struct key *key, struct key *dest_keyring)
 {
-	struct task_struct *tsk = current;
+	struct task_security *sec = current->sec;
 	struct key *drop = NULL;
 
 	kenter("{%d},%p", key->serial, dest_keyring);
 
 	/* find the appropriate keyring */
 	if (!dest_keyring) {
-		switch (tsk->act_as->jit_keyring) {
+		switch (sec->jit_keyring) {
 		case KEY_REQKEY_DEFL_DEFAULT:
 		case KEY_REQKEY_DEFL_THREAD_KEYRING:
-			dest_keyring = tsk->act_as->thread_keyring;
+			dest_keyring = sec->thread_keyring;
 			if (dest_keyring)
 				break;
 
 		case KEY_REQKEY_DEFL_PROCESS_KEYRING:
-			dest_keyring = tsk->signal->process_keyring;
+			dest_keyring = sec->tgsec->process_keyring;
 			if (dest_keyring)
 				break;
 
 		case KEY_REQKEY_DEFL_SESSION_KEYRING:
 			rcu_read_lock();
 			dest_keyring = key_get(
-				rcu_dereference(tsk->signal->session_keyring));
+				rcu_dereference(sec->tgsec->session_keyring));
 			rcu_read_unlock();
 			drop = dest_keyring;
 
@@ -240,11 +238,11 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring)
 				break;
 
 		case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
-			dest_keyring = tsk->act_as->user->session_keyring;
+			dest_keyring = sec->user->session_keyring;
 			break;
 
 		case KEY_REQKEY_DEFL_USER_KEYRING:
-			dest_keyring = tsk->act_as->user->uid_keyring;
+			dest_keyring = sec->user->uid_keyring;
 			break;
 
 		case KEY_REQKEY_DEFL_GROUP_KEYRING:
@@ -268,6 +266,7 @@ static int construct_alloc_key(struct key_type *type,
 			       const char *description,
 			       struct key *dest_keyring,
 			       unsigned long flags,
+			       struct task_security *sec,
 			       struct key_user *user,
 			       struct key **_key)
 {
@@ -278,9 +277,8 @@ static int construct_alloc_key(struct key_type *type,
 
 	mutex_lock(&user->cons_lock);
 
-	key = key_alloc(type, description,
-			current_fsuid(), current_fsgid(), current, KEY_POS_ALL,
-			flags);
+	key = key_alloc(type, description, sec->fsuid, sec->fsgid, sec,
+			KEY_POS_ALL, flags);
 	if (IS_ERR(key))
 		goto alloc_failed;
 
@@ -294,8 +292,7 @@ static int construct_alloc_key(struct key_type *type,
 	 * waited for locks */
 	mutex_lock(&key_construction_mutex);
 
-	key_ref = search_process_keyrings(type, description, type->match,
-					  current);
+	key_ref = search_process_keyrings(type, description, type->match, sec);
 	if (!IS_ERR(key_ref))
 		goto key_already_present;
 
@@ -336,18 +333,19 @@ static struct key *construct_key_and_link(struct key_type *type,
 					  size_t callout_len,
 					  void *aux,
 					  struct key *dest_keyring,
+					  struct task_security *sec,
 					  unsigned long flags)
 {
 	struct key_user *user;
 	struct key *key;
 	int ret;
 
-	user = key_user_lookup(current_fsuid());
+	user = key_user_lookup(sec->fsuid);
 	if (!user)
 		return ERR_PTR(-ENOMEM);
 
-	ret = construct_alloc_key(type, description, dest_keyring, flags, user,
-				  &key);
+	ret = construct_alloc_key(type, description, dest_keyring, flags, sec,
+				  user, &key);
 	key_user_put(user);
 
 	if (ret == 0) {
@@ -379,6 +377,7 @@ struct key *request_key_and_link(struct key_type *type,
 				 struct key *dest_keyring,
 				 unsigned long flags)
 {
+	struct task_security *sec = current->sec;
 	struct key *key;
 	key_ref_t key_ref;
 
@@ -387,9 +386,7 @@ struct key *request_key_and_link(struct key_type *type,
 	       dest_keyring, flags);
 
 	/* search all the process keyrings for a key */
-	key_ref = search_process_keyrings(type, description, type->match,
-					  current);
-
+	key_ref = search_process_keyrings(type, description, type->match, sec);
 	if (!IS_ERR(key_ref)) {
 		key = key_ref_to_ptr(key_ref);
 	} else if (PTR_ERR(key_ref) != -EAGAIN) {
@@ -403,7 +400,7 @@ struct key *request_key_and_link(struct key_type *type,
 
 		key = construct_key_and_link(type, description, callout_info,
 					     callout_len, aux, dest_keyring,
-					     flags);
+					     sec, flags);
 	}
 
 error:
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 9598670..e3c09a4 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -104,10 +104,8 @@ static void request_key_auth_revoke(struct key *key)
 
 	kenter("{%d}", key->serial);
 
-	if (rka->context) {
-		put_task_struct(rka->context);
-		rka->context = NULL;
-	}
+	put_task_security(rka->sec);
+	rka->sec = NULL;
 
 } /* end request_key_auth_revoke() */
 
@@ -121,11 +119,7 @@ static void request_key_auth_destroy(struct key *key)
 
 	kenter("{%d}", key->serial);
 
-	if (rka->context) {
-		put_task_struct(rka->context);
-		rka->context = NULL;
-	}
-
+	put_task_security(rka->sec);
 	key_put(rka->target_key);
 	kfree(rka->callout_info);
 	kfree(rka);
@@ -141,6 +135,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 				 size_t callout_len)
 {
 	struct request_key_auth *rka, *irka;
+	struct task_security *sec = current->sec;
 	struct key *authkey = NULL;
 	char desc[20];
 	int ret;
@@ -162,28 +157,25 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 
 	/* see if the calling process is already servicing the key request of
 	 * another process */
-	if (current->act_as->request_key_auth) {
+	if (sec->request_key_auth) {
 		/* it is - use that instantiation context here too */
-		down_read(&current->act_as->request_key_auth->sem);
+		down_read(&sec->request_key_auth->sem);
 
 		/* if the auth key has been revoked, then the key we're
 		 * servicing is already instantiated */
-		if (test_bit(KEY_FLAG_REVOKED,
-			     &current->act_as->request_key_auth->flags))
+		if (test_bit(KEY_FLAG_REVOKED, &sec->request_key_auth->flags))
 			goto auth_key_revoked;
 
-		irka = current->act_as->request_key_auth->payload.data;
-		rka->context = irka->context;
+		irka = sec->request_key_auth->payload.data;
+		rka->sec = irka->sec;
 		rka->pid = irka->pid;
-		get_task_struct(rka->context);
+		get_task_security(rka->sec);
 
-		up_read(&current->act_as->request_key_auth->sem);
-	}
-	else {
+		up_read(&sec->request_key_auth->sem);
+	} else {
 		/* it isn't - use this process as the context */
-		rka->context = current;
+		rka->sec = get_task_security(sec);
 		rka->pid = current->pid;
-		get_task_struct(rka->context);
 	}
 
 	rka->target_key = key_get(target);
@@ -194,7 +186,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 	sprintf(desc, "%x", target->serial);
 
 	authkey = key_alloc(&key_type_request_key_auth, desc,
-			    current_fsuid(), current_fsgid(), current,
+			    sec->fsuid, sec->fsgid, sec,
 			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
 			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
 	if (IS_ERR(authkey)) {
@@ -260,7 +252,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
 		&key_type_request_key_auth,
 		(void *) (unsigned long) target_id,
 		key_get_instantiation_authkey_match,
-		current);
+		current->act_as);
 
 	if (IS_ERR(authkey_ref)) {
 		authkey = ERR_PTR(PTR_ERR(authkey_ref));
diff --git a/security/security.c b/security/security.c
index 16213e3..92d66d6 100644
--- a/security/security.c
+++ b/security/security.c
@@ -573,9 +573,14 @@ int security_task_alloc(struct task_struct *p)
 	return security_ops->task_alloc_security(p);
 }
 
-void security_task_free(struct task_struct *p)
+void security_task_free(struct task_security *sec)
 {
-	security_ops->task_free_security(p);
+	security_ops->task_free_security(sec);
+}
+
+int security_task_dup(struct task_security *sec)
+{
+	return security_ops->task_dup_security(sec);
 }
 
 int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
@@ -1063,9 +1068,10 @@ EXPORT_SYMBOL(security_skb_classify_flow);
 
 #ifdef CONFIG_KEYS
 
-int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long flags)
+int security_key_alloc(struct key *key, struct task_security *sec,
+		       unsigned long flags)
 {
-	return security_ops->key_alloc(key, tsk, flags);
+	return security_ops->key_alloc(key, sec, flags);
 }
 
 void security_key_free(struct key *key)
@@ -1073,10 +1079,10 @@ void security_key_free(struct key *key)
 	security_ops->key_free(key);
 }
 
-int security_key_permission(key_ref_t key_ref,
-			    struct task_struct *context, key_perm_t perm)
+int security_key_permission(key_ref_t key_ref, struct task_security *sec,
+			    key_perm_t perm)
 {
-	return security_ops->key_permission(key_ref, context, perm);
+	return security_ops->key_permission(key_ref, sec, perm);
 }
 
 int security_key_getsecurity(struct key *key, char **_buffer)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e56529f..20a6b55 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -170,10 +170,10 @@ static int task_alloc_security(struct task_struct *task)
 	return 0;
 }
 
-static void task_free_security(struct task_struct *task)
+static void task_free_security(struct task_security *sec)
 {
-	struct task_security_struct *tsec = task->sec->security;
-	task->sec->security = NULL;
+	struct task_security_struct *tsec = sec->security;
+	sec->security = NULL;
 	kfree(tsec);
 }
 
@@ -2818,9 +2818,32 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
 	return 0;
 }
 
-static void selinux_task_free_security(struct task_struct *tsk)
+static void selinux_task_free_security(struct task_security *sec)
 {
-	task_free_security(tsk);
+	task_free_security(sec);
+}
+
+static int selinux_task_dup_security(struct task_security *sec)
+{
+	struct task_security_struct *tsec1, *tsec2;
+
+	tsec1 = sec->security;
+
+	tsec2 = kmemdup(tsec1, sizeof(*tsec1), GFP_KERNEL);
+	if (!tsec2)
+		return -ENOMEM;
+
+	tsec2->osid = tsec1->osid;
+	tsec2->sid = tsec1->sid;
+
+	tsec2->exec_sid = tsec1->exec_sid;
+	tsec2->create_sid = tsec1->create_sid;
+	tsec2->keycreate_sid = tsec1->keycreate_sid;
+	tsec2->sockcreate_sid = tsec1->sockcreate_sid;
+	tsec2->ptrace_sid = SECINITSID_UNLABELED;
+	sec->security = tsec2;
+
+	return 0;
 }
 
 static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
@@ -4718,10 +4741,10 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
 
 #ifdef CONFIG_KEYS
 
-static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
+static int selinux_key_alloc(struct key *k, struct task_security *context,
 			     unsigned long flags)
 {
-	struct task_security_struct *tsec = tsk->sec->security;
+	struct task_security_struct *tsec = context->security;
 	struct key_security_struct *ksec;
 
 	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
@@ -4747,7 +4770,7 @@ static void selinux_key_free(struct key *k)
 }
 
 static int selinux_key_permission(key_ref_t key_ref,
-			    struct task_struct *ctx,
+			    struct task_security *context,
 			    key_perm_t perm)
 {
 	struct key *key;
@@ -4756,7 +4779,7 @@ static int selinux_key_permission(key_ref_t key_ref,
 
 	key = key_ref_to_ptr(key_ref);
 
-	tsec = ctx->sec->security;
+	tsec = context->security;
 	ksec = key->security;
 
 	/* if no specific permissions are requested, we skip the
@@ -4860,6 +4883,7 @@ static struct security_operations selinux_ops = {
 	.task_create =			selinux_task_create,
 	.task_alloc_security =		selinux_task_alloc_security,
 	.task_free_security =		selinux_task_free_security,
+	.task_dup_security =		selinux_task_dup_security,
 	.task_setuid =			selinux_task_setuid,
 	.task_post_setuid =		selinux_task_post_setuid,
 	.task_setgid =			selinux_task_setgid,
@@ -5001,9 +5025,9 @@ static __init int selinux_init(void)
 
 #ifdef CONFIG_KEYS
 	/* Add security information to initial keyrings */
-	selinux_key_alloc(&root_user_keyring, current,
+	selinux_key_alloc(&root_user_keyring, current->sec,
 			  KEY_ALLOC_NOT_IN_QUOTA);
-	selinux_key_alloc(&root_session_keyring, current,
+	selinux_key_alloc(&root_session_keyring, current->sec,
 			  KEY_ALLOC_NOT_IN_QUOTA);
 #endif
 


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

* Re: [PATCH 4/7] KEYS: Add keyctl function to get a security label
  2007-12-05 19:37 ` [PATCH 4/7] KEYS: Add keyctl function to get a security label David Howells
@ 2007-12-05 20:12   ` Casey Schaufler
  2007-12-05 20:38     ` Stephen Smalley
  2007-12-06  1:28     ` David Howells
  0 siblings, 2 replies; 14+ messages in thread
From: Casey Schaufler @ 2007-12-05 20:12 UTC (permalink / raw)
  To: David Howells, viro, hch, Trond.Myklebust, sds, casey
  Cc: linux-kernel, selinux, linux-security-module, dhowells


--- David Howells <dhowells@redhat.com> wrote:

> Add a keyctl() function to get the security label of a key.
> 
> The following is added to Documentation/keys.txt:
> 
>  (*) Get the LSM security context attached to a key.
> 
> 	long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
> 		    size_t buflen)
> 
>      This function returns a string that represents the LSM security context
>      attached to a key in the buffer provided.
> 
>      Unless there's an error, it always returns the amount of data it could
>      produce, even if that's too big for the buffer, but it won't copy more
>      than requested to userspace. If the buffer pointer is NULL then no copy
>      will take place.
> 
>      A NUL character is included at the end of the string if the buffer is
>      sufficiently big.  This is included in the returned count.  If no LSM is
>      in force then an empty string will be returned.
> 
>      A process must have view permission on the key for this function to be
>      successful.
> 
> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
> 
>  Documentation/keys.txt   |   21 +++++++++++++++
>  include/linux/keyctl.h   |    1 +
>  include/linux/security.h |   20 +++++++++++++-
>  security/dummy.c         |    8 ++++++
>  security/keys/compat.c   |    3 ++
>  security/keys/keyctl.c   |   66
> ++++++++++++++++++++++++++++++++++++++++++++++
>  security/security.c      |    5 +++
>  security/selinux/hooks.c |   21 +++++++++++++--
>  8 files changed, 141 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/keys.txt b/Documentation/keys.txt
> index b82d38d..be424b0 100644
> --- a/Documentation/keys.txt
> +++ b/Documentation/keys.txt
> @@ -711,6 +711,27 @@ The keyctl syscall functions are:
>       The assumed authoritative key is inherited across fork and exec.
>  
>  
> + (*) Get the LSM security context attached to a key.
> +
> +	long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
> +		    size_t buflen)
> +
> +     This function returns a string that represents the LSM security context
> +     attached to a key in the buffer provided.
> +
> +     Unless there's an error, it always returns the amount of data it could
> +     produce, even if that's too big for the buffer, but it won't copy more
> +     than requested to userspace. If the buffer pointer is NULL then no copy
> +     will take place.
> +
> +     A NUL character is included at the end of the string if the buffer is
> +     sufficiently big.  This is included in the returned count.  If no LSM
> is
> +     in force then an empty string will be returned.
> +
> +     A process must have view permission on the key for this function to be
> +     successful.
> +
> +
>  ===============
>  KERNEL SERVICES
>  ===============
> diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
> index 3365945..656ee6b 100644
> --- a/include/linux/keyctl.h
> +++ b/include/linux/keyctl.h
> @@ -49,5 +49,6 @@
>  #define KEYCTL_SET_REQKEY_KEYRING	14	/* set default request-key keyring */
>  #define KEYCTL_SET_TIMEOUT		15	/* set key timeout */
>  #define KEYCTL_ASSUME_AUTHORITY		16	/* assume request_key() authorisation */
> +#define KEYCTL_GET_SECURITY		17	/* get key security label */
>  
>  #endif /*  _LINUX_KEYCTL_H */
> diff --git a/include/linux/security.h b/include/linux/security.h
> index ac05083..8d9e946 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -959,6 +959,17 @@ struct request_sock;
>   *	@perm describes the combination of permissions required of this key.
>   *	Return 1 if permission granted, 0 if permission denied and -ve it the
>   *      normal permissions model should be effected.
> + * @key_getsecurity:

If I contradict what I said last time around, well, I've seen
more of what's going on since then. (insert smiley here)

I think that this should be key_getsecctx(). That would get you
what you need from SELinux and Smack. Unfortunately, there is no
precedent for interfaces that return the secctx, while the are
places in networking and audit (audit needs to be converted off
of SELinux calls to LSM calls) that call getsecid() interfaces
and later use security_secid_to_secctx() to get the "printable"
version. So, key_getsecid() is the interface to introduce if you
want to be consistant, and pass the result to
security_secid_to_secctx() to get the data you're looking for.

> + *	Get a textual representation of the security context attached to a key
> + *	for the purposes of honouring KEYCTL_GETSECURITY.  This function
> + *	allocates the storage for the NUL-terminated string and the caller
> + *	should free it.
> + *	@key points to the key to be queried.
> + *	@_buffer points to a pointer that should be set to point to the
> + *	 resulting string (if no label or an error occurs).
> + *	Return the length of the string (including terminating NUL) or -ve if
> + *      an error.
> + *	May also return 0 (and a NULL buffer pointer) if there is no label.
>   *
>   * Security hooks affecting all System V IPC operations.
>   *
> @@ -1437,7 +1448,7 @@ struct security_operations {
>  	int (*key_permission)(key_ref_t key_ref,
>  			      struct task_struct *context,
>  			      key_perm_t perm);
> -
> +	int (*key_getsecurity)(struct key *key, char **_buffer);
>  #endif	/* CONFIG_KEYS */
>  
>  };
> @@ -2567,6 +2578,7 @@ int security_key_alloc(struct key *key, struct
> task_struct *tsk, unsigned long f
>  void security_key_free(struct key *key);
>  int security_key_permission(key_ref_t key_ref,
>  			    struct task_struct *context, key_perm_t perm);
> +int security_key_getsecurity(struct key *key, char **_buffer);
>  
>  #else
>  
> @@ -2588,6 +2600,12 @@ static inline int security_key_permission(key_ref_t
> key_ref,
>  	return 0;
>  }
>  
> +static inline int security_key_getsecurity(struct key *key, char **_buffer)
> +{
> +	*_buffer = NULL;
> +	return 0;
> +}
> +
>  #endif
>  #endif /* CONFIG_KEYS */
>  
> diff --git a/security/dummy.c b/security/dummy.c
> index 6d895ad..7993b30 100644
> --- a/security/dummy.c
> +++ b/security/dummy.c
> @@ -949,6 +949,13 @@ static inline int dummy_key_permission(key_ref_t
> key_ref,
>  {
>  	return 0;
>  }
> +
> +static int dummy_key_getsecurity(struct key *key, char **_buffer)
> +{
> +	*_buffer = NULL;
> +	return 0;
> +}
> +
>  #endif /* CONFIG_KEYS */
>  
>  struct security_operations dummy_security_ops;
> @@ -1133,6 +1140,7 @@ void security_fixup_ops (struct security_operations
> *ops)
>  	set_to_dummy_if_null(ops, key_alloc);
>  	set_to_dummy_if_null(ops, key_free);
>  	set_to_dummy_if_null(ops, key_permission);
> +	set_to_dummy_if_null(ops, key_getsecurity);
>  #endif	/* CONFIG_KEYS */
>  
>  }
> diff --git a/security/keys/compat.c b/security/keys/compat.c
> index e10ec99..c766c68 100644
> --- a/security/keys/compat.c
> +++ b/security/keys/compat.c
> @@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
>  	case KEYCTL_ASSUME_AUTHORITY:
>  		return keyctl_assume_authority(arg2);
>  
> +	case KEYCTL_GET_SECURITY:
> +		return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
> +
>  	default:
>  		return -EOPNOTSUPP;
>  	}
> diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
> index 1698bf9..56e963b 100644
> --- a/security/keys/keyctl.c
> +++ b/security/keys/keyctl.c
> @@ -20,6 +20,7 @@
>  #include <linux/string.h>
>  #include <linux/err.h>
>  #include <linux/vmalloc.h>
> +#include <linux/security.h>
>  #include <asm/uaccess.h>
>  #include "internal.h"
>  
> @@ -1080,6 +1081,66 @@ error:
>  
>  } /* end keyctl_assume_authority() */
>  
> +/*
> + * get the security label of a key
> + * - the key must grant us view permission
> + * - if there's a buffer, we place up to buflen bytes of data into it
> + * - unless there's an error, we return the amount of information available,
> + *   irrespective of how much we may have copied (including the terminal
> NUL)
> + * - implements keyctl(KEYCTL_GET_SECURITY)
> + */
> +long keyctl_get_security(key_serial_t keyid,
> +			 char __user *buffer,
> +			 size_t buflen)
> +{
> +	struct key *key, *instkey;
> +	key_ref_t key_ref;
> +	char *context;
> +	long ret;
> +
> +	key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
> +	if (IS_ERR(key_ref)) {
> +		if (PTR_ERR(key_ref) != -EACCES)
> +			return PTR_ERR(key_ref);
> +
> +		/* viewing a key under construction is also permitted if we
> +		 * have the authorisation token handy */
> +		instkey = key_get_instantiation_authkey(keyid);
> +		if (IS_ERR(instkey))
> +			return PTR_ERR(key_ref);
> +		key_put(instkey);
> +
> +		key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
> +		if (IS_ERR(key_ref))
> +			return PTR_ERR(key_ref);
> +	}
> +
> +	key = key_ref_to_ptr(key_ref);
> +	ret = security_key_getsecurity(key, &context);
> +	if (ret == 0) {
> +		/* if no information was returned, give userspace an empty
> +		 * string */
> +		ret = 1;
> +		if (buffer && buflen > 0 &&
> +		    copy_to_user(buffer, "", 1) != 0)
> +			ret = -EFAULT;
> +	} else if (ret > 0) {
> +		/* return as much data as there's room for */
> +		if (buffer && buflen > 0) {
> +			if (buflen > ret)
> +				buflen = ret;
> +
> +			if (copy_to_user(buffer, context, buflen) != 0)
> +				ret = -EFAULT;
> +		}
> +
> +		kfree(context);
> +	}
> +
> +	key_ref_put(key_ref);
> +	return ret;
> +}
> +
> 
>
/*****************************************************************************/
>  /*
>   * the key control system call
> @@ -1160,6 +1221,11 @@ asmlinkage long sys_keyctl(int option, unsigned long
> arg2, unsigned long arg3,
>  	case KEYCTL_ASSUME_AUTHORITY:
>  		return keyctl_assume_authority((key_serial_t) arg2);
>  
> +	case KEYCTL_GET_SECURITY:
> +		return keyctl_get_security((key_serial_t) arg2,
> +					   (char *) arg3,
> +					   (size_t) arg4);
> +
>  	default:
>  		return -EOPNOTSUPP;
>  	}
> diff --git a/security/security.c b/security/security.c
> index 0e1f1f1..16213e3 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1079,4 +1079,9 @@ int security_key_permission(key_ref_t key_ref,
>  	return security_ops->key_permission(key_ref, context, perm);
>  }
>  
> +int security_key_getsecurity(struct key *key, char **_buffer)
> +{
> +	return security_ops->key_getsecurity(key, _buffer);
> +}
> +
>  #endif	/* CONFIG_KEYS */
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 9f3124b..bd4cfab 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4768,6 +4768,20 @@ static int selinux_key_permission(key_ref_t key_ref,
>  			    SECCLASS_KEY, perm, NULL);
>  }
>  
> +static int selinux_key_getsecurity(struct key *key, char **_buffer)
> +{
> +	struct key_security_struct *ksec = key->security;
> +	char *context = NULL;
> +	unsigned len;
> +	int rc;
> +
> +	rc = security_sid_to_context(ksec->sid, &context, &len);
> +	if (!rc)
> +		rc = len;
> +	*_buffer = context;
> +	return rc;
> +}
> +
>  #endif
>  
>  static struct security_operations selinux_ops = {
> @@ -4943,9 +4957,10 @@ static struct security_operations selinux_ops = {
>  #endif
>  
>  #ifdef CONFIG_KEYS
> -	.key_alloc =                    selinux_key_alloc,
> -	.key_free =                     selinux_key_free,
> -	.key_permission =               selinux_key_permission,
> +	.key_alloc =			selinux_key_alloc,
> +	.key_free =			selinux_key_free,
> +	.key_permission =		selinux_key_permission,
> +	.key_getsecurity =		selinux_key_getsecurity,
>  #endif
>  };
>  
> 
> 
> 


Casey Schaufler
casey@schaufler-ca.com

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

* Re: [PATCH 4/7] KEYS: Add keyctl function to get a security label
  2007-12-05 20:12   ` Casey Schaufler
@ 2007-12-05 20:38     ` Stephen Smalley
  2007-12-06  1:28     ` David Howells
  1 sibling, 0 replies; 14+ messages in thread
From: Stephen Smalley @ 2007-12-05 20:38 UTC (permalink / raw)
  To: casey
  Cc: David Howells, viro, hch, Trond.Myklebust, linux-kernel, selinux,
	linux-security-module

On Wed, 2007-12-05 at 12:12 -0800, Casey Schaufler wrote:
> --- David Howells <dhowells@redhat.com> wrote:
> 
> > Add a keyctl() function to get the security label of a key.
> > 
> > The following is added to Documentation/keys.txt:
> > 
> >  (*) Get the LSM security context attached to a key.
> > 
> > 	long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
> > 		    size_t buflen)
> > 
> >      This function returns a string that represents the LSM security context
> >      attached to a key in the buffer provided.
> > 
> >      Unless there's an error, it always returns the amount of data it could
> >      produce, even if that's too big for the buffer, but it won't copy more
> >      than requested to userspace. If the buffer pointer is NULL then no copy
> >      will take place.
> > 
> >      A NUL character is included at the end of the string if the buffer is
> >      sufficiently big.  This is included in the returned count.  If no LSM is
> >      in force then an empty string will be returned.
> > 
> >      A process must have view permission on the key for this function to be
> >      successful.
> > 
> > Signed-off-by: David Howells <dhowells@redhat.com>
> > ---
> > 
> >  Documentation/keys.txt   |   21 +++++++++++++++
> >  include/linux/keyctl.h   |    1 +
> >  include/linux/security.h |   20 +++++++++++++-
> >  security/dummy.c         |    8 ++++++
> >  security/keys/compat.c   |    3 ++
> >  security/keys/keyctl.c   |   66
> > ++++++++++++++++++++++++++++++++++++++++++++++
> >  security/security.c      |    5 +++
> >  security/selinux/hooks.c |   21 +++++++++++++--
> >  8 files changed, 141 insertions(+), 4 deletions(-)
> > 
> > diff --git a/Documentation/keys.txt b/Documentation/keys.txt
> > index b82d38d..be424b0 100644
> > --- a/Documentation/keys.txt
> > +++ b/Documentation/keys.txt
> > @@ -711,6 +711,27 @@ The keyctl syscall functions are:
> >       The assumed authoritative key is inherited across fork and exec.
> >  
> >  
> > + (*) Get the LSM security context attached to a key.
> > +
> > +	long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
> > +		    size_t buflen)
> > +
> > +     This function returns a string that represents the LSM security context
> > +     attached to a key in the buffer provided.
> > +
> > +     Unless there's an error, it always returns the amount of data it could
> > +     produce, even if that's too big for the buffer, but it won't copy more
> > +     than requested to userspace. If the buffer pointer is NULL then no copy
> > +     will take place.
> > +
> > +     A NUL character is included at the end of the string if the buffer is
> > +     sufficiently big.  This is included in the returned count.  If no LSM
> > is
> > +     in force then an empty string will be returned.
> > +
> > +     A process must have view permission on the key for this function to be
> > +     successful.
> > +
> > +
> >  ===============
> >  KERNEL SERVICES
> >  ===============
> > diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
> > index 3365945..656ee6b 100644
> > --- a/include/linux/keyctl.h
> > +++ b/include/linux/keyctl.h
> > @@ -49,5 +49,6 @@
> >  #define KEYCTL_SET_REQKEY_KEYRING	14	/* set default request-key keyring */
> >  #define KEYCTL_SET_TIMEOUT		15	/* set key timeout */
> >  #define KEYCTL_ASSUME_AUTHORITY		16	/* assume request_key() authorisation */
> > +#define KEYCTL_GET_SECURITY		17	/* get key security label */
> >  
> >  #endif /*  _LINUX_KEYCTL_H */
> > diff --git a/include/linux/security.h b/include/linux/security.h
> > index ac05083..8d9e946 100644
> > --- a/include/linux/security.h
> > +++ b/include/linux/security.h
> > @@ -959,6 +959,17 @@ struct request_sock;
> >   *	@perm describes the combination of permissions required of this key.
> >   *	Return 1 if permission granted, 0 if permission denied and -ve it the
> >   *      normal permissions model should be effected.
> > + * @key_getsecurity:
> 
> If I contradict what I said last time around, well, I've seen
> more of what's going on since then. (insert smiley here)
> 
> I think that this should be key_getsecctx(). That would get you
> what you need from SELinux and Smack. Unfortunately, there is no
> precedent for interfaces that return the secctx, while the are
> places in networking and audit (audit needs to be converted off
> of SELinux calls to LSM calls) that call getsecid() interfaces
> and later use security_secid_to_secctx() to get the "printable"
> version. So, key_getsecid() is the interface to introduce if you
> want to be consistant, and pass the result to
> security_secid_to_secctx() to get the data you're looking for.

inode_getsecurity and getprocattr directly return the strings.
Admittedly, the whole interface could be cleaned up and made far more
consistent, but I don't think he necessarily has to go through the
getsecid + secid_to_secctx sequence if he only wants the secctx.

> > + *	Get a textual representation of the security context attached to a key
> > + *	for the purposes of honouring KEYCTL_GETSECURITY.  This function
> > + *	allocates the storage for the NUL-terminated string and the caller
> > + *	should free it.
> > + *	@key points to the key to be queried.
> > + *	@_buffer points to a pointer that should be set to point to the
> > + *	 resulting string (if no label or an error occurs).
> > + *	Return the length of the string (including terminating NUL) or -ve if
> > + *      an error.
> > + *	May also return 0 (and a NULL buffer pointer) if there is no label.
> >   *
> >   * Security hooks affecting all System V IPC operations.
> >   *
> > @@ -1437,7 +1448,7 @@ struct security_operations {
> >  	int (*key_permission)(key_ref_t key_ref,
> >  			      struct task_struct *context,
> >  			      key_perm_t perm);
> > -
> > +	int (*key_getsecurity)(struct key *key, char **_buffer);
> >  #endif	/* CONFIG_KEYS */
> >  
> >  };
> > @@ -2567,6 +2578,7 @@ int security_key_alloc(struct key *key, struct
> > task_struct *tsk, unsigned long f
> >  void security_key_free(struct key *key);
> >  int security_key_permission(key_ref_t key_ref,
> >  			    struct task_struct *context, key_perm_t perm);
> > +int security_key_getsecurity(struct key *key, char **_buffer);
> >  
> >  #else
> >  
> > @@ -2588,6 +2600,12 @@ static inline int security_key_permission(key_ref_t
> > key_ref,
> >  	return 0;
> >  }
> >  
> > +static inline int security_key_getsecurity(struct key *key, char **_buffer)
> > +{
> > +	*_buffer = NULL;
> > +	return 0;
> > +}
> > +
> >  #endif
> >  #endif /* CONFIG_KEYS */
> >  
> > diff --git a/security/dummy.c b/security/dummy.c
> > index 6d895ad..7993b30 100644
> > --- a/security/dummy.c
> > +++ b/security/dummy.c
> > @@ -949,6 +949,13 @@ static inline int dummy_key_permission(key_ref_t
> > key_ref,
> >  {
> >  	return 0;
> >  }
> > +
> > +static int dummy_key_getsecurity(struct key *key, char **_buffer)
> > +{
> > +	*_buffer = NULL;
> > +	return 0;
> > +}
> > +
> >  #endif /* CONFIG_KEYS */
> >  
> >  struct security_operations dummy_security_ops;
> > @@ -1133,6 +1140,7 @@ void security_fixup_ops (struct security_operations
> > *ops)
> >  	set_to_dummy_if_null(ops, key_alloc);
> >  	set_to_dummy_if_null(ops, key_free);
> >  	set_to_dummy_if_null(ops, key_permission);
> > +	set_to_dummy_if_null(ops, key_getsecurity);
> >  #endif	/* CONFIG_KEYS */
> >  
> >  }
> > diff --git a/security/keys/compat.c b/security/keys/compat.c
> > index e10ec99..c766c68 100644
> > --- a/security/keys/compat.c
> > +++ b/security/keys/compat.c
> > @@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
> >  	case KEYCTL_ASSUME_AUTHORITY:
> >  		return keyctl_assume_authority(arg2);
> >  
> > +	case KEYCTL_GET_SECURITY:
> > +		return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
> > +
> >  	default:
> >  		return -EOPNOTSUPP;
> >  	}
> > diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
> > index 1698bf9..56e963b 100644
> > --- a/security/keys/keyctl.c
> > +++ b/security/keys/keyctl.c
> > @@ -20,6 +20,7 @@
> >  #include <linux/string.h>
> >  #include <linux/err.h>
> >  #include <linux/vmalloc.h>
> > +#include <linux/security.h>
> >  #include <asm/uaccess.h>
> >  #include "internal.h"
> >  
> > @@ -1080,6 +1081,66 @@ error:
> >  
> >  } /* end keyctl_assume_authority() */
> >  
> > +/*
> > + * get the security label of a key
> > + * - the key must grant us view permission
> > + * - if there's a buffer, we place up to buflen bytes of data into it
> > + * - unless there's an error, we return the amount of information available,
> > + *   irrespective of how much we may have copied (including the terminal
> > NUL)
> > + * - implements keyctl(KEYCTL_GET_SECURITY)
> > + */
> > +long keyctl_get_security(key_serial_t keyid,
> > +			 char __user *buffer,
> > +			 size_t buflen)
> > +{
> > +	struct key *key, *instkey;
> > +	key_ref_t key_ref;
> > +	char *context;
> > +	long ret;
> > +
> > +	key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
> > +	if (IS_ERR(key_ref)) {
> > +		if (PTR_ERR(key_ref) != -EACCES)
> > +			return PTR_ERR(key_ref);
> > +
> > +		/* viewing a key under construction is also permitted if we
> > +		 * have the authorisation token handy */
> > +		instkey = key_get_instantiation_authkey(keyid);
> > +		if (IS_ERR(instkey))
> > +			return PTR_ERR(key_ref);
> > +		key_put(instkey);
> > +
> > +		key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
> > +		if (IS_ERR(key_ref))
> > +			return PTR_ERR(key_ref);
> > +	}
> > +
> > +	key = key_ref_to_ptr(key_ref);
> > +	ret = security_key_getsecurity(key, &context);
> > +	if (ret == 0) {
> > +		/* if no information was returned, give userspace an empty
> > +		 * string */
> > +		ret = 1;
> > +		if (buffer && buflen > 0 &&
> > +		    copy_to_user(buffer, "", 1) != 0)
> > +			ret = -EFAULT;
> > +	} else if (ret > 0) {
> > +		/* return as much data as there's room for */
> > +		if (buffer && buflen > 0) {
> > +			if (buflen > ret)
> > +				buflen = ret;
> > +
> > +			if (copy_to_user(buffer, context, buflen) != 0)
> > +				ret = -EFAULT;
> > +		}
> > +
> > +		kfree(context);
> > +	}
> > +
> > +	key_ref_put(key_ref);
> > +	return ret;
> > +}
> > +
> > 
> >
> /*****************************************************************************/
> >  /*
> >   * the key control system call
> > @@ -1160,6 +1221,11 @@ asmlinkage long sys_keyctl(int option, unsigned long
> > arg2, unsigned long arg3,
> >  	case KEYCTL_ASSUME_AUTHORITY:
> >  		return keyctl_assume_authority((key_serial_t) arg2);
> >  
> > +	case KEYCTL_GET_SECURITY:
> > +		return keyctl_get_security((key_serial_t) arg2,
> > +					   (char *) arg3,
> > +					   (size_t) arg4);
> > +
> >  	default:
> >  		return -EOPNOTSUPP;
> >  	}
> > diff --git a/security/security.c b/security/security.c
> > index 0e1f1f1..16213e3 100644
> > --- a/security/security.c
> > +++ b/security/security.c
> > @@ -1079,4 +1079,9 @@ int security_key_permission(key_ref_t key_ref,
> >  	return security_ops->key_permission(key_ref, context, perm);
> >  }
> >  
> > +int security_key_getsecurity(struct key *key, char **_buffer)
> > +{
> > +	return security_ops->key_getsecurity(key, _buffer);
> > +}
> > +
> >  #endif	/* CONFIG_KEYS */
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 9f3124b..bd4cfab 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -4768,6 +4768,20 @@ static int selinux_key_permission(key_ref_t key_ref,
> >  			    SECCLASS_KEY, perm, NULL);
> >  }
> >  
> > +static int selinux_key_getsecurity(struct key *key, char **_buffer)
> > +{
> > +	struct key_security_struct *ksec = key->security;
> > +	char *context = NULL;
> > +	unsigned len;
> > +	int rc;
> > +
> > +	rc = security_sid_to_context(ksec->sid, &context, &len);
> > +	if (!rc)
> > +		rc = len;
> > +	*_buffer = context;
> > +	return rc;
> > +}
> > +
> >  #endif
> >  
> >  static struct security_operations selinux_ops = {
> > @@ -4943,9 +4957,10 @@ static struct security_operations selinux_ops = {
> >  #endif
> >  
> >  #ifdef CONFIG_KEYS
> > -	.key_alloc =                    selinux_key_alloc,
> > -	.key_free =                     selinux_key_free,
> > -	.key_permission =               selinux_key_permission,
> > +	.key_alloc =			selinux_key_alloc,
> > +	.key_free =			selinux_key_free,
> > +	.key_permission =		selinux_key_permission,
> > +	.key_getsecurity =		selinux_key_getsecurity,
> >  #endif
> >  };
> >  
> > 
> > 
> > 
> 
> 
> Casey Schaufler
> casey@schaufler-ca.com
> 
> --
> 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.
-- 
Stephen Smalley
National Security Agency


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

* Re: [PATCH 4/7] KEYS: Add keyctl function to get a security label
  2007-12-05 20:12   ` Casey Schaufler
  2007-12-05 20:38     ` Stephen Smalley
@ 2007-12-06  1:28     ` David Howells
  2007-12-06  1:40       ` Casey Schaufler
  1 sibling, 1 reply; 14+ messages in thread
From: David Howells @ 2007-12-06  1:28 UTC (permalink / raw)
  To: Stephen Smalley, Daniel J Walsh
  Cc: dhowells, casey, viro, hch, Trond.Myklebust, linux-kernel,
	selinux, linux-security-module

Stephen Smalley <sds@tycho.nsa.gov> wrote:

> inode_getsecurity and getprocattr directly return the strings.
> Admittedly, the whole interface could be cleaned up and made far more
> consistent, but I don't think he necessarily has to go through the
> getsecid + secid_to_secctx sequence if he only wants the secctx.

It's what Daniel Walsh wanted.

David

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

* Re: [PATCH 4/7] KEYS: Add keyctl function to get a security label
  2007-12-06  1:28     ` David Howells
@ 2007-12-06  1:40       ` Casey Schaufler
  0 siblings, 0 replies; 14+ messages in thread
From: Casey Schaufler @ 2007-12-06  1:40 UTC (permalink / raw)
  To: David Howells, Stephen Smalley, Daniel J Walsh
  Cc: dhowells, casey, viro, hch, Trond.Myklebust, linux-kernel,
	selinux, linux-security-module


--- David Howells <dhowells@redhat.com> wrote:

> Stephen Smalley <sds@tycho.nsa.gov> wrote:
> 
> > inode_getsecurity and getprocattr directly return the strings.
> > Admittedly, the whole interface could be cleaned up and made far more
> > consistent, but I don't think he necessarily has to go through the
> > getsecid + secid_to_secctx sequence if he only wants the secctx.
> 
> It's what Daniel Walsh wanted.

Name dropper. And we don't have a convention, really. So go ahead
with key_getsecurity or key_getsecctx, as you choose. At some point
we should either change inode_getsecurity to inode_getsecctx or
secid_to_secctx to secid_to_security. Not the problem of the day.



Casey Schaufler
casey@schaufler-ca.com

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

* Re: [PATCH 5/7] Security: Change current->fs[ug]id to current_fs[ug]id()
  2007-12-05 19:37 ` [PATCH 5/7] Security: Change current->fs[ug]id to current_fs[ug]id() David Howells
@ 2007-12-07 17:44   ` Serge E. Hallyn
  2007-12-08  0:53   ` David Howells
  1 sibling, 0 replies; 14+ messages in thread
From: Serge E. Hallyn @ 2007-12-07 17:44 UTC (permalink / raw)
  To: David Howells
  Cc: viro, hch, Trond.Myklebust, sds, casey, linux-kernel, selinux,
	linux-security-module

Quoting David Howells (dhowells@redhat.com):
> Change current->fs[ug]id to current_fs[ug]id() so that fsgid and fsuid can be
> separated from the task_struct.

Hi David,

this one looks straightforward enough.

Unfortunately I don't have patch 6.  In either of my
linux-security-module-receiving mailboxes, so I don't think I
accidentally deleted it :)

Could you resend patch 6?

thanks,
-serge

> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
> 
>  arch/ia64/kernel/perfmon.c                |    4 ++--
>  arch/powerpc/platforms/cell/spufs/inode.c |    4 ++--
>  drivers/isdn/capi/capifs.c                |    4 ++--
>  drivers/usb/core/inode.c                  |    4 ++--
>  fs/9p/fid.c                               |    2 +-
>  fs/9p/vfs_inode.c                         |    4 ++--
>  fs/9p/vfs_super.c                         |    4 ++--
>  fs/affs/inode.c                           |    4 ++--
>  fs/anon_inodes.c                          |    4 ++--
>  fs/attr.c                                 |    4 ++--
>  fs/bfs/dir.c                              |    4 ++--
>  fs/cifs/cifsproto.h                       |    2 +-
>  fs/cifs/dir.c                             |   12 ++++++------
>  fs/cifs/inode.c                           |    8 ++++----
>  fs/cifs/misc.c                            |    4 ++--
>  fs/coda/cache.c                           |    6 +++---
>  fs/coda/upcall.c                          |    4 ++--
>  fs/devpts/inode.c                         |    4 ++--
>  fs/dquot.c                                |    2 +-
>  fs/exec.c                                 |    4 ++--
>  fs/ext2/balloc.c                          |    2 +-
>  fs/ext2/ialloc.c                          |    4 ++--
>  fs/ext2/ioctl.c                           |    2 +-
>  fs/ext3/balloc.c                          |    2 +-
>  fs/ext3/ialloc.c                          |    4 ++--
>  fs/ext4/balloc.c                          |    2 +-
>  fs/ext4/ialloc.c                          |    4 ++--
>  fs/fuse/dev.c                             |    4 ++--
>  fs/gfs2/inode.c                           |   10 +++++-----
>  fs/hfs/inode.c                            |    4 ++--
>  fs/hfsplus/inode.c                        |    4 ++--
>  fs/hpfs/namei.c                           |   24 ++++++++++++------------
>  fs/hugetlbfs/inode.c                      |   16 ++++++++--------
>  fs/jffs2/fs.c                             |    4 ++--
>  fs/jfs/jfs_inode.c                        |    4 ++--
>  fs/locks.c                                |    2 +-
>  fs/minix/bitmap.c                         |    4 ++--
>  fs/namei.c                                |    8 ++++----
>  fs/nfsd/vfs.c                             |    4 ++--
>  fs/ocfs2/dlm/dlmfs.c                      |    8 ++++----
>  fs/ocfs2/namei.c                          |    4 ++--
>  fs/pipe.c                                 |    4 ++--
>  fs/posix_acl.c                            |    4 ++--
>  fs/ramfs/inode.c                          |    4 ++--
>  fs/reiserfs/namei.c                       |    4 ++--
>  fs/sysv/ialloc.c                          |    4 ++--
>  fs/udf/ialloc.c                           |    4 ++--
>  fs/udf/namei.c                            |    2 +-
>  fs/ufs/ialloc.c                           |    4 ++--
>  fs/xfs/linux-2.6/xfs_linux.h              |    4 ++--
>  fs/xfs/xfs_acl.c                          |    6 +++---
>  fs/xfs/xfs_attr.c                         |    2 +-
>  fs/xfs/xfs_inode.c                        |    6 +++---
>  fs/xfs/xfs_vnodeops.c                     |    8 ++++----
>  include/linux/fs.h                        |    2 +-
>  include/linux/sched.h                     |    3 +++
>  ipc/mqueue.c                              |    4 ++--
>  kernel/cgroup.c                           |    4 ++--
>  mm/shmem.c                                |    8 ++++----
>  net/9p/client.c                           |    2 +-
>  net/socket.c                              |    4 ++--
>  net/sunrpc/auth.c                         |    8 ++++----
>  security/commoncap.c                      |    8 ++++----
>  security/keys/key.c                       |    2 +-
>  security/keys/keyctl.c                    |    2 +-
>  security/keys/request_key.c               |   10 +++++-----
>  security/keys/request_key_auth.c          |    2 +-
>  67 files changed, 163 insertions(+), 160 deletions(-)
> 
> diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
> index 73e7c2e..ef383d9 100644
> --- a/arch/ia64/kernel/perfmon.c
> +++ b/arch/ia64/kernel/perfmon.c
> @@ -2206,8 +2206,8 @@ pfm_alloc_fd(struct file **cfile)
>  	DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode));
> 
>  	inode->i_mode = S_IFCHR|S_IRUGO;
> -	inode->i_uid  = current->fsuid;
> -	inode->i_gid  = current->fsgid;
> +	inode->i_uid  = current_fsuid();
> +	inode->i_gid  = current_fsgid();
> 
>  	sprintf(name, "[%lu]", inode->i_ino);
>  	this.name = name;
> diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
> index c0e968a..4efe7bf 100644
> --- a/arch/powerpc/platforms/cell/spufs/inode.c
> +++ b/arch/powerpc/platforms/cell/spufs/inode.c
> @@ -85,8 +85,8 @@ spufs_new_inode(struct super_block *sb, int mode)
>  		goto out;
> 
>  	inode->i_mode = mode;
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = current_fsgid();
>  	inode->i_blocks = 0;
>  	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
>  out:
> diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
> index 2dd1b57..26b9aea 100644
> --- a/drivers/isdn/capi/capifs.c
> +++ b/drivers/isdn/capi/capifs.c
> @@ -148,8 +148,8 @@ void capifs_new_ncci(unsigned int number, dev_t device)
>  	if (!inode)
>  		return;
>  	inode->i_ino = number+2;
> -	inode->i_uid = config.setuid ? config.uid : current->fsuid;
> -	inode->i_gid = config.setgid ? config.gid : current->fsgid;
> +	inode->i_uid = config.setuid ? config.uid : current_fsuid();
> +	inode->i_gid = config.setgid ? config.gid : current_fsgid();
>  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
>  	init_special_inode(inode, S_IFCHR|config.mode, device);
>  	//inode->i_op = &capifs_file_inode_operations;
> diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
> index cd4f111..9173eae 100644
> --- a/drivers/usb/core/inode.c
> +++ b/drivers/usb/core/inode.c
> @@ -246,8 +246,8 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
> 
>  	if (inode) {
>  		inode->i_mode = mode;
> -		inode->i_uid = current->fsuid;
> -		inode->i_gid = current->fsgid;
> +		inode->i_uid = current_fsuid();
> +		inode->i_gid = current_fsgid();
>  		inode->i_blocks = 0;
>  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
>  		switch (mode & S_IFMT) {
> diff --git a/fs/9p/fid.c b/fs/9p/fid.c
> index b364da7..cd7799c 100644
> --- a/fs/9p/fid.c
> +++ b/fs/9p/fid.c
> @@ -121,7 +121,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
>  	switch (access) {
>  	case V9FS_ACCESS_SINGLE:
>  	case V9FS_ACCESS_USER:
> -		uid = current->fsuid;
> +		uid = current_fsuid();
>  		any = 0;
>  		break;
> 
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 23581bc..b6d7fc9 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -202,8 +202,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
>  	inode = new_inode(sb);
>  	if (inode) {
>  		inode->i_mode = mode;
> -		inode->i_uid = current->fsuid;
> -		inode->i_gid = current->fsgid;
> +		inode->i_uid = current_fsuid();
> +		inode->i_gid = current_fsgid();
>  		inode->i_blocks = 0;
>  		inode->i_rdev = 0;
>  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
> diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
> index 678c02f..465520d 100644
> --- a/fs/9p/vfs_super.c
> +++ b/fs/9p/vfs_super.c
> @@ -112,8 +112,8 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
>  	struct v9fs_session_info *v9ses = NULL;
>  	struct p9_stat *st = NULL;
>  	int mode = S_IRWXUGO | S_ISVTX;
> -	uid_t uid = current->fsuid;
> -	gid_t gid = current->fsgid;
> +	uid_t uid = current_fsuid();
> +	gid_t gid = current_fsgid();
>  	struct p9_fid *fid;
>  	int retval = 0;
> 
> diff --git a/fs/affs/inode.c b/fs/affs/inode.c
> index 4609a6c..fb84ebc 100644
> --- a/fs/affs/inode.c
> +++ b/fs/affs/inode.c
> @@ -305,8 +305,8 @@ affs_new_inode(struct inode *dir)
>  	mark_buffer_dirty_inode(bh, inode);
>  	affs_brelse(bh);
> 
> -	inode->i_uid     = current->fsuid;
> -	inode->i_gid     = current->fsgid;
> +	inode->i_uid     = current_fsuid();
> +	inode->i_gid     = current_fsgid();
>  	inode->i_ino     = block;
>  	inode->i_nlink   = 1;
>  	inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
> diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
> index 2332188..a2f6a13 100644
> --- a/fs/anon_inodes.c
> +++ b/fs/anon_inodes.c
> @@ -162,8 +162,8 @@ static struct inode *anon_inode_mkinode(void)
>  	 */
>  	inode->i_state = I_DIRTY;
>  	inode->i_mode = S_IRUSR | S_IWUSR;
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = current_fsgid();
>  	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
>  	return inode;
>  }
> diff --git a/fs/attr.c b/fs/attr.c
> index 966b73e..117cca7 100644
> --- a/fs/attr.c
> +++ b/fs/attr.c
> @@ -29,13 +29,13 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
> 
>  	/* Make sure a caller can chown. */
>  	if ((ia_valid & ATTR_UID) &&
> -	    (current->fsuid != inode->i_uid ||
> +	    (current_fsuid() != inode->i_uid ||
>  	     attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
>  		goto error;
> 
>  	/* Make sure caller can chgrp. */
>  	if ((ia_valid & ATTR_GID) &&
> -	    (current->fsuid != inode->i_uid ||
> +	    (current_fsuid() != inode->i_uid ||
>  	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
>  	    !capable(CAP_CHOWN))
>  		goto error;
> diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
> index 1fd056d..499c531 100644
> --- a/fs/bfs/dir.c
> +++ b/fs/bfs/dir.c
> @@ -104,8 +104,8 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
>  	}
>  	set_bit(ino, info->si_imap);
>  	info->si_freei--;
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current_fsgid();
>  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
>  	inode->i_blocks = 0;
>  	inode->i_op = &bfs_file_inops;
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 8350eec..1c659db 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -39,7 +39,7 @@ extern int smb_send(struct socket *, struct smb_hdr *,
>  			unsigned int /* length */ , struct sockaddr *);
>  extern unsigned int _GetXid(void);
>  extern void _FreeXid(unsigned int);
> -#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
> +#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current_fsuid()));
>  #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
>  extern char *build_path_from_dentry(struct dentry *);
>  extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> index 37dc97a..728726a 100644
> --- a/fs/cifs/dir.c
> +++ b/fs/cifs/dir.c
> @@ -211,8 +211,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
>  			mode &= ~current->fs->umask;
>  			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
>  				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
> -					(__u64)current->fsuid,
> -					(__u64)current->fsgid,
> +					(__u64)current_fsuid(),
> +					(__u64)current_fsgid(),
>  					0 /* dev */,
>  					cifs_sb->local_nls,
>  					cifs_sb->mnt_cifs_flags &
> @@ -246,8 +246,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
>  				if ((oplock & CIFS_CREATE_ACTION) &&
>  				    (cifs_sb->mnt_cifs_flags &
>  				     CIFS_MOUNT_SET_UID)) {
> -					newinode->i_uid = current->fsuid;
> -					newinode->i_gid = current->fsgid;
> +					newinode->i_uid = current_fsuid();
> +					newinode->i_gid = current_fsgid();
>  				}
>  			}
>  		}
> @@ -340,8 +340,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
>  		mode &= ~current->fs->umask;
>  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
>  			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
> -				mode, (__u64)current->fsuid,
> -				(__u64)current->fsgid,
> +				mode, (__u64)current_fsuid(),
> +				(__u64)current_fsgid(),
>  				device_number, cifs_sb->local_nls,
>  				cifs_sb->mnt_cifs_flags &
>  					CIFS_MOUNT_MAP_SPECIAL_CHR);
> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> index e915eb1..8040b1b 100644
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -1031,8 +1031,8 @@ mkdir_get_info:
>  			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
>  				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
>  						    mode,
> -						    (__u64)current->fsuid,
> -						    (__u64)current->fsgid,
> +						    (__u64)current_fsuid(),
> +						    (__u64)current_fsgid(),
>  						    0 /* dev_t */,
>  						    cifs_sb->local_nls,
>  						    cifs_sb->mnt_cifs_flags &
> @@ -1055,9 +1055,9 @@ mkdir_get_info:
>  				if (cifs_sb->mnt_cifs_flags &
>  				     CIFS_MOUNT_SET_UID) {
>  					direntry->d_inode->i_uid =
> -						current->fsuid;
> +						current_fsuid();
>  					direntry->d_inode->i_gid =
> -						current->fsgid;
> +						current_fsgid();
>  				}
>  			}
>  		}
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index 15546c2..b862231 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -351,13 +351,13 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
>  		/*  BB Add support for establishing new tCon and SMB Session  */
>  		/*      with userid/password pairs found on the smb session   */
>  		/*	for other target tcp/ip addresses 		BB    */
> -				if (current->fsuid != treeCon->ses->linux_uid) {
> +				if (current_fsuid() != treeCon->ses->linux_uid) {
>  					cFYI(1, ("Multiuser mode and UID "
>  						 "did not match tcon uid"));
>  					read_lock(&GlobalSMBSeslock);
>  					list_for_each(temp_item, &GlobalSMBSessionList) {
>  						ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
> -						if (ses->linux_uid == current->fsuid) {
> +						if (ses->linux_uid == current_fsuid()) {
>  							if (ses->server == treeCon->ses->server) {
>  								cFYI(1, ("found matching uid substitute right smb_uid"));
>  								buffer->Uid = ses->Suid;
> diff --git a/fs/coda/cache.c b/fs/coda/cache.c
> index 8a23703..a5bf577 100644
> --- a/fs/coda/cache.c
> +++ b/fs/coda/cache.c
> @@ -32,8 +32,8 @@ void coda_cache_enter(struct inode *inode, int mask)
>  	struct coda_inode_info *cii = ITOC(inode);
> 
>  	cii->c_cached_epoch = atomic_read(&permission_epoch);
> -	if (cii->c_uid != current->fsuid) {
> -                cii->c_uid = current->fsuid;
> +	if (cii->c_uid != current_fsuid()) {
> +		cii->c_uid = current_fsuid();
>                  cii->c_cached_perm = mask;
>          } else
>                  cii->c_cached_perm |= mask;
> @@ -60,7 +60,7 @@ int coda_cache_check(struct inode *inode, int mask)
>          int hit;
>  	
>          hit = (mask & cii->c_cached_perm) == mask &&
> -		cii->c_uid == current->fsuid &&
> +		cii->c_uid == current_fsuid() &&
>  		cii->c_cached_epoch == atomic_read(&permission_epoch);
> 
>          return hit;
> diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
> index 359e531..806e6aa 100644
> --- a/fs/coda/upcall.c
> +++ b/fs/coda/upcall.c
> @@ -54,9 +54,9 @@ static void *alloc_upcall(int opcode, int size)
>  	inp->ih.pgid = task_pgrp_nr(current);
>  #ifdef CONFIG_CODA_FS_OLD_API
>  	memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
> -	inp->ih.cred.cr_fsuid = current->fsuid;
> +	inp->ih.cred.cr_fsuid = current_fsuid();
>  #else
> -	inp->ih.uid = current->fsuid;
> +	inp->ih.uid = current_fsuid();
>  #endif
>  	return (void*)inp;
>  }
> diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
> index 06ef9a2..1c9ffd9 100644
> --- a/fs/devpts/inode.c
> +++ b/fs/devpts/inode.c
> @@ -172,8 +172,8 @@ int devpts_pty_new(struct tty_struct *tty)
>  		return -ENOMEM;
> 
>  	inode->i_ino = number+2;
> -	inode->i_uid = config.setuid ? config.uid : current->fsuid;
> -	inode->i_gid = config.setgid ? config.gid : current->fsgid;
> +	inode->i_uid = config.setuid ? config.uid : current_fsuid();
> +	inode->i_gid = config.setgid ? config.gid : current_fsgid();
>  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
>  	init_special_inode(inode, S_IFCHR|config.mode, device);
>  	inode->i_private = tty;
> diff --git a/fs/dquot.c b/fs/dquot.c
> index 2809768..3dc58a8 100644
> --- a/fs/dquot.c
> +++ b/fs/dquot.c
> @@ -837,7 +837,7 @@ static inline int need_print_warning(struct dquot *dquot)
> 
>  	switch (dquot->dq_type) {
>  		case USRQUOTA:
> -			return current->fsuid == dquot->dq_id;
> +			return current_fsuid() == dquot->dq_id;
>  		case GRPQUOTA:
>  			return in_group_p(dquot->dq_id);
>  	}
> diff --git a/fs/exec.c b/fs/exec.c
> index 282240a..a09ce1b 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -1678,7 +1678,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
>  	struct inode * inode;
>  	struct file * file;
>  	int retval = 0;
> -	int fsuid = current->fsuid;
> +	int fsuid = current_fsuid();
>  	int flag = 0;
>  	int ispipe = 0;
>  	unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
> @@ -1784,7 +1784,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
>  	 * Dont allow local users get cute and trick others to coredump
>  	 * into their pre-created files:
>  	 */
> -	if (inode->i_uid != current->fsuid)
> +	if (inode->i_uid != current_fsuid())
>  		goto close_fail;
>  	if (!file->f_op)
>  		goto close_fail;
> diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
> index 377ad17..bbddd14 100644
> --- a/fs/ext2/balloc.c
> +++ b/fs/ext2/balloc.c
> @@ -1128,7 +1128,7 @@ static int ext2_has_free_blocks(struct ext2_sb_info *sbi)
>  	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
>  	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
>  	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
> -		sbi->s_resuid != current->fsuid &&
> +		sbi->s_resuid != current_fsuid() &&
>  		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
>  		return 0;
>  	}
> diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
> index 5deb8b7..1d020a9 100644
> --- a/fs/ext2/ialloc.c
> +++ b/fs/ext2/ialloc.c
> @@ -554,7 +554,7 @@ got:
> 
>  	sb->s_dirt = 1;
>  	mark_buffer_dirty(bh2);
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	if (test_opt (sb, GRPID))
>  		inode->i_gid = dir->i_gid;
>  	else if (dir->i_mode & S_ISGID) {
> @@ -562,7 +562,7 @@ got:
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else
> -		inode->i_gid = current->fsgid;
> +		inode->i_gid = current_fsgid();
>  	inode->i_mode = mode;
> 
>  	inode->i_ino = ino;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 320b2cb..f5fdb95 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -105,7 +105,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
>  		if (IS_RDONLY(inode))
>  			return -EROFS;
> 
> -		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
> +		if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
>  			return -EACCES;
> 
>  		if (get_user(rsv_window_size, (int __user *)arg))
> diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
> index a8ba7e8..55e39a3 100644
> --- a/fs/ext3/balloc.c
> +++ b/fs/ext3/balloc.c
> @@ -1360,7 +1360,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
>  	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
>  	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
>  	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
> -		sbi->s_resuid != current->fsuid &&
> +		sbi->s_resuid != current_fsuid() &&
>  		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
>  		return 0;
>  	}
> diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
> index 1bc8cd8..fe20718 100644
> --- a/fs/ext3/ialloc.c
> +++ b/fs/ext3/ialloc.c
> @@ -543,7 +543,7 @@ got:
>  		percpu_counter_inc(&sbi->s_dirs_counter);
>  	sb->s_dirt = 1;
> 
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	if (test_opt (sb, GRPID))
>  		inode->i_gid = dir->i_gid;
>  	else if (dir->i_mode & S_ISGID) {
> @@ -551,7 +551,7 @@ got:
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else
> -		inode->i_gid = current->fsgid;
> +		inode->i_gid = current_fsgid();
>  	inode->i_mode = mode;
> 
>  	inode->i_ino = ino;
> diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
> index 71ee95e..a67d6bc 100644
> --- a/fs/ext4/balloc.c
> +++ b/fs/ext4/balloc.c
> @@ -1480,7 +1480,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
>  	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
>  	root_blocks = ext4_r_blocks_count(sbi->s_es);
>  	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
> -		sbi->s_resuid != current->fsuid &&
> +		sbi->s_resuid != current_fsuid() &&
>  		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
>  		return 0;
>  	}
> diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
> index c61f37f..37e95d2 100644
> --- a/fs/ext4/ialloc.c
> +++ b/fs/ext4/ialloc.c
> @@ -674,7 +674,7 @@ got:
>  		percpu_counter_inc(&sbi->s_dirs_counter);
>  	sb->s_dirt = 1;
> 
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	if (test_opt (sb, GRPID))
>  		inode->i_gid = dir->i_gid;
>  	else if (dir->i_mode & S_ISGID) {
> @@ -682,7 +682,7 @@ got:
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else
> -		inode->i_gid = current->fsgid;
> +		inode->i_gid = current_fsgid();
>  	inode->i_mode = mode;
> 
>  	inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index db534bc..471a256 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -79,8 +79,8 @@ static void __fuse_put_request(struct fuse_req *req)
> 
>  static void fuse_req_init_context(struct fuse_req *req)
>  {
> -	req->in.h.uid = current->fsuid;
> -	req->in.h.gid = current->fsgid;
> +	req->in.h.uid = current_fsuid();
> +	req->in.h.gid = current_fsgid();
>  	req->in.h.pid = current->pid;
>  }
> 
> diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> index 5f6dc32..7719132 100644
> --- a/fs/gfs2/inode.c
> +++ b/fs/gfs2/inode.c
> @@ -688,18 +688,18 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
>  	    (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
>  		if (S_ISDIR(*mode))
>  			*mode |= S_ISUID;
> -		else if (dip->i_inode.i_uid != current->fsuid)
> +		else if (dip->i_inode.i_uid != current_fsuid())
>  			*mode &= ~07111;
>  		*uid = dip->i_inode.i_uid;
>  	} else
> -		*uid = current->fsuid;
> +		*uid = current_fsuid();
> 
>  	if (dip->i_inode.i_mode & S_ISGID) {
>  		if (S_ISDIR(*mode))
>  			*mode |= S_ISGID;
>  		*gid = dip->i_inode.i_gid;
>  	} else
> -		*gid = current->fsgid;
> +		*gid = current_fsgid();
>  }
> 
>  static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
> @@ -1108,8 +1108,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
>  		return -EPERM;
> 
>  	if ((dip->i_inode.i_mode & S_ISVTX) &&
> -	    dip->i_inode.i_uid != current->fsuid &&
> -	    ip->i_inode.i_uid != current->fsuid && !capable(CAP_FOWNER))
> +	    dip->i_inode.i_uid != current_fsuid() &&
> +	    ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER))
>  		return -EPERM;
> 
>  	if (IS_APPEND(&dip->i_inode))
> diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
> index 97f8446..29caee5 100644
> --- a/fs/hfs/inode.c
> +++ b/fs/hfs/inode.c
> @@ -155,8 +155,8 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
>  	hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
>  	inode->i_ino = HFS_SB(sb)->next_id++;
>  	inode->i_mode = mode;
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = current_fsgid();
>  	inode->i_nlink = 1;
>  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
>  	HFS_I(inode)->flags = 0;
> diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
> index 37744cf..af54c28 100644
> --- a/fs/hfsplus/inode.c
> +++ b/fs/hfsplus/inode.c
> @@ -312,8 +312,8 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
> 
>  	inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
>  	inode->i_mode = mode;
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = current_fsgid();
>  	inode->i_nlink = 1;
>  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
>  	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
> diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
> index d256559..2af4578 100644
> --- a/fs/hpfs/namei.c
> +++ b/fs/hpfs/namei.c
> @@ -92,11 +92,11 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
>  	inc_nlink(dir);
>  	insert_inode_hash(result);
> 
> -	if (result->i_uid != current->fsuid ||
> -	    result->i_gid != current->fsgid ||
> +	if (result->i_uid != current_fsuid() ||
> +	    result->i_gid != current_fsgid() ||
>  	    result->i_mode != (mode | S_IFDIR)) {
> -		result->i_uid = current->fsuid;
> -		result->i_gid = current->fsgid;
> +		result->i_uid = current_fsuid();
> +		result->i_gid = current_fsgid();
>  		result->i_mode = mode | S_IFDIR;
>  		hpfs_write_inode_nolock(result);
>  	}
> @@ -184,11 +184,11 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
> 
>  	insert_inode_hash(result);
> 
> -	if (result->i_uid != current->fsuid ||
> -	    result->i_gid != current->fsgid ||
> +	if (result->i_uid != current_fsuid() ||
> +	    result->i_gid != current_fsgid() ||
>  	    result->i_mode != (mode | S_IFREG)) {
> -		result->i_uid = current->fsuid;
> -		result->i_gid = current->fsgid;
> +		result->i_uid = current_fsuid();
> +		result->i_gid = current_fsgid();
>  		result->i_mode = mode | S_IFREG;
>  		hpfs_write_inode_nolock(result);
>  	}
> @@ -247,8 +247,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
>  	result->i_mtime.tv_nsec = 0;
>  	result->i_atime.tv_nsec = 0;
>  	hpfs_i(result)->i_ea_size = 0;
> -	result->i_uid = current->fsuid;
> -	result->i_gid = current->fsgid;
> +	result->i_uid = current_fsuid();
> +	result->i_gid = current_fsgid();
>  	result->i_nlink = 1;
>  	result->i_size = 0;
>  	result->i_blocks = 1;
> @@ -325,8 +325,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
>  	result->i_atime.tv_nsec = 0;
>  	hpfs_i(result)->i_ea_size = 0;
>  	result->i_mode = S_IFLNK | 0777;
> -	result->i_uid = current->fsuid;
> -	result->i_gid = current->fsgid;
> +	result->i_uid = current_fsuid();
> +	result->i_gid = current_fsgid();
>  	result->i_blocks = 1;
>  	result->i_nlink = 1;
>  	result->i_size = strlen(symlink);
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 09ee07f..39ad919 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -543,9 +543,9 @@ static int hugetlbfs_mknod(struct inode *dir,
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else {
> -		gid = current->fsgid;
> +		gid = current_fsgid();
>  	}
> -	inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid, gid, mode, dev);
> +	inode = hugetlbfs_get_inode(dir->i_sb, current_fsuid(), gid, mode, dev);
>  	if (inode) {
>  		dir->i_ctime = dir->i_mtime = CURRENT_TIME;
>  		d_instantiate(dentry, inode);
> @@ -578,9 +578,9 @@ static int hugetlbfs_symlink(struct inode *dir,
>  	if (dir->i_mode & S_ISGID)
>  		gid = dir->i_gid;
>  	else
> -		gid = current->fsgid;
> +		gid = current_fsgid();
> 
> -	inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid,
> +	inode = hugetlbfs_get_inode(dir->i_sb, current_fsuid(),
>  					gid, S_IFLNK|S_IRWXUGO, 0);
>  	if (inode) {
>  		int l = strlen(symname)+1;
> @@ -819,8 +819,8 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
> 
>  	config.nr_blocks = -1; /* No limit on size by default */
>  	config.nr_inodes = -1; /* No limit on number of inodes by default */
> -	config.uid = current->fsuid;
> -	config.gid = current->fsgid;
> +	config.uid = current_fsuid();
> +	config.gid = current_fsgid();
>  	config.mode = 0755;
>  	ret = hugetlbfs_parse_options(data, &config);
>  	if (ret)
> @@ -933,8 +933,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
>  		goto out_shm_unlock;
> 
>  	error = -ENOSPC;
> -	inode = hugetlbfs_get_inode(root->d_sb, current->fsuid,
> -				current->fsgid, S_IFREG | S_IRWXUGO, 0);
> +	inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(),
> +				current_fsgid(), S_IFREG | S_IRWXUGO, 0);
>  	if (!inode)
>  		goto out_dentry;
> 
> diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
> index d2e06f7..61849f3 100644
> --- a/fs/jffs2/fs.c
> +++ b/fs/jffs2/fs.c
> @@ -425,14 +425,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
> 
>  	memset(ri, 0, sizeof(*ri));
>  	/* Set OS-specific defaults for new inodes */
> -	ri->uid = cpu_to_je16(current->fsuid);
> +	ri->uid = cpu_to_je16(current_fsuid());
> 
>  	if (dir_i->i_mode & S_ISGID) {
>  		ri->gid = cpu_to_je16(dir_i->i_gid);
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else {
> -		ri->gid = cpu_to_je16(current->fsgid);
> +		ri->gid = cpu_to_je16(current_fsgid());
>  	}
> 
>  	/* POSIX ACLs have to be processed now, at least partly.
> diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
> index ed6574b..70022fd 100644
> --- a/fs/jfs/jfs_inode.c
> +++ b/fs/jfs/jfs_inode.c
> @@ -93,13 +93,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
>  		return ERR_PTR(rc);
>  	}
> 
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	if (parent->i_mode & S_ISGID) {
>  		inode->i_gid = parent->i_gid;
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else
> -		inode->i_gid = current->fsgid;
> +		inode->i_gid = current_fsgid();
> 
>  	/*
>  	 * New inodes need to save sane values on disk when
> diff --git a/fs/locks.c b/fs/locks.c
> index 8b8388e..359030b 100644
> --- a/fs/locks.c
> +++ b/fs/locks.c
> @@ -1358,7 +1358,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
>  	struct inode *inode = dentry->d_inode;
>  	int error, rdlease_count = 0, wrlease_count = 0;
> 
> -	if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
> +	if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE))
>  		return -EACCES;
>  	if (!S_ISREG(inode->i_mode))
>  		return -EINVAL;
> diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
> index 703cc35..3aebe32 100644
> --- a/fs/minix/bitmap.c
> +++ b/fs/minix/bitmap.c
> @@ -262,8 +262,8 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
>  		iput(inode);
>  		return NULL;
>  	}
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current_fsgid();
>  	inode->i_ino = j;
>  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
>  	inode->i_blocks = 0;
> diff --git a/fs/namei.c b/fs/namei.c
> index 3b993db..8963e91 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -184,7 +184,7 @@ int generic_permission(struct inode *inode, int mask,
>  {
>  	umode_t			mode = inode->i_mode;
> 
> -	if (current->fsuid == inode->i_uid)
> +	if (current_fsuid() == inode->i_uid)
>  		mode >>= 6;
>  	else {
>  		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
> @@ -452,7 +452,7 @@ static int exec_permission_lite(struct inode *inode,
>  	if (inode->i_op && inode->i_op->permission)
>  		return -EAGAIN;
> 
> -	if (current->fsuid == inode->i_uid)
> +	if (current_fsuid() == inode->i_uid)
>  		mode >>= 6;
>  	else if (in_group_p(inode->i_gid))
>  		mode >>= 3;
> @@ -1435,9 +1435,9 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
>  {
>  	if (!(dir->i_mode & S_ISVTX))
>  		return 0;
> -	if (inode->i_uid == current->fsuid)
> +	if (inode->i_uid == current_fsuid())
>  		return 0;
> -	if (dir->i_uid == current->fsuid)
> +	if (dir->i_uid == current_fsuid())
>  		return 0;
>  	return !capable(CAP_FOWNER);
>  }
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index d019918..f11c48d 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -1857,7 +1857,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
>  		IS_APPEND(inode)?	" append" : "",
>  		IS_RDONLY(inode)?	" ro" : "");
>  	dprintk("      owner %d/%d user %d/%d\n",
> -		inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
> +		inode->i_uid, inode->i_gid, current_fsuid(), current->fsgid);
>  #endif
> 
>  	/* Normally we reject any write/sattr etc access on a read-only file
> @@ -1899,7 +1899,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
>  	 * with NFSv3.
>  	 */
>  	if ((acc & MAY_OWNER_OVERRIDE) &&
> -	    inode->i_uid == current->fsuid)
> +	    inode->i_uid == current_fsuid())
>  		return 0;
> 
>  	err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
> diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
> index 6639baa..ea65979 100644
> --- a/fs/ocfs2/dlm/dlmfs.c
> +++ b/fs/ocfs2/dlm/dlmfs.c
> @@ -328,8 +328,8 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
>  		ip = DLMFS_I(inode);
> 
>  		inode->i_mode = mode;
> -		inode->i_uid = current->fsuid;
> -		inode->i_gid = current->fsgid;
> +		inode->i_uid = current_fsuid();
> +		inode->i_gid = current_fsgid();
>  		inode->i_blocks = 0;
>  		inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
>  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
> @@ -354,8 +354,8 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
>  		return NULL;
> 
>  	inode->i_mode = mode;
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = current_fsgid();
>  	inode->i_blocks = 0;
>  	inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
>  	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
> diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
> index 989ac27..86e2717 100644
> --- a/fs/ocfs2/namei.c
> +++ b/fs/ocfs2/namei.c
> @@ -426,13 +426,13 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
>  	fe->i_blkno = cpu_to_le64(fe_blkno);
>  	fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
>  	fe->i_suballoc_slot = cpu_to_le16(osb->slot_num);
> -	fe->i_uid = cpu_to_le32(current->fsuid);
> +	fe->i_uid = cpu_to_le32(current_fsuid());
>  	if (dir->i_mode & S_ISGID) {
>  		fe->i_gid = cpu_to_le32(dir->i_gid);
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else
> -		fe->i_gid = cpu_to_le32(current->fsgid);
> +		fe->i_gid = cpu_to_le32(current_fsgid());
>  	fe->i_mode = cpu_to_le16(mode);
>  	if (S_ISCHR(mode) || S_ISBLK(mode))
>  		fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
> diff --git a/fs/pipe.c b/fs/pipe.c
> index e66ec48..598cf6c 100644
> --- a/fs/pipe.c
> +++ b/fs/pipe.c
> @@ -938,8 +938,8 @@ static struct inode * get_pipe_inode(void)
>  	 */
>  	inode->i_state = I_DIRTY;
>  	inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = current_fsgid();
>  	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
> 
>  	return inode;
> diff --git a/fs/posix_acl.c b/fs/posix_acl.c
> index aec931e..39df95a 100644
> --- a/fs/posix_acl.c
> +++ b/fs/posix_acl.c
> @@ -217,11 +217,11 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
>                  switch(pa->e_tag) {
>                          case ACL_USER_OBJ:
>  				/* (May have been checked already) */
> -                                if (inode->i_uid == current->fsuid)
> +				if (inode->i_uid == current_fsuid())
>                                          goto check_perm;
>                                  break;
>                          case ACL_USER:
> -                                if (pa->e_id == current->fsuid)
> +				if (pa->e_id == current_fsuid())
>                                          goto mask;
>  				break;
>                          case ACL_GROUP_OBJ:
> diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
> index 8428d5b..98421f7 100644
> --- a/fs/ramfs/inode.c
> +++ b/fs/ramfs/inode.c
> @@ -55,8 +55,8 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
> 
>  	if (inode) {
>  		inode->i_mode = mode;
> -		inode->i_uid = current->fsuid;
> -		inode->i_gid = current->fsgid;
> +		inode->i_uid = current_fsuid();
> +		inode->i_gid = current_fsgid();
>  		inode->i_blocks = 0;
>  		inode->i_mapping->a_ops = &ramfs_aops;
>  		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
> diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
> index b378eea..84458f3 100644
> --- a/fs/reiserfs/namei.c
> +++ b/fs/reiserfs/namei.c
> @@ -582,7 +582,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
>  	/* the quota init calls have to know who to charge the quota to, so
>  	 ** we have to set uid and gid here
>  	 */
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	inode->i_mode = mode;
>  	/* Make inode invalid - just in case we are going to drop it before
>  	 * the initialization happens */
> @@ -593,7 +593,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
>  		if (S_ISDIR(mode))
>  			inode->i_mode |= S_ISGID;
>  	} else {
> -		inode->i_gid = current->fsgid;
> +		inode->i_gid = current_fsgid();
>  	}
>  	DQUOT_INIT(inode);
>  	return 0;
> diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
> index 115ab0d..241e976 100644
> --- a/fs/sysv/ialloc.c
> +++ b/fs/sysv/ialloc.c
> @@ -165,9 +165,9 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else
> -		inode->i_gid = current->fsgid;
> +		inode->i_gid = current_fsgid();
> 
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	inode->i_ino = fs16_to_cpu(sbi, ino);
>  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
>  	inode->i_blocks = 0;
> diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
> index 636d8f6..1f3c01a 100644
> --- a/fs/udf/ialloc.c
> +++ b/fs/udf/ialloc.c
> @@ -105,13 +105,13 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
>  		mark_buffer_dirty(UDF_SB_LVIDBH(sb));
>  	}
>  	inode->i_mode = mode;
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	if (dir->i_mode & S_ISGID) {
>  		inode->i_gid = dir->i_gid;
>  		if (S_ISDIR(mode))
>  			mode |= S_ISGID;
>  	} else {
> -		inode->i_gid = current->fsgid;
> +		inode->i_gid = current_fsgid();
>  	}
> 
>  	UDF_I_LOCATION(inode).logicalBlockNum = block;
> diff --git a/fs/udf/namei.c b/fs/udf/namei.c
> index bec96a6..e2d466c 100644
> --- a/fs/udf/namei.c
> +++ b/fs/udf/namei.c
> @@ -636,7 +636,7 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
>  	if (!inode)
>  		goto out;
> 
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	init_special_inode(inode, mode, rdev);
>  	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
>  		inode->i_nlink--;
> diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
> index 7e260bc..88f8889 100644
> --- a/fs/ufs/ialloc.c
> +++ b/fs/ufs/ialloc.c
> @@ -304,13 +304,13 @@ cg_found:
> 
>  	inode->i_ino = cg * uspi->s_ipg + bit;
>  	inode->i_mode = mode;
> -	inode->i_uid = current->fsuid;
> +	inode->i_uid = current_fsuid();
>  	if (dir->i_mode & S_ISGID) {
>  		inode->i_gid = dir->i_gid;
>  		if (S_ISDIR(mode))
>  			inode->i_mode |= S_ISGID;
>  	} else
> -		inode->i_gid = current->fsgid;
> +		inode->i_gid = current_fsgid();
> 
>  	inode->i_blocks = 0;
>  	inode->i_generation = 0;
> diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
> index dc3752d..0b943dd 100644
> --- a/fs/xfs/linux-2.6/xfs_linux.h
> +++ b/fs/xfs/linux-2.6/xfs_linux.h
> @@ -126,8 +126,8 @@
> 
>  #define current_cpu()		(raw_smp_processor_id())
>  #define current_pid()		(current->pid)
> -#define current_fsuid(cred)	(current->fsuid)
> -#define current_fsgid(cred)	(current->fsgid)
> +#define this_fsuid(cred)	(current_fsuid())
> +#define this_fsgid(cred)	(current_fsgid())
>  #define current_test_flags(f)	(current->flags & (f))
>  #define current_set_flags_nested(sp, f)		\
>  		(*(sp) = current->flags, current->flags |= (f))
> diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
> index 5bfb66f..878ca6e 100644
> --- a/fs/xfs/xfs_acl.c
> +++ b/fs/xfs/xfs_acl.c
> @@ -386,7 +386,7 @@ xfs_acl_allow_set(
>  	error = xfs_getattr(ip, &va, 0);
>  	if (error)
>  		return error;
> -	if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
> +	if (va.va_uid != current_fsuid() && !capable(CAP_FOWNER))
>  		return EPERM;
>  	return error;
>  }
> @@ -460,13 +460,13 @@ xfs_acl_access(
>  		switch (fap->acl_entry[i].ae_tag) {
>  		case ACL_USER_OBJ:
>  			seen_userobj = 1;
> -			if (fuid != current->fsuid)
> +			if (fuid != current_fsuid())
>  				continue;
>  			matched.ae_tag = ACL_USER_OBJ;
>  			matched.ae_perm = allows;
>  			break;
>  		case ACL_USER:
> -			if (fap->acl_entry[i].ae_id != current->fsuid)
> +			if (fap->acl_entry[i].ae_id != current_fsuid())
>  				continue;
>  			matched.ae_tag = ACL_USER;
>  			matched.ae_perm = allows;
> diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
> index 93fa64d..33c1173 100644
> --- a/fs/xfs/xfs_attr.c
> +++ b/fs/xfs/xfs_attr.c
> @@ -2627,7 +2627,7 @@ attr_user_capable(
>  	    !capable(CAP_SYS_ADMIN))
>  		return -EPERM;
>  	if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
> -	    (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
> +	    (this_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
>  		return -EPERM;
>  	return 0;
>  }
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index abf509a..31eba0d 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -1132,8 +1132,8 @@ xfs_ialloc(
>  	ip->i_d.di_onlink = 0;
>  	ip->i_d.di_nlink = nlink;
>  	ASSERT(ip->i_d.di_nlink == nlink);
> -	ip->i_d.di_uid = current_fsuid(cr);
> -	ip->i_d.di_gid = current_fsgid(cr);
> +	ip->i_d.di_uid = this_fsuid(cr);
> +	ip->i_d.di_gid = this_fsgid(cr);
>  	ip->i_d.di_projid = prid;
>  	memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
> 
> @@ -3640,7 +3640,7 @@ xfs_iaccess(
>  	if ((error = _ACL_XFS_IACCESS(ip, mode, cr)) != -1)
>  		return error ? XFS_ERROR(error) : 0;
> 
> -	if (current_fsuid(cr) != ip->i_d.di_uid) {
> +	if (this_fsuid(cr) != ip->i_d.di_uid) {
>  		mode >>= 3;
>  		if (!in_group_p((gid_t)ip->i_d.di_gid))
>  			mode >>= 3;
> diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
> index efd5aff..86bc8ec 100644
> --- a/fs/xfs/xfs_vnodeops.c
> +++ b/fs/xfs/xfs_vnodeops.c
> @@ -341,7 +341,7 @@ xfs_setattr(
>  	xfs_ilock(ip, lock_flags);
> 
>  	/* boolean: are we the file owner? */
> -	file_owner = (current_fsuid(credp) == ip->i_d.di_uid);
> +	file_owner = (this_fsuid(credp) == ip->i_d.di_uid);
> 
>  	/*
>  	 * Change various properties of a file.
> @@ -1878,7 +1878,7 @@ xfs_create(
>  	 * Make sure that we have allocated dquot(s) on disk.
>  	 */
>  	error = XFS_QM_DQVOPALLOC(mp, dp,
> -			current_fsuid(credp), current_fsgid(credp), prid,
> +			this_fsuid(credp), this_fsgid(credp), prid,
>  			XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
>  	if (error)
>  		goto std_return;
> @@ -2757,7 +2757,7 @@ xfs_mkdir(
>  	 * Make sure that we have allocated dquot(s) on disk.
>  	 */
>  	error = XFS_QM_DQVOPALLOC(mp, dp,
> -			current_fsuid(credp), current_fsgid(credp), prid,
> +			this_fsuid(credp), this_fsgid(credp), prid,
>  			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
>  	if (error)
>  		goto std_return;
> @@ -3249,7 +3249,7 @@ xfs_symlink(
>  	 * Make sure that we have allocated dquot(s) on disk.
>  	 */
>  	error = XFS_QM_DQVOPALLOC(mp, dp,
> -			current_fsuid(credp), current_fsgid(credp), prid,
> +			this_fsuid(credp), this_fsgid(credp), prid,
>  			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
>  	if (error)
>  		goto std_return;
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index b3ec4a4..850d3fc 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1057,7 +1057,7 @@ enum {
>  #define has_fs_excl() atomic_read(&current->fs_excl)
> 
>  #define is_owner_or_cap(inode)	\
> -	((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER))
> +	((current_fsuid() == (inode)->i_uid) || capable(CAP_FOWNER))
> 
>  /* not quite ready to be deprecated, but... */
>  extern void lock_super(struct super_block *);
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index ac3d496..88a5626 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1180,6 +1180,9 @@ struct task_struct {
>  	struct prop_local_single dirties;
>  };
> 
> +#define current_fsuid() (current->fsuid)
> +#define current_fsgid() (current->fsgid)
> +
>  /*
>   * Priority of a process goes from 0..MAX_PRIO-1, valid RT
>   * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
> diff --git a/ipc/mqueue.c b/ipc/mqueue.c
> index 6ca7b97..590045a 100644
> --- a/ipc/mqueue.c
> +++ b/ipc/mqueue.c
> @@ -109,8 +109,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
>  	inode = new_inode(sb);
>  	if (inode) {
>  		inode->i_mode = mode;
> -		inode->i_uid = current->fsuid;
> -		inode->i_gid = current->fsgid;
> +		inode->i_uid = current_fsuid();
> +		inode->i_gid = current_fsgid();
>  		inode->i_blocks = 0;
>  		inode->i_mtime = inode->i_ctime = inode->i_atime =
>  				CURRENT_TIME;
> diff --git a/kernel/cgroup.c b/kernel/cgroup.c
> index 1a3c239..1b85df5 100644
> --- a/kernel/cgroup.c
> +++ b/kernel/cgroup.c
> @@ -577,8 +577,8 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
> 
>  	if (inode) {
>  		inode->i_mode = mode;
> -		inode->i_uid = current->fsuid;
> -		inode->i_gid = current->fsgid;
> +		inode->i_uid = current_fsuid();
> +		inode->i_gid = current_fsgid();
>  		inode->i_blocks = 0;
>  		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
>  		inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 51b3d6c..292b329 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1412,8 +1412,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
>  	inode = new_inode(sb);
>  	if (inode) {
>  		inode->i_mode = mode;
> -		inode->i_uid = current->fsuid;
> -		inode->i_gid = current->fsgid;
> +		inode->i_uid = current_fsuid();
> +		inode->i_gid = current_fsgid();
>  		inode->i_blocks = 0;
>  		inode->i_mapping->a_ops = &shmem_aops;
>  		inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
> @@ -2241,8 +2241,8 @@ static int shmem_fill_super(struct super_block *sb,
>  	struct inode *inode;
>  	struct dentry *root;
>  	int mode   = S_IRWXUGO | S_ISVTX;
> -	uid_t uid = current->fsuid;
> -	gid_t gid = current->fsgid;
> +	uid_t uid = current_fsuid();
> +	gid_t gid = current_fsgid();
>  	int err = -ENOMEM;
>  	struct shmem_sb_info *sbinfo;
>  	unsigned long blocks = 0;
> diff --git a/net/9p/client.c b/net/9p/client.c
> index af91993..9cb8b3b 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -938,7 +938,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
>  	fid->rdir_fpos = 0;
>  	fid->rdir_pos = 0;
>  	fid->rdir_fcall = NULL;
> -	fid->uid = current->fsuid;
> +	fid->uid = current_fsuid();
>  	fid->clnt = clnt;
>  	fid->aux = NULL;
> 
> diff --git a/net/socket.c b/net/socket.c
> index 74784df..e5f8151 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -484,8 +484,8 @@ static struct socket *sock_alloc(void)
>  	sock = SOCKET_I(inode);
> 
>  	inode->i_mode = S_IFSOCK | S_IRWXUGO;
> -	inode->i_uid = current->fsuid;
> -	inode->i_gid = current->fsgid;
> +	inode->i_uid = current_fsuid();
> +	inode->i_gid = current_fsgid();
> 
>  	get_cpu_var(sockets_in_use)++;
>  	put_cpu_var(sockets_in_use);
> diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
> index 1ea2755..390a1ec 100644
> --- a/net/sunrpc/auth.c
> +++ b/net/sunrpc/auth.c
> @@ -337,8 +337,8 @@ struct rpc_cred *
>  rpcauth_lookupcred(struct rpc_auth *auth, int flags)
>  {
>  	struct auth_cred acred = {
> -		.uid = current->fsuid,
> -		.gid = current->fsgid,
> +		.uid = current_fsuid(),
> +		.gid = current_fsgid(),
>  		.group_info = current->group_info,
>  	};
>  	struct rpc_cred *ret;
> @@ -373,8 +373,8 @@ rpcauth_bindcred(struct rpc_task *task)
>  {
>  	struct rpc_auth *auth = task->tk_client->cl_auth;
>  	struct auth_cred acred = {
> -		.uid = current->fsuid,
> -		.gid = current->fsgid,
> +		.uid = current_fsuid(),
> +		.gid = current_fsgid(),
>  		.group_info = current->group_info,
>  	};
>  	struct rpc_cred *ret;
> diff --git a/security/commoncap.c b/security/commoncap.c
> index 5bc1895..bbe188e 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -336,8 +336,8 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
>  		}
>  	}
> 
> -	current->suid = current->euid = current->fsuid = bprm->e_uid;
> -	current->sgid = current->egid = current->fsgid = bprm->e_gid;
> +	current->suid = current->euid = current_fsuid() = bprm->e_uid;
> +	current->sgid = current->egid = current_fsgid() = bprm->e_gid;
> 
>  	/* For init, we want to retain the capabilities set
>  	 * in the init_task struct. Thus we skip the usual
> @@ -466,11 +466,11 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
>  			 */
> 
>  			if (!issecure (SECURE_NO_SETUID_FIXUP)) {
> -				if (old_fsuid == 0 && current->fsuid != 0) {
> +				if (old_fsuid == 0 && current_fsuid() != 0) {
>  					cap_t (current->cap_effective) &=
>  					    ~CAP_FS_MASK;
>  				}
> -				if (old_fsuid != 0 && current->fsuid == 0) {
> +				if (old_fsuid != 0 && current_fsuid() == 0) {
>  					cap_t (current->cap_effective) |=
>  					    (cap_t (current->cap_permitted) &
>  					     CAP_FS_MASK);
> diff --git a/security/keys/key.c b/security/keys/key.c
> index fdd5ca6..48fabb1 100644
> --- a/security/keys/key.c
> +++ b/security/keys/key.c
> @@ -817,7 +817,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
>  		perm |= KEY_USR_WRITE;
> 
>  	/* allocate a new key */
> -	key = key_alloc(ktype, description, current->fsuid, current->fsgid,
> +	key = key_alloc(ktype, description, current_fsuid(), current->fsgid,
>  			current, perm, flags);
>  	if (IS_ERR(key)) {
>  		key_ref = ERR_PTR(PTR_ERR(key));
> diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
> index 56e963b..b3a63dd 100644
> --- a/security/keys/keyctl.c
> +++ b/security/keys/keyctl.c
> @@ -810,7 +810,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
>  	down_write(&key->sem);
> 
>  	/* if we're not the sysadmin, we can only change a key that we own */
> -	if (capable(CAP_SYS_ADMIN) || key->uid == current->fsuid) {
> +	if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) {
>  		key->perm = perm;
>  		ret = 0;
>  	}
> diff --git a/security/keys/request_key.c b/security/keys/request_key.c
> index aee4897..6d25911 100644
> --- a/security/keys/request_key.c
> +++ b/security/keys/request_key.c
> @@ -76,7 +76,7 @@ static int call_sbin_request_key(struct key_construction *cons,
>  	/* allocate a new session keyring */
>  	sprintf(desc, "_req.%u", key->serial);
> 
> -	keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current,
> +	keyring = keyring_alloc(desc, current_fsuid(), current->fsgid, current,
>  				KEY_ALLOC_QUOTA_OVERRUN, NULL);
>  	if (IS_ERR(keyring)) {
>  		ret = PTR_ERR(keyring);
> @@ -89,8 +89,8 @@ static int call_sbin_request_key(struct key_construction *cons,
>  		goto error_link;
> 
>  	/* record the UID and GID */
> -	sprintf(uid_str, "%d", current->fsuid);
> -	sprintf(gid_str, "%d", current->fsgid);
> +	sprintf(uid_str, "%d", current_fsuid());
> +	sprintf(gid_str, "%d", current_fsgid());
> 
>  	/* we say which key is under construction */
>  	sprintf(key_str, "%d", key->serial);
> @@ -278,7 +278,7 @@ static int construct_alloc_key(struct key_type *type,
>  	mutex_lock(&user->cons_lock);
> 
>  	key = key_alloc(type, description,
> -			current->fsuid, current->fsgid, current, KEY_POS_ALL,
> +			current_fsuid(), current->fsgid, current, KEY_POS_ALL,
>  			flags);
>  	if (IS_ERR(key))
>  		goto alloc_failed;
> @@ -341,7 +341,7 @@ static struct key *construct_key_and_link(struct key_type *type,
>  	struct key *key;
>  	int ret;
> 
> -	user = key_user_lookup(current->fsuid);
> +	user = key_user_lookup(current_fsuid());
>  	if (!user)
>  		return ERR_PTR(-ENOMEM);
> 
> diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
> index 6827ae3..cce6b4d 100644
> --- a/security/keys/request_key_auth.c
> +++ b/security/keys/request_key_auth.c
> @@ -194,7 +194,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
>  	sprintf(desc, "%x", target->serial);
> 
>  	authkey = key_alloc(&key_type_request_key_auth, desc,
> -			    current->fsuid, current->fsgid, current,
> +			    current_fsuid(), current->fsgid, current,
>  			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
>  			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
>  	if (IS_ERR(authkey)) {
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 5/7] Security: Change current->fs[ug]id to current_fs[ug]id()
  2007-12-05 19:37 ` [PATCH 5/7] Security: Change current->fs[ug]id to current_fs[ug]id() David Howells
  2007-12-07 17:44   ` Serge E. Hallyn
@ 2007-12-08  0:53   ` David Howells
  1 sibling, 0 replies; 14+ messages in thread
From: David Howells @ 2007-12-08  0:53 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: dhowells, viro, hch, Trond.Myklebust, sds, casey, linux-kernel,
	selinux, linux-security-module


Serge E. Hallyn <serue@us.ibm.com> wrote:

> Could you resend patch 6?

As I said in the cover note:

A tarball of the patches is available at:

	http://people.redhat.com/~dhowells/fscache/patches/nfs+fscache-25.tar.bz2

David

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

end of thread, other threads:[~2007-12-08  0:56 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-12-05 19:37 [PATCH 0/7] Permit filesystem local caching David Howells
2007-12-05 19:37 ` [PATCH 1/7] KEYS: Increase the payload size when instantiating a key David Howells
2007-12-05 19:37 ` [PATCH 2/7] KEYS: Check starting keyring as part of search David Howells
2007-12-05 19:37 ` [PATCH 3/7] KEYS: Allow the callout data to be passed as a blob rather than a string David Howells
2007-12-05 19:37 ` [PATCH 4/7] KEYS: Add keyctl function to get a security label David Howells
2007-12-05 20:12   ` Casey Schaufler
2007-12-05 20:38     ` Stephen Smalley
2007-12-06  1:28     ` David Howells
2007-12-06  1:40       ` Casey Schaufler
2007-12-05 19:37 ` [PATCH 5/7] Security: Change current->fs[ug]id to current_fs[ug]id() David Howells
2007-12-07 17:44   ` Serge E. Hallyn
2007-12-08  0:53   ` David Howells
2007-12-05 19:37 ` [PATCH 6/7] SECURITY: Separate task security context from task_struct David Howells
2007-12-05 19:37 ` [PATCH 7/7] SECURITY: De-embed task security record from task and use refcounting David Howells

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).