Browse Source

Merge branch 'next' into for-linus

James Morris 16 years ago
parent
commit
cbacc2c7f0
100 changed files with 1308 additions and 494 deletions
  1. 582 0
      Documentation/credentials.txt
  2. 4 0
      Documentation/kernel-parameters.txt
  3. 21 0
      Documentation/scheduler/sched-design-CFS.txt
  4. 7 4
      arch/alpha/kernel/asm-offsets.c
  5. 6 4
      arch/alpha/kernel/entry.S
  6. 3 4
      arch/ia64/ia32/sys_ia32.c
  7. 1 1
      arch/ia64/kernel/mca_drv.c
  8. 27 16
      arch/ia64/kernel/perfmon.c
  9. 2 2
      arch/ia64/kernel/signal.c
  10. 2 2
      arch/mips/kernel/kspd.c
  11. 3 2
      arch/mips/kernel/mips-mt-fpaff.c
  12. 2 2
      arch/mips/kernel/vpe.c
  13. 1 1
      arch/parisc/kernel/signal.c
  14. 1 1
      arch/powerpc/mm/fault.c
  15. 4 4
      arch/powerpc/platforms/cell/spufs/inode.c
  16. 2 2
      arch/s390/hypfs/inode.c
  17. 14 14
      arch/s390/kernel/compat_linux.c
  18. 2 1
      arch/um/drivers/mconsole_kern.c
  19. 1 1
      arch/x86/ia32/ia32_aout.c
  20. 1 1
      arch/x86/mm/fault.c
  21. 4 2
      drivers/block/loop.c
  22. 61 15
      drivers/char/tty_audit.c
  23. 1 0
      drivers/char/tty_io.c
  24. 11 5
      drivers/connector/cn_proc.c
  25. 2 2
      drivers/isdn/capi/capifs.c
  26. 4 2
      drivers/isdn/hysdn/hysdn_procconf.c
  27. 5 3
      drivers/net/tun.c
  28. 6 4
      drivers/usb/core/devio.c
  29. 2 2
      drivers/usb/core/inode.c
  30. 1 1
      fs/9p/fid.c
  31. 2 2
      fs/9p/vfs_inode.c
  32. 2 2
      fs/9p/vfs_super.c
  33. 2 2
      fs/affs/inode.c
  34. 2 2
      fs/affs/super.c
  35. 2 2
      fs/anon_inodes.c
  36. 2 2
      fs/attr.c
  37. 2 2
      fs/autofs/inode.c
  38. 2 1
      fs/autofs4/dev-ioctl.c
  39. 2 2
      fs/autofs4/inode.c
  40. 2 2
      fs/autofs4/waitq.c
  41. 2 2
      fs/bfs/dir.c
  42. 1 1
      fs/binfmt_aout.c
  43. 12 8
      fs/binfmt_elf.c
  44. 12 7
      fs/binfmt_elf_fdpic.c
  45. 1 1
      fs/binfmt_flat.c
  46. 1 1
      fs/binfmt_som.c
  47. 1 1
      fs/cifs/cifs_fs_sb.h
  48. 1 1
      fs/cifs/cifsproto.h
  49. 2 2
      fs/cifs/connect.c
  50. 6 6
      fs/cifs/dir.c
  51. 4 4
      fs/cifs/inode.c
  52. 1 1
      fs/cifs/ioctl.c
  53. 2 2
      fs/cifs/misc.c
  54. 3 3
      fs/coda/cache.c
  55. 2 1
      fs/coda/file.c
  56. 1 1
      fs/coda/upcall.c
  57. 24 18
      fs/compat.c
  58. 2 2
      fs/devpts/inode.c
  59. 2 2
      fs/dquot.c
  60. 2 1
      fs/ecryptfs/ecryptfs_kernel.h
  61. 5 4
      fs/ecryptfs/kthread.c
  62. 2 1
      fs/ecryptfs/main.c
  63. 14 13
      fs/ecryptfs/messaging.c
  64. 13 14
      fs/ecryptfs/miscdev.c
  65. 109 74
      fs/exec.c
  66. 3 1
      fs/exportfs/expfs.c
  67. 1 1
      fs/ext2/balloc.c
  68. 2 2
      fs/ext2/ialloc.c
  69. 1 1
      fs/ext3/balloc.c
  70. 2 2
      fs/ext3/ialloc.c
  71. 1 1
      fs/ext4/balloc.c
  72. 2 2
      fs/ext4/ialloc.c
  73. 1 1
      fs/fat/file.c
  74. 2 2
      fs/fat/inode.c
  75. 13 5
      fs/fcntl.c
  76. 5 5
      fs/file_table.c
  77. 2 2
      fs/fuse/dev.c
  78. 15 8
      fs/fuse/dir.c
  79. 5 5
      fs/gfs2/inode.c
  80. 2 2
      fs/hfs/inode.c
  81. 2 2
      fs/hfs/super.c
  82. 2 2
      fs/hfsplus/inode.c
  83. 2 2
      fs/hfsplus/options.c
  84. 12 12
      fs/hpfs/namei.c
  85. 2 2
      fs/hpfs/super.c
  86. 4 2
      fs/hppfs/hppfs.c
  87. 11 10
      fs/hugetlbfs/inode.c
  88. 1 1
      fs/inotify_user.c
  89. 6 0
      fs/internal.h
  90. 12 6
      fs/ioprio.c
  91. 2 2
      fs/jfs/jfs_inode.c
  92. 1 1
      fs/locks.c
  93. 2 2
      fs/minix/bitmap.c
  94. 6 4
      fs/namei.c
  95. 1 1
      fs/namespace.c
  96. 44 47
      fs/ncpfs/ioctl.c
  97. 4 1
      fs/nfsctl.c
  98. 56 39
      fs/nfsd/auth.c
  99. 45 27
      fs/nfsd/nfs4recover.c
  100. 8 3
      fs/nfsd/nfsfh.c

+ 582 - 0
Documentation/credentials.txt

@@ -0,0 +1,582 @@
+			     ====================
+			     CREDENTIALS IN LINUX
+			     ====================
+
+By: David Howells <dhowells@redhat.com>
+
+Contents:
+
+ (*) Overview.
+
+ (*) Types of credentials.
+
+ (*) File markings.
+
+ (*) Task credentials.
+
+     - Immutable credentials.
+     - Accessing task credentials.
+     - Accessing another task's credentials.
+     - Altering credentials.
+     - Managing credentials.
+
+ (*) Open file credentials.
+
+ (*) Overriding the VFS's use of credentials.
+
+
+========
+OVERVIEW
+========
+
+There are several parts to the security check performed by Linux when one
+object acts upon another:
+
+ (1) Objects.
+
+     Objects are things in the system that may be acted upon directly by
+     userspace programs.  Linux has a variety of actionable objects, including:
+
+	- Tasks
+	- Files/inodes
+	- Sockets
+	- Message queues
+	- Shared memory segments
+	- Semaphores
+	- Keys
+
+     As a part of the description of all these objects there is a set of
+     credentials.  What's in the set depends on the type of object.
+
+ (2) Object ownership.
+
+     Amongst the credentials of most objects, there will be a subset that
+     indicates the ownership of that object.  This is used for resource
+     accounting and limitation (disk quotas and task rlimits for example).
+
+     In a standard UNIX filesystem, for instance, this will be defined by the
+     UID marked on the inode.
+
+ (3) The objective context.
+
+     Also amongst the credentials of those objects, there will be a subset that
+     indicates the 'objective context' of that object.  This may or may not be
+     the same set as in (2) - in standard UNIX files, for instance, this is the
+     defined by the UID and the GID marked on the inode.
+
+     The objective context is used as part of the security calculation that is
+     carried out when an object is acted upon.
+
+ (4) Subjects.
+
+     A subject is an object that is acting upon another object.
+
+     Most of the objects in the system are inactive: they don't act on other
+     objects within the system.  Processes/tasks are the obvious exception:
+     they do stuff; they access and manipulate things.
+
+     Objects other than tasks may under some circumstances also be subjects.
+     For instance an open file may send SIGIO to a task using the UID and EUID
+     given to it by a task that called fcntl(F_SETOWN) upon it.  In this case,
+     the file struct will have a subjective context too.
+
+ (5) The subjective context.
+
+     A subject has an additional interpretation of its credentials.  A subset
+     of its credentials forms the 'subjective context'.  The subjective context
+     is used as part of the security calculation that is carried out when a
+     subject acts.
+
+     A Linux task, for example, has the FSUID, FSGID and the supplementary
+     group list for when it is acting upon a file - which are quite separate
+     from the real UID and GID that normally form the objective context of the
+     task.
+
+ (6) Actions.
+
+     Linux has a number of actions available that a subject may perform upon an
+     object.  The set of actions available depends on the nature of the subject
+     and the object.
+
+     Actions include reading, writing, creating and deleting files; forking or
+     signalling and tracing tasks.
+
+ (7) Rules, access control lists and security calculations.
+
+     When a subject acts upon an object, a security calculation is made.  This
+     involves taking the subjective context, the objective context and the
+     action, and searching one or more sets of rules to see whether the subject
+     is granted or denied permission to act in the desired manner on the
+     object, given those contexts.
+
+     There are two main sources of rules:
+
+     (a) Discretionary access control (DAC):
+
+	 Sometimes the object will include sets of rules as part of its
+	 description.  This is an 'Access Control List' or 'ACL'.  A Linux
+	 file may supply more than one ACL.
+
+	 A traditional UNIX file, for example, includes a permissions mask that
+	 is an abbreviated ACL with three fixed classes of subject ('user',
+	 'group' and 'other'), each of which may be granted certain privileges
+	 ('read', 'write' and 'execute' - whatever those map to for the object
+	 in question).  UNIX file permissions do not allow the arbitrary
+	 specification of subjects, however, and so are of limited use.
+
+	 A Linux file might also sport a POSIX ACL.  This is a list of rules
+	 that grants various permissions to arbitrary subjects.
+
+     (b) Mandatory access control (MAC):
+
+	 The system as a whole may have one or more sets of rules that get
+	 applied to all subjects and objects, regardless of their source.
+	 SELinux and Smack are examples of this.
+
+	 In the case of SELinux and Smack, each object is given a label as part
+	 of its credentials.  When an action is requested, they take the
+	 subject label, the object label and the action and look for a rule
+	 that says that this action is either granted or denied.
+
+
+====================
+TYPES OF CREDENTIALS
+====================
+
+The Linux kernel supports the following types of credentials:
+
+ (1) Traditional UNIX credentials.
+
+	Real User ID
+	Real Group ID
+
+     The UID and GID are carried by most, if not all, Linux objects, even if in
+     some cases it has to be invented (FAT or CIFS files for example, which are
+     derived from Windows).  These (mostly) define the objective context of
+     that object, with tasks being slightly different in some cases.
+
+	Effective, Saved and FS User ID
+	Effective, Saved and FS Group ID
+	Supplementary groups
+
+     These are additional credentials used by tasks only.  Usually, an
+     EUID/EGID/GROUPS will be used as the subjective context, and real UID/GID
+     will be used as the objective.  For tasks, it should be noted that this is
+     not always true.
+
+ (2) Capabilities.
+
+	Set of permitted capabilities
+	Set of inheritable capabilities
+	Set of effective capabilities
+	Capability bounding set
+
+     These are only carried by tasks.  They indicate superior capabilities
+     granted piecemeal to a task that an ordinary task wouldn't otherwise have.
+     These are manipulated implicitly by changes to the traditional UNIX
+     credentials, but can also be manipulated directly by the capset() system
+     call.
+
+     The permitted capabilities are those caps that the process might grant
+     itself to its effective or permitted sets through capset().  This
+     inheritable set might also be so constrained.
+
+     The effective capabilities are the ones that a task is actually allowed to
+     make use of itself.
+
+     The inheritable capabilities are the ones that may get passed across
+     execve().
+
+     The bounding set limits the capabilities that may be inherited across
+     execve(), especially when a binary is executed that will execute as UID 0.
+
+ (3) Secure management flags (securebits).
+
+     These are only carried by tasks.  These govern the way the above
+     credentials are manipulated and inherited over certain operations such as
+     execve().  They aren't used directly as objective or subjective
+     credentials.
+
+ (4) Keys and keyrings.
+
+     These are only carried by tasks.  They carry and cache security tokens
+     that don't fit into the other standard UNIX credentials.  They are for
+     making such things as network filesystem keys available to the file
+     accesses performed by processes, without the necessity of ordinary
+     programs having to know about security details involved.
+
+     Keyrings are a special type of key.  They carry sets of other keys and can
+     be searched for the desired key.  Each process may subscribe to a number
+     of keyrings:
+
+	Per-thread keying
+	Per-process keyring
+	Per-session keyring
+
+     When a process accesses a key, if not already present, it will normally be
+     cached on one of these keyrings for future accesses to find.
+
+     For more information on using keys, see Documentation/keys.txt.
+
+ (5) LSM
+
+     The Linux Security Module allows extra controls to be placed over the
+     operations that a task may do.  Currently Linux supports two main
+     alternate LSM options: SELinux and Smack.
+
+     Both work by labelling the objects in a system and then applying sets of
+     rules (policies) that say what operations a task with one label may do to
+     an object with another label.
+
+ (6) AF_KEY
+
+     This is a socket-based approach to credential management for networking
+     stacks [RFC 2367].  It isn't discussed by this document as it doesn't
+     interact directly with task and file credentials; rather it keeps system
+     level credentials.
+
+
+When a file is opened, part of the opening task's subjective context is
+recorded in the file struct created.  This allows operations using that file
+struct to use those credentials instead of the subjective context of the task
+that issued the operation.  An example of this would be a file opened on a
+network filesystem where the credentials of the opened file should be presented
+to the server, regardless of who is actually doing a read or a write upon it.
+
+
+=============
+FILE MARKINGS
+=============
+
+Files on disk or obtained over the network may have annotations that form the
+objective security context of that file.  Depending on the type of filesystem,
+this may include one or more of the following:
+
+ (*) UNIX UID, GID, mode;
+
+ (*) Windows user ID;
+
+ (*) Access control list;
+
+ (*) LSM security label;
+
+ (*) UNIX exec privilege escalation bits (SUID/SGID);
+
+ (*) File capabilities exec privilege escalation bits.
+
+These are compared to the task's subjective security context, and certain
+operations allowed or disallowed as a result.  In the case of execve(), the
+privilege escalation bits come into play, and may allow the resulting process
+extra privileges, based on the annotations on the executable file.
+
+
+================
+TASK CREDENTIALS
+================
+
+In Linux, all of a task's credentials are held in (uid, gid) or through
+(groups, keys, LSM security) a refcounted structure of type 'struct cred'.
+Each task points to its credentials by a pointer called 'cred' in its
+task_struct.
+
+Once a set of credentials has been prepared and committed, it may not be
+changed, barring the following exceptions:
+
+ (1) its reference count may be changed;
+
+ (2) the reference count on the group_info struct it points to may be changed;
+
+ (3) the reference count on the security data it points to may be changed;
+
+ (4) the reference count on any keyrings it points to may be changed;
+
+ (5) any keyrings it points to may be revoked, expired or have their security
+     attributes changed; and
+
+ (6) the contents of any keyrings to which it points may be changed (the whole
+     point of keyrings being a shared set of credentials, modifiable by anyone
+     with appropriate access).
+
+To alter anything in the cred struct, the copy-and-replace principle must be
+adhered to.  First take a copy, then alter the copy and then use RCU to change
+the task pointer to make it point to the new copy.  There are wrappers to aid
+with this (see below).
+
+A task may only alter its _own_ credentials; it is no longer permitted for a
+task to alter another's credentials.  This means the capset() system call is no
+longer permitted to take any PID other than the one of the current process.
+Also keyctl_instantiate() and keyctl_negate() functions no longer permit
+attachment to process-specific keyrings in the requesting process as the
+instantiating process may need to create them.
+
+
+IMMUTABLE CREDENTIALS
+---------------------
+
+Once a set of credentials has been made public (by calling commit_creds() for
+example), it must be considered immutable, barring two exceptions:
+
+ (1) The reference count may be altered.
+
+ (2) Whilst the keyring subscriptions of a set of credentials may not be
+     changed, the keyrings subscribed to may have their contents altered.
+
+To catch accidental credential alteration at compile time, struct task_struct
+has _const_ pointers to its credential sets, as does struct file.  Furthermore,
+certain functions such as get_cred() and put_cred() operate on const pointers,
+thus rendering casts unnecessary, but require to temporarily ditch the const
+qualification to be able to alter the reference count.
+
+
+ACCESSING TASK CREDENTIALS
+--------------------------
+
+A task being able to alter only its own credentials permits the current process
+to read or replace its own credentials without the need for any form of locking
+- which simplifies things greatly.  It can just call:
+
+	const struct cred *current_cred()
+
+to get a pointer to its credentials structure, and it doesn't have to release
+it afterwards.
+
+There are convenience wrappers for retrieving specific aspects of a task's
+credentials (the value is simply returned in each case):
+
+	uid_t current_uid(void)		Current's real UID
+	gid_t current_gid(void)		Current's real GID
+	uid_t current_euid(void)	Current's effective UID
+	gid_t current_egid(void)	Current's effective GID
+	uid_t current_fsuid(void)	Current's file access UID
+	gid_t current_fsgid(void)	Current's file access GID
+	kernel_cap_t current_cap(void)	Current's effective capabilities
+	void *current_security(void)	Current's LSM security pointer
+	struct user_struct *current_user(void)  Current's user account
+
+There are also convenience wrappers for retrieving specific associated pairs of
+a task's credentials:
+
+	void current_uid_gid(uid_t *, gid_t *);
+	void current_euid_egid(uid_t *, gid_t *);
+	void current_fsuid_fsgid(uid_t *, gid_t *);
+
+which return these pairs of values through their arguments after retrieving
+them from the current task's credentials.
+
+
+In addition, there is a function for obtaining a reference on the current
+process's current set of credentials:
+
+	const struct cred *get_current_cred(void);
+
+and functions for getting references to one of the credentials that don't
+actually live in struct cred:
+
+	struct user_struct *get_current_user(void);
+	struct group_info *get_current_groups(void);
+
+which get references to the current process's user accounting structure and
+supplementary groups list respectively.
+
+Once a reference has been obtained, it must be released with put_cred(),
+free_uid() or put_group_info() as appropriate.
+
+
+ACCESSING ANOTHER TASK'S CREDENTIALS
+------------------------------------
+
+Whilst a task may access its own credentials without the need for locking, the
+same is not true of a task wanting to access another task's credentials.  It
+must use the RCU read lock and rcu_dereference().
+
+The rcu_dereference() is wrapped by:
+
+	const struct cred *__task_cred(struct task_struct *task);
+
+This should be used inside the RCU read lock, as in the following example:
+
+	void foo(struct task_struct *t, struct foo_data *f)
+	{
+		const struct cred *tcred;
+		...
+		rcu_read_lock();
+		tcred = __task_cred(t);
+		f->uid = tcred->uid;
+		f->gid = tcred->gid;
+		f->groups = get_group_info(tcred->groups);
+		rcu_read_unlock();
+		...
+	}
+
+A function need not get RCU read lock to use __task_cred() if it is holding a
+spinlock at the time as this implicitly holds the RCU read lock.
+
+Should it be necessary to hold another task's credentials for a long period of
+time, and possibly to sleep whilst doing so, then the caller should get a
+reference on them using:
+
+	const struct cred *get_task_cred(struct task_struct *task);
+
+This does all the RCU magic inside of it.  The caller must call put_cred() on
+the credentials so obtained when they're finished with.
+
+There are a couple of convenience functions to access bits of another task's
+credentials, hiding the RCU magic from the caller:
+
+	uid_t task_uid(task)		Task's real UID
+	uid_t task_euid(task)		Task's effective UID
+
+If the caller is holding a spinlock or the RCU read lock at the time anyway,
+then:
+
+	__task_cred(task)->uid
+	__task_cred(task)->euid
+
+should be used instead.  Similarly, if multiple aspects of a task's credentials
+need to be accessed, RCU read lock or a spinlock should be used, __task_cred()
+called, the result stored in a temporary pointer and then the credential
+aspects called from that before dropping the lock.  This prevents the
+potentially expensive RCU magic from being invoked multiple times.
+
+Should some other single aspect of another task's credentials need to be
+accessed, then this can be used:
+
+	task_cred_xxx(task, member)
+
+where 'member' is a non-pointer member of the cred struct.  For instance:
+
+	uid_t task_cred_xxx(task, suid);
+
+will retrieve 'struct cred::suid' from the task, doing the appropriate RCU
+magic.  This may not be used for pointer members as what they point to may
+disappear the moment the RCU read lock is dropped.
+
+
+ALTERING CREDENTIALS
+--------------------
+
+As previously mentioned, a task may only alter its own credentials, and may not
+alter those of another task.  This means that it doesn't need to use any
+locking to alter its own credentials.
+
+To alter the current process's credentials, a function should first prepare a
+new set of credentials by calling:
+
+	struct cred *prepare_creds(void);
+
+this locks current->cred_replace_mutex and then allocates and constructs a
+duplicate of the current process's credentials, returning with the mutex still
+held if successful.  It returns NULL if not successful (out of memory).
+
+The mutex prevents ptrace() from altering the ptrace state of a process whilst
+security checks on credentials construction and changing is taking place as
+the ptrace state may alter the outcome, particularly in the case of execve().
+
+The new credentials set should be altered appropriately, and any security
+checks and hooks done.  Both the current and the proposed sets of credentials
+are available for this purpose as current_cred() will return the current set
+still at this point.
+
+
+When the credential set is ready, it should be committed to the current process
+by calling:
+
+	int commit_creds(struct cred *new);
+
+This will alter various aspects of the credentials and the process, giving the
+LSM a chance to do likewise, then it will use rcu_assign_pointer() to actually
+commit the new credentials to current->cred, it will release
+current->cred_replace_mutex to allow ptrace() to take place, and it will notify
+the scheduler and others of the changes.
+
+This function is guaranteed to return 0, so that it can be tail-called at the
+end of such functions as sys_setresuid().
+
+Note that this function consumes the caller's reference to the new credentials.
+The caller should _not_ call put_cred() on the new credentials afterwards.
+
+Furthermore, once this function has been called on a new set of credentials,
+those credentials may _not_ be changed further.
+
+
+Should the security checks fail or some other error occur after prepare_creds()
+has been called, then the following function should be invoked:
+
+	void abort_creds(struct cred *new);
+
+This releases the lock on current->cred_replace_mutex that prepare_creds() got
+and then releases the new credentials.
+
+
+A typical credentials alteration function would look something like this:
+
+	int alter_suid(uid_t suid)
+	{
+		struct cred *new;
+		int ret;
+
+		new = prepare_creds();
+		if (!new)
+			return -ENOMEM;
+
+		new->suid = suid;
+		ret = security_alter_suid(new);
+		if (ret < 0) {
+			abort_creds(new);
+			return ret;
+		}
+
+		return commit_creds(new);
+	}
+
+
+MANAGING CREDENTIALS
+--------------------
+
+There are some functions to help manage credentials:
+
+ (*) void put_cred(const struct cred *cred);
+
+     This releases a reference to the given set of credentials.  If the
+     reference count reaches zero, the credentials will be scheduled for
+     destruction by the RCU system.
+
+ (*) const struct cred *get_cred(const struct cred *cred);
+
+     This gets a reference on a live set of credentials, returning a pointer to
+     that set of credentials.
+
+ (*) struct cred *get_new_cred(struct cred *cred);
+
+     This gets a reference on a set of credentials that is under construction
+     and is thus still mutable, returning a pointer to that set of credentials.
+
+
+=====================
+OPEN FILE CREDENTIALS
+=====================
+
+When a new file is opened, a reference is obtained on the opening task's
+credentials and this is attached to the file struct as 'f_cred' in place of
+'f_uid' and 'f_gid'.  Code that used to access file->f_uid and file->f_gid
+should now access file->f_cred->fsuid and file->f_cred->fsgid.
+
+It is safe to access f_cred without the use of RCU or locking because the
+pointer will not change over the lifetime of the file struct, and nor will the
+contents of the cred struct pointed to, barring the exceptions listed above
+(see the Task Credentials section).
+
+
+=======================================
+OVERRIDING THE VFS'S USE OF CREDENTIALS
+=======================================
+
+Under some circumstances it is desirable to override the credentials used by
+the VFS, and that can be done by calling into such as vfs_mkdir() with a
+different set of credentials.  This is done in the following places:
+
+ (*) sys_faccessat().
+
+ (*) do_coredump().
+
+ (*) nfs4recover.c.

+ 4 - 0
Documentation/kernel-parameters.txt

@@ -1452,6 +1452,10 @@ and is between 256 and 4096 characters. It is defined in the file
 			instruction doesn't work correctly and not to
 			instruction doesn't work correctly and not to
 			use it.
 			use it.
 
 
+	no_file_caps	Tells the kernel not to honor file capabilities.  The
+			only way then for a file to be executed with privilege
+			is to be setuid root or executed by root.
+
 	nohalt		[IA-64] Tells the kernel not to use the power saving
 	nohalt		[IA-64] Tells the kernel not to use the power saving
 			function PAL_HALT_LIGHT when idle. This increases
 			function PAL_HALT_LIGHT when idle. This increases
 			power-consumption. On the positive side, it reduces
 			power-consumption. On the positive side, it reduces

+ 21 - 0
Documentation/scheduler/sched-design-CFS.txt

@@ -273,3 +273,24 @@ task groups and modify their CPU share using the "cgroups" pseudo filesystem.
 
 
 	# #Launch gmplayer (or your favourite movie player)
 	# #Launch gmplayer (or your favourite movie player)
 	# echo <movie_player_pid> > multimedia/tasks
 	# echo <movie_player_pid> > multimedia/tasks
+
+8. Implementation note: user namespaces
+
+User namespaces are intended to be hierarchical.  But they are currently
+only partially implemented.  Each of those has ramifications for CFS.
+
+First, since user namespaces are hierarchical, the /sys/kernel/uids
+presentation is inadequate.  Eventually we will likely want to use sysfs
+tagging to provide private views of /sys/kernel/uids within each user
+namespace.
+
+Second, the hierarchical nature is intended to support completely
+unprivileged use of user namespaces.  So if using user groups, then
+we want the users in a user namespace to be children of the user
+who created it.
+
+That is currently unimplemented.  So instead, every user in a new
+user namespace will receive 1024 shares just like any user in the
+initial user namespace.  Note that at the moment creation of a new
+user namespace requires each of CAP_SYS_ADMIN, CAP_SETUID, and
+CAP_SETGID.

+ 7 - 4
arch/alpha/kernel/asm-offsets.c

@@ -19,15 +19,18 @@ void foo(void)
 	BLANK();
 	BLANK();
 
 
         DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
         DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
-        DEFINE(TASK_UID, offsetof(struct task_struct, uid));
-        DEFINE(TASK_EUID, offsetof(struct task_struct, euid));
-        DEFINE(TASK_GID, offsetof(struct task_struct, gid));
-        DEFINE(TASK_EGID, offsetof(struct task_struct, egid));
+        DEFINE(TASK_CRED, offsetof(struct task_struct, cred));
         DEFINE(TASK_REAL_PARENT, offsetof(struct task_struct, real_parent));
         DEFINE(TASK_REAL_PARENT, offsetof(struct task_struct, real_parent));
         DEFINE(TASK_GROUP_LEADER, offsetof(struct task_struct, group_leader));
         DEFINE(TASK_GROUP_LEADER, offsetof(struct task_struct, group_leader));
         DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
         DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
         BLANK();
         BLANK();
 
 
+        DEFINE(CRED_UID,  offsetof(struct cred, uid));
+        DEFINE(CRED_EUID, offsetof(struct cred, euid));
+        DEFINE(CRED_GID,  offsetof(struct cred, gid));
+        DEFINE(CRED_EGID, offsetof(struct cred, egid));
+        BLANK();
+
 	DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs));
 	DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs));
 	DEFINE(PT_PTRACED, PT_PTRACED);
 	DEFINE(PT_PTRACED, PT_PTRACED);
 	DEFINE(CLONE_VM, CLONE_VM);
 	DEFINE(CLONE_VM, CLONE_VM);

+ 6 - 4
arch/alpha/kernel/entry.S

@@ -850,8 +850,9 @@ osf_getpriority:
 sys_getxuid:
 sys_getxuid:
 	.prologue 0
 	.prologue 0
 	ldq	$2, TI_TASK($8)
 	ldq	$2, TI_TASK($8)
-	ldl	$0, TASK_UID($2)
-	ldl	$1, TASK_EUID($2)
+	ldq	$3, TASK_CRED($2)
+	ldl	$0, CRED_UID($3)
+	ldl	$1, CRED_EUID($3)
 	stq	$1, 80($sp)
 	stq	$1, 80($sp)
 	ret
 	ret
 .end sys_getxuid
 .end sys_getxuid
@@ -862,8 +863,9 @@ sys_getxuid:
 sys_getxgid:
 sys_getxgid:
 	.prologue 0
 	.prologue 0
 	ldq	$2, TI_TASK($8)
 	ldq	$2, TI_TASK($8)
-	ldl	$0, TASK_GID($2)
-	ldl	$1, TASK_EGID($2)
+	ldq	$3, TASK_CRED($2)
+	ldl	$0, CRED_GID($3)
+	ldl	$1, CRED_EGID($3)
 	stq	$1, 80($sp)
 	stq	$1, 80($sp)
 	ret
 	ret
 .end sys_getxgid
 .end sys_getxgid

+ 3 - 4
arch/ia64/ia32/sys_ia32.c

@@ -1767,25 +1767,24 @@ groups16_from_user(struct group_info *group_info, short __user *grouplist)
 asmlinkage long
 asmlinkage long
 sys32_getgroups16 (int gidsetsize, short __user *grouplist)
 sys32_getgroups16 (int gidsetsize, short __user *grouplist)
 {
 {
+	const struct cred *cred = current_cred();
 	int i;
 	int i;
 
 
 	if (gidsetsize < 0)
 	if (gidsetsize < 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	get_group_info(current->group_info);
-	i = current->group_info->ngroups;
+	i = cred->group_info->ngroups;
 	if (gidsetsize) {
 	if (gidsetsize) {
 		if (i > gidsetsize) {
 		if (i > gidsetsize) {
 			i = -EINVAL;
 			i = -EINVAL;
 			goto out;
 			goto out;
 		}
 		}
-		if (groups16_to_user(grouplist, current->group_info)) {
+		if (groups16_to_user(grouplist, cred->group_info)) {
 			i = -EFAULT;
 			i = -EFAULT;
 			goto out;
 			goto out;
 		}
 		}
 	}
 	}
 out:
 out:
-	put_group_info(current->group_info);
 	return i;
 	return i;
 }
 }
 
 

+ 1 - 1
arch/ia64/kernel/mca_drv.c

@@ -158,7 +158,7 @@ mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
 	ia64_mlogbuf_dump();
 	ia64_mlogbuf_dump();
 	printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
 	printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
 		"iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
 		"iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
-		raw_smp_processor_id(), current->pid, current->uid,
+	       raw_smp_processor_id(), current->pid, current_uid(),
 		iip, ipsr, paddr, current->comm);
 		iip, ipsr, paddr, current->comm);
 
 
 	spin_lock(&mca_bh_lock);
 	spin_lock(&mca_bh_lock);

+ 27 - 16
arch/ia64/kernel/perfmon.c

@@ -2220,8 +2220,8 @@ pfm_alloc_file(pfm_context_t *ctx)
 	DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode));
 	DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode));
 
 
 	inode->i_mode = S_IFCHR|S_IRUGO;
 	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);
 	sprintf(name, "[%lu]", inode->i_ino);
 	this.name = name;
 	this.name = name;
@@ -2399,22 +2399,33 @@ error_kmem:
 static int
 static int
 pfm_bad_permissions(struct task_struct *task)
 pfm_bad_permissions(struct task_struct *task)
 {
 {
+	const struct cred *tcred;
+	uid_t uid = current_uid();
+	gid_t gid = current_gid();
+	int ret;
+
+	rcu_read_lock();
+	tcred = __task_cred(task);
+
 	/* inspired by ptrace_attach() */
 	/* inspired by ptrace_attach() */
 	DPRINT(("cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n",
 	DPRINT(("cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n",
-		current->uid,
-		current->gid,
-		task->euid,
-		task->suid,
-		task->uid,
-		task->egid,
-		task->sgid));
-
-	return ((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);
+		uid,
+		gid,
+		tcred->euid,
+		tcred->suid,
+		tcred->uid,
+		tcred->egid,
+		tcred->sgid));
+
+	ret = ((uid != tcred->euid)
+	       || (uid != tcred->suid)
+	       || (uid != tcred->uid)
+	       || (gid != tcred->egid)
+	       || (gid != tcred->sgid)
+	       || (gid != tcred->gid)) && !capable(CAP_SYS_PTRACE);
+
+	rcu_read_unlock();
+	return ret;
 }
 }
 
 
 static int
 static int

+ 2 - 2
arch/ia64/kernel/signal.c

@@ -229,7 +229,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
 	si.si_errno = 0;
 	si.si_errno = 0;
 	si.si_code = SI_KERNEL;
 	si.si_code = SI_KERNEL;
 	si.si_pid = task_pid_vnr(current);
 	si.si_pid = task_pid_vnr(current);
-	si.si_uid = current->uid;
+	si.si_uid = current_uid();
 	si.si_addr = sc;
 	si.si_addr = sc;
 	force_sig_info(SIGSEGV, &si, current);
 	force_sig_info(SIGSEGV, &si, current);
 	return retval;
 	return retval;
@@ -326,7 +326,7 @@ force_sigsegv_info (int sig, void __user *addr)
 	si.si_errno = 0;
 	si.si_errno = 0;
 	si.si_code = SI_KERNEL;
 	si.si_code = SI_KERNEL;
 	si.si_pid = task_pid_vnr(current);
 	si.si_pid = task_pid_vnr(current);
-	si.si_uid = current->uid;
+	si.si_uid = current_uid();
 	si.si_addr = addr;
 	si.si_addr = addr;
 	force_sig_info(SIGSEGV, &si, current);
 	force_sig_info(SIGSEGV, &si, current);
 	return 0;
 	return 0;

+ 2 - 2
arch/mips/kernel/kspd.c

@@ -174,8 +174,8 @@ static unsigned int translate_open_flags(int flags)
 
 
 static void sp_setfsuidgid( uid_t uid, gid_t gid)
 static void sp_setfsuidgid( uid_t uid, gid_t gid)
 {
 {
-	current->fsuid = uid;
-	current->fsgid = gid;
+	current->cred->fsuid = uid;
+	current->cred->fsgid = gid;
 
 
 	key_fsuid_changed(current);
 	key_fsuid_changed(current);
 	key_fsgid_changed(current);
 	key_fsgid_changed(current);

+ 3 - 2
arch/mips/kernel/mips-mt-fpaff.c

@@ -51,6 +51,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
 	int retval;
 	int retval;
 	struct task_struct *p;
 	struct task_struct *p;
 	struct thread_info *ti;
 	struct thread_info *ti;
+	uid_t euid;
 
 
 	if (len < sizeof(new_mask))
 	if (len < sizeof(new_mask))
 		return -EINVAL;
 		return -EINVAL;
@@ -76,9 +77,9 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
 	 */
 	 */
 	get_task_struct(p);
 	get_task_struct(p);
 
 
+	euid = current_euid();
 	retval = -EPERM;
 	retval = -EPERM;
-	if ((current->euid != p->euid) && (current->euid != p->uid) &&
-			!capable(CAP_SYS_NICE)) {
+	if (euid != p->euid && euid != p->uid && !capable(CAP_SYS_NICE)) {
 		read_unlock(&tasklist_lock);
 		read_unlock(&tasklist_lock);
 		goto out_unlock;
 		goto out_unlock;
 	}
 	}

+ 2 - 2
arch/mips/kernel/vpe.c

@@ -1085,8 +1085,8 @@ static int vpe_open(struct inode *inode, struct file *filp)
 	v->load_addr = NULL;
 	v->load_addr = NULL;
 	v->len = 0;
 	v->len = 0;
 
 
-	v->uid = filp->f_uid;
-	v->gid = filp->f_gid;
+	v->uid = filp->f_cred->fsuid;
+	v->gid = filp->f_cred->fsgid;
 
 
 #ifdef CONFIG_MIPS_APSP_KSPD
 #ifdef CONFIG_MIPS_APSP_KSPD
 	/* get kspd to tell us when a syscall_exit happens */
 	/* get kspd to tell us when a syscall_exit happens */

+ 1 - 1
arch/parisc/kernel/signal.c

@@ -182,7 +182,7 @@ give_sigsegv:
 	si.si_errno = 0;
 	si.si_errno = 0;
 	si.si_code = SI_KERNEL;
 	si.si_code = SI_KERNEL;
 	si.si_pid = task_pid_vnr(current);
 	si.si_pid = task_pid_vnr(current);
-	si.si_uid = current->uid;
+	si.si_uid = current_uid();
 	si.si_addr = &frame->uc;
 	si.si_addr = &frame->uc;
 	force_sig_info(SIGSEGV, &si, current);
 	force_sig_info(SIGSEGV, &si, current);
 	return;
 	return;

+ 1 - 1
arch/powerpc/mm/fault.c

@@ -339,7 +339,7 @@ bad_area_nosemaphore:
 	    && printk_ratelimit())
 	    && printk_ratelimit())
 		printk(KERN_CRIT "kernel tried to execute NX-protected"
 		printk(KERN_CRIT "kernel tried to execute NX-protected"
 		       " page (%lx) - exploit attempt? (uid: %d)\n",
 		       " page (%lx) - exploit attempt? (uid: %d)\n",
-		       address, current->uid);
+		       address, current_uid());
 
 
 	return SIGSEGV;
 	return SIGSEGV;
 
 

+ 4 - 4
arch/powerpc/platforms/cell/spufs/inode.c

@@ -95,8 +95,8 @@ spufs_new_inode(struct super_block *sb, int mode)
 		goto out;
 		goto out;
 
 
 	inode->i_mode = mode;
 	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_blocks = 0;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 out:
 out:
@@ -323,7 +323,7 @@ static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt)
 		goto out;
 		goto out;
 	}
 	}
 
 
-	filp = dentry_open(dentry, mnt, O_RDONLY);
+	filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
 	if (IS_ERR(filp)) {
 	if (IS_ERR(filp)) {
 		put_unused_fd(ret);
 		put_unused_fd(ret);
 		ret = PTR_ERR(filp);
 		ret = PTR_ERR(filp);
@@ -562,7 +562,7 @@ static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
 		goto out;
 		goto out;
 	}
 	}
 
 
-	filp = dentry_open(dentry, mnt, O_RDONLY);
+	filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
 	if (IS_ERR(filp)) {
 	if (IS_ERR(filp)) {
 		put_unused_fd(ret);
 		put_unused_fd(ret);
 		ret = PTR_ERR(filp);
 		ret = PTR_ERR(filp);

+ 2 - 2
arch/s390/hypfs/inode.c

@@ -280,8 +280,8 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
 	if (!sbi)
 	if (!sbi)
 		return -ENOMEM;
 		return -ENOMEM;
 	mutex_init(&sbi->lock);
 	mutex_init(&sbi->lock);
-	sbi->uid = current->uid;
-	sbi->gid = current->gid;
+	sbi->uid = current_uid();
+	sbi->gid = current_gid();
 	sb->s_fs_info = sbi;
 	sb->s_fs_info = sbi;
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;

+ 14 - 14
arch/s390/kernel/compat_linux.c

@@ -148,9 +148,9 @@ asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user
 {
 {
 	int retval;
 	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->cred->uid), ruid)) &&
+	    !(retval = put_user(high2lowuid(current->cred->euid), euid)))
+		retval = put_user(high2lowuid(current->cred->suid), suid);
 
 
 	return retval;
 	return retval;
 }
 }
@@ -165,9 +165,9 @@ asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user
 {
 {
 	int retval;
 	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->cred->gid), rgid)) &&
+	    !(retval = put_user(high2lowgid(current->cred->egid), egid)))
+		retval = put_user(high2lowgid(current->cred->sgid), sgid);
 
 
 	return retval;
 	return retval;
 }
 }
@@ -217,20 +217,20 @@ asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
 	if (gidsetsize < 0)
 	if (gidsetsize < 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	get_group_info(current->group_info);
-	i = current->group_info->ngroups;
+	get_group_info(current->cred->group_info);
+	i = current->cred->group_info->ngroups;
 	if (gidsetsize) {
 	if (gidsetsize) {
 		if (i > gidsetsize) {
 		if (i > gidsetsize) {
 			i = -EINVAL;
 			i = -EINVAL;
 			goto out;
 			goto out;
 		}
 		}
-		if (groups16_to_user(grouplist, current->group_info)) {
+		if (groups16_to_user(grouplist, current->cred->group_info)) {
 			i = -EFAULT;
 			i = -EFAULT;
 			goto out;
 			goto out;
 		}
 		}
 	}
 	}
 out:
 out:
-	put_group_info(current->group_info);
+	put_group_info(current->cred->group_info);
 	return i;
 	return i;
 }
 }
 
 
@@ -261,22 +261,22 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
 
 
 asmlinkage long sys32_getuid16(void)
 asmlinkage long sys32_getuid16(void)
 {
 {
-	return high2lowuid(current->uid);
+	return high2lowuid(current->cred->uid);
 }
 }
 
 
 asmlinkage long sys32_geteuid16(void)
 asmlinkage long sys32_geteuid16(void)
 {
 {
-	return high2lowuid(current->euid);
+	return high2lowuid(current->cred->euid);
 }
 }
 
 
 asmlinkage long sys32_getgid16(void)
 asmlinkage long sys32_getgid16(void)
 {
 {
-	return high2lowgid(current->gid);
+	return high2lowgid(current->cred->gid);
 }
 }
 
 
 asmlinkage long sys32_getegid16(void)
 asmlinkage long sys32_getegid16(void)
 {
 {
-	return high2lowgid(current->egid);
+	return high2lowgid(current->cred->egid);
 }
 }
 
 
 /*
 /*

+ 2 - 1
arch/um/drivers/mconsole_kern.c

@@ -161,7 +161,8 @@ void mconsole_proc(struct mc_request *req)
 		goto out_kill;
 		goto out_kill;
 	}
 	}
 
 
-	file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY);
+	file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
+			   current_cred());
 	if (IS_ERR(file)) {
 	if (IS_ERR(file)) {
 		mconsole_reply(req, "Failed to open file", 1, 0);
 		mconsole_reply(req, "Failed to open file", 1, 0);
 		goto out_kill;
 		goto out_kill;

+ 1 - 1
arch/x86/ia32/ia32_aout.c

@@ -327,7 +327,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 	current->mm->cached_hole_size = 0;
 	current->mm->cached_hole_size = 0;
 
 
 	current->mm->mmap = NULL;
 	current->mm->mmap = NULL;
-	compute_creds(bprm);
+	install_exec_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
 	current->flags &= ~PF_FORKNOEXEC;
 
 
 	if (N_MAGIC(ex) == OMAGIC) {
 	if (N_MAGIC(ex) == OMAGIC) {

+ 1 - 1
arch/x86/mm/fault.c

@@ -393,7 +393,7 @@ static void show_fault_oops(struct pt_regs *regs, unsigned long error_code,
 		if (pte && pte_present(*pte) && !pte_exec(*pte))
 		if (pte && pte_present(*pte) && !pte_exec(*pte))
 			printk(KERN_CRIT "kernel tried to execute "
 			printk(KERN_CRIT "kernel tried to execute "
 				"NX-protected page - exploit attempt? "
 				"NX-protected page - exploit attempt? "
-				"(uid: %d)\n", current->uid);
+				"(uid: %d)\n", current_uid());
 	}
 	}
 #endif
 #endif
 
 

+ 4 - 2
drivers/block/loop.c

@@ -936,8 +936,10 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 {
 {
 	int err;
 	int err;
 	struct loop_func_table *xfer;
 	struct loop_func_table *xfer;
+	uid_t uid = current_uid();
 
 
-	if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid &&
+	if (lo->lo_encrypt_key_size &&
+	    lo->lo_key_owner != uid &&
 	    !capable(CAP_SYS_ADMIN))
 	    !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 		return -EPERM;
 	if (lo->lo_state != Lo_bound)
 	if (lo->lo_state != Lo_bound)
@@ -992,7 +994,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 	if (info->lo_encrypt_key_size) {
 	if (info->lo_encrypt_key_size) {
 		memcpy(lo->lo_encrypt_key, info->lo_encrypt_key,
 		memcpy(lo->lo_encrypt_key, info->lo_encrypt_key,
 		       info->lo_encrypt_key_size);
 		       info->lo_encrypt_key_size);
-		lo->lo_key_owner = current->uid;
+		lo->lo_key_owner = uid;
 	}	
 	}	
 
 
 	return 0;
 	return 0;

+ 61 - 15
drivers/char/tty_audit.c

@@ -67,6 +67,29 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf)
 		tty_audit_buf_free(buf);
 		tty_audit_buf_free(buf);
 }
 }
 
 
+static void tty_audit_log(const char *description, struct task_struct *tsk,
+			  uid_t loginuid, unsigned sessionid, int major,
+			  int minor, unsigned char *data, size_t size)
+{
+	struct audit_buffer *ab;
+
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
+	if (ab) {
+		char name[sizeof(tsk->comm)];
+		uid_t uid = task_uid(tsk);
+
+		audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u "
+				 "major=%d minor=%d comm=", description,
+				 tsk->pid, uid, loginuid, sessionid,
+				 major, minor);
+		get_task_comm(name, tsk);
+		audit_log_untrustedstring(ab, name);
+		audit_log_format(ab, " data=");
+		audit_log_n_hex(ab, data, size);
+		audit_log_end(ab);
+	}
+}
+
 /**
 /**
  *	tty_audit_buf_push	-	Push buffered data out
  *	tty_audit_buf_push	-	Push buffered data out
  *
  *
@@ -77,25 +100,12 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
 			       unsigned int sessionid,
 			       unsigned int sessionid,
 			       struct tty_audit_buf *buf)
 			       struct tty_audit_buf *buf)
 {
 {
-	struct audit_buffer *ab;
-
 	if (buf->valid == 0)
 	if (buf->valid == 0)
 		return;
 		return;
 	if (audit_enabled == 0)
 	if (audit_enabled == 0)
 		return;
 		return;
-	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
-	if (ab) {
-		char name[sizeof(tsk->comm)];
-
-		audit_log_format(ab, "tty pid=%u uid=%u auid=%u ses=%u "
-				 "major=%d minor=%d comm=", tsk->pid, tsk->uid,
-				 loginuid, sessionid, buf->major, buf->minor);
-		get_task_comm(name, tsk);
-		audit_log_untrustedstring(ab, name);
-		audit_log_format(ab, " data=");
-		audit_log_n_hex(ab, buf->data, buf->valid);
-		audit_log_end(ab);
-	}
+	tty_audit_log("tty", tsk, loginuid, sessionid, buf->major, buf->minor,
+		      buf->data, buf->valid);
 	buf->valid = 0;
 	buf->valid = 0;
 }
 }
 
 
@@ -149,6 +159,42 @@ void tty_audit_fork(struct signal_struct *sig)
 	sig->tty_audit_buf = NULL;
 	sig->tty_audit_buf = NULL;
 }
 }
 
 
+/**
+ *	tty_audit_tiocsti	-	Log TIOCSTI
+ */
+void tty_audit_tiocsti(struct tty_struct *tty, char ch)
+{
+	struct tty_audit_buf *buf;
+	int major, minor, should_audit;
+
+	spin_lock_irq(&current->sighand->siglock);
+	should_audit = current->signal->audit_tty;
+	buf = current->signal->tty_audit_buf;
+	if (buf)
+		atomic_inc(&buf->count);
+	spin_unlock_irq(&current->sighand->siglock);
+
+	major = tty->driver->major;
+	minor = tty->driver->minor_start + tty->index;
+	if (buf) {
+		mutex_lock(&buf->mutex);
+		if (buf->major == major && buf->minor == minor)
+			tty_audit_buf_push_current(buf);
+		mutex_unlock(&buf->mutex);
+		tty_audit_buf_put(buf);
+	}
+
+	if (should_audit && audit_enabled) {
+		uid_t auid;
+		unsigned int sessionid;
+
+		auid = audit_get_loginuid(current);
+		sessionid = audit_get_sessionid(current);
+		tty_audit_log("ioctl=TIOCSTI", current, auid, sessionid, major,
+			      minor, &ch, 1);
+	}
+}
+
 /**
 /**
  *	tty_audit_push_task	-	Flush task's pending audit data
  *	tty_audit_push_task	-	Flush task's pending audit data
  */
  */

+ 1 - 0
drivers/char/tty_io.c

@@ -2018,6 +2018,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
 		return -EPERM;
 		return -EPERM;
 	if (get_user(ch, p))
 	if (get_user(ch, p))
 		return -EFAULT;
 		return -EFAULT;
+	tty_audit_tiocsti(tty, ch);
 	ld = tty_ldisc_ref_wait(tty);
 	ld = tty_ldisc_ref_wait(tty);
 	ld->ops->receive_buf(tty, &ch, &mbz, 1);
 	ld->ops->receive_buf(tty, &ch, &mbz, 1);
 	tty_ldisc_deref(ld);
 	tty_ldisc_deref(ld);

+ 11 - 5
drivers/connector/cn_proc.c

@@ -106,6 +106,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
 	struct proc_event *ev;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE];
 	__u8 buffer[CN_PROC_MSG_SIZE];
 	struct timespec ts;
 	struct timespec ts;
+	const struct cred *cred;
 
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
 		return;
@@ -115,14 +116,19 @@ void proc_id_connector(struct task_struct *task, int which_id)
 	ev->what = which_id;
 	ev->what = which_id;
 	ev->event_data.id.process_pid = task->pid;
 	ev->event_data.id.process_pid = task->pid;
 	ev->event_data.id.process_tgid = task->tgid;
 	ev->event_data.id.process_tgid = task->tgid;
+	rcu_read_lock();
+	cred = __task_cred(task);
 	if (which_id == PROC_EVENT_UID) {
 	if (which_id == PROC_EVENT_UID) {
-	 	ev->event_data.id.r.ruid = task->uid;
-	 	ev->event_data.id.e.euid = task->euid;
+		ev->event_data.id.r.ruid = cred->uid;
+		ev->event_data.id.e.euid = cred->euid;
 	} else if (which_id == PROC_EVENT_GID) {
 	} else if (which_id == PROC_EVENT_GID) {
-	   	ev->event_data.id.r.rgid = task->gid;
-	   	ev->event_data.id.e.egid = task->egid;
-	} else
+		ev->event_data.id.r.rgid = cred->gid;
+		ev->event_data.id.e.egid = cred->egid;
+	} else {
+		rcu_read_unlock();
 	     	return;
 	     	return;
+	}
+	rcu_read_unlock();
 	get_seq(&msg->seq, &ev->cpu);
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);

+ 2 - 2
drivers/isdn/capi/capifs.c

@@ -156,8 +156,8 @@ void capifs_new_ncci(unsigned int number, dev_t device)
 	if (!inode)
 	if (!inode)
 		return;
 		return;
 	inode->i_ino = number+2;
 	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;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	//inode->i_op = &capifs_file_inode_operations;
 	//inode->i_op = &capifs_file_inode_operations;

+ 4 - 2
drivers/isdn/hysdn/hysdn_procconf.c

@@ -246,7 +246,8 @@ hysdn_conf_open(struct inode *ino, struct file *filep)
 	}
 	}
 	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
 	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
 		hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x",
 		hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x",
-			     filep->f_uid, filep->f_gid, filep->f_mode);
+			     filep->f_cred->fsuid, filep->f_cred->fsgid,
+			     filep->f_mode);
 
 
 	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
 	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
 		/* write only access -> write boot file or conf line */
 		/* write only access -> write boot file or conf line */
@@ -331,7 +332,8 @@ hysdn_conf_close(struct inode *ino, struct file *filep)
 	}
 	}
 	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
 	if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
 		hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x",
 		hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x",
-			     filep->f_uid, filep->f_gid, filep->f_mode);
+			     filep->f_cred->fsuid, filep->f_cred->fsgid,
+			     filep->f_mode);
 
 
 	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
 	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
 		/* write only access -> write boot file or conf line */
 		/* write only access -> write boot file or conf line */

+ 5 - 3
drivers/net/tun.c

@@ -702,6 +702,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 	struct tun_net *tn;
 	struct tun_net *tn;
 	struct tun_struct *tun;
 	struct tun_struct *tun;
 	struct net_device *dev;
 	struct net_device *dev;
+	const struct cred *cred = current_cred();
 	int err;
 	int err;
 
 
 	tn = net_generic(net, tun_net_id);
 	tn = net_generic(net, tun_net_id);
@@ -712,11 +713,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
 
 		/* Check permissions */
 		/* Check permissions */
 		if (((tun->owner != -1 &&
 		if (((tun->owner != -1 &&
-		      current->euid != tun->owner) ||
+		      cred->euid != tun->owner) ||
 		     (tun->group != -1 &&
 		     (tun->group != -1 &&
-		      current->egid != tun->group)) &&
-		     !capable(CAP_NET_ADMIN))
+		      cred->egid != tun->group)) &&
+		    !capable(CAP_NET_ADMIN)) {
 			return -EPERM;
 			return -EPERM;
+		}
 	}
 	}
 	else if (__dev_get_by_name(net, ifr->ifr_name))
 	else if (__dev_get_by_name(net, ifr->ifr_name))
 		return -EINVAL;
 		return -EINVAL;

+ 6 - 4
drivers/usb/core/devio.c

@@ -574,6 +574,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
 {
 {
 	struct usb_device *dev = NULL;
 	struct usb_device *dev = NULL;
 	struct dev_state *ps;
 	struct dev_state *ps;
+	const struct cred *cred = current_cred();
 	int ret;
 	int ret;
 
 
 	lock_kernel();
 	lock_kernel();
@@ -617,8 +618,8 @@ static int usbdev_open(struct inode *inode, struct file *file)
 	init_waitqueue_head(&ps->wait);
 	init_waitqueue_head(&ps->wait);
 	ps->discsignr = 0;
 	ps->discsignr = 0;
 	ps->disc_pid = get_pid(task_pid(current));
 	ps->disc_pid = get_pid(task_pid(current));
-	ps->disc_uid = current->uid;
-	ps->disc_euid = current->euid;
+	ps->disc_uid = cred->uid;
+	ps->disc_euid = cred->euid;
 	ps->disccontext = NULL;
 	ps->disccontext = NULL;
 	ps->ifclaimed = 0;
 	ps->ifclaimed = 0;
 	security_task_getsecid(current, &ps->secid);
 	security_task_getsecid(current, &ps->secid);
@@ -967,6 +968,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	struct usb_host_endpoint *ep;
 	struct usb_host_endpoint *ep;
 	struct async *as;
 	struct async *as;
 	struct usb_ctrlrequest *dr = NULL;
 	struct usb_ctrlrequest *dr = NULL;
+	const struct cred *cred = current_cred();
 	unsigned int u, totlen, isofrmlen;
 	unsigned int u, totlen, isofrmlen;
 	int ret, ifnum = -1;
 	int ret, ifnum = -1;
 	int is_in;
 	int is_in;
@@ -1174,8 +1176,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	as->signr = uurb->signr;
 	as->signr = uurb->signr;
 	as->ifnum = ifnum;
 	as->ifnum = ifnum;
 	as->pid = get_pid(task_pid(current));
 	as->pid = get_pid(task_pid(current));
-	as->uid = current->uid;
-	as->euid = current->euid;
+	as->uid = cred->uid;
+	as->euid = cred->euid;
 	security_task_getsecid(current, &as->secid);
 	security_task_getsecid(current, &as->secid);
 	if (!is_in) {
 	if (!is_in) {
 		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
 		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,

+ 2 - 2
drivers/usb/core/inode.c

@@ -277,8 +277,8 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
 
 
 	if (inode) {
 	if (inode) {
 		inode->i_mode = mode;
 		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_blocks = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		switch (mode & S_IFMT) {
 		switch (mode & S_IFMT) {

+ 1 - 1
fs/9p/fid.c

@@ -120,7 +120,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
 	switch (access) {
 	switch (access) {
 	case V9FS_ACCESS_SINGLE:
 	case V9FS_ACCESS_SINGLE:
 	case V9FS_ACCESS_USER:
 	case V9FS_ACCESS_USER:
-		uid = current->fsuid;
+		uid = current_fsuid();
 		any = 0;
 		any = 0;
 		break;
 		break;
 
 

+ 2 - 2
fs/9p/vfs_inode.c

@@ -215,8 +215,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 	inode = new_inode(sb);
 	inode = new_inode(sb);
 	if (inode) {
 	if (inode) {
 		inode->i_mode = mode;
 		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_blocks = 0;
 		inode->i_rdev = 0;
 		inode->i_rdev = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;

+ 2 - 2
fs/9p/vfs_super.c

@@ -113,8 +113,8 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
 	struct v9fs_session_info *v9ses = NULL;
 	struct v9fs_session_info *v9ses = NULL;
 	struct p9_wstat *st = NULL;
 	struct p9_wstat *st = NULL;
 	int mode = S_IRWXUGO | S_ISVTX;
 	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;
 	struct p9_fid *fid;
 	int retval = 0;
 	int retval = 0;
 
 

+ 2 - 2
fs/affs/inode.c

@@ -293,8 +293,8 @@ affs_new_inode(struct inode *dir)
 	mark_buffer_dirty_inode(bh, inode);
 	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
 	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_ino     = block;
 	inode->i_nlink   = 1;
 	inode->i_nlink   = 1;
 	inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;

+ 2 - 2
fs/affs/super.c

@@ -163,8 +163,8 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
 
 
 	/* Fill in defaults */
 	/* Fill in defaults */
 
 
-	*uid        = current->uid;
-	*gid        = current->gid;
+	*uid        = current_uid();
+	*gid        = current_gid();
 	*reserved   = 2;
 	*reserved   = 2;
 	*root       = -1;
 	*root       = -1;
 	*blocksize  = -1;
 	*blocksize  = -1;

+ 2 - 2
fs/anon_inodes.c

@@ -154,8 +154,8 @@ static struct inode *anon_inode_mkinode(void)
 	 */
 	 */
 	inode->i_state = I_DIRTY;
 	inode->i_state = I_DIRTY;
 	inode->i_mode = S_IRUSR | S_IWUSR;
 	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;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	return inode;
 	return inode;
 }
 }

+ 2 - 2
fs/attr.c

@@ -29,13 +29,13 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
 
 
 	/* Make sure a caller can chown. */
 	/* Make sure a caller can chown. */
 	if ((ia_valid & ATTR_UID) &&
 	if ((ia_valid & ATTR_UID) &&
-	    (current->fsuid != inode->i_uid ||
+	    (current_fsuid() != inode->i_uid ||
 	     attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
 	     attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
 		goto error;
 		goto error;
 
 
 	/* Make sure caller can chgrp. */
 	/* Make sure caller can chgrp. */
 	if ((ia_valid & ATTR_GID) &&
 	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)) &&
 	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
 	    !capable(CAP_CHOWN))
 	    !capable(CAP_CHOWN))
 		goto error;
 		goto error;

+ 2 - 2
fs/autofs/inode.c

@@ -76,8 +76,8 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
 	substring_t args[MAX_OPT_ARGS];
 	substring_t args[MAX_OPT_ARGS];
 	int option;
 	int option;
 
 
-	*uid = current->uid;
-	*gid = current->gid;
+	*uid = current_uid();
+	*gid = current_gid();
 	*pgrp = task_pgrp_nr(current);
 	*pgrp = task_pgrp_nr(current);
 
 
 	*minproto = *maxproto = AUTOFS_PROTO_VERSION;
 	*minproto = *maxproto = AUTOFS_PROTO_VERSION;

+ 2 - 1
fs/autofs4/dev-ioctl.c

@@ -308,7 +308,8 @@ static int autofs_dev_ioctl_open_mountpoint(const char *path, dev_t devid)
 			goto out;
 			goto out;
 		}
 		}
 
 
-		filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY);
+		filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
+				   current_cred());
 		if (IS_ERR(filp)) {
 		if (IS_ERR(filp)) {
 			err = PTR_ERR(filp);
 			err = PTR_ERR(filp);
 			goto out;
 			goto out;

+ 2 - 2
fs/autofs4/inode.c

@@ -235,8 +235,8 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
 	substring_t args[MAX_OPT_ARGS];
 	substring_t args[MAX_OPT_ARGS];
 	int option;
 	int option;
 
 
-	*uid = current->uid;
-	*gid = current->gid;
+	*uid = current_uid();
+	*gid = current_gid();
 	*pgrp = task_pgrp_nr(current);
 	*pgrp = task_pgrp_nr(current);
 
 
 	*minproto = AUTOFS_MIN_PROTO_VERSION;
 	*minproto = AUTOFS_MIN_PROTO_VERSION;

+ 2 - 2
fs/autofs4/waitq.c

@@ -391,8 +391,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 		memcpy(&wq->name, &qstr, sizeof(struct qstr));
 		memcpy(&wq->name, &qstr, sizeof(struct qstr));
 		wq->dev = autofs4_get_dev(sbi);
 		wq->dev = autofs4_get_dev(sbi);
 		wq->ino = autofs4_get_ino(sbi);
 		wq->ino = autofs4_get_ino(sbi);
-		wq->uid = current->uid;
-		wq->gid = current->gid;
+		wq->uid = current_uid();
+		wq->gid = current_gid();
 		wq->pid = current->pid;
 		wq->pid = current->pid;
 		wq->tgid = current->tgid;
 		wq->tgid = current->tgid;
 		wq->status = -EINTR; /* Status return if interrupted */
 		wq->status = -EINTR; /* Status return if interrupted */

+ 2 - 2
fs/bfs/dir.c

@@ -106,8 +106,8 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	}
 	}
 	set_bit(ino, info->si_imap);
 	set_bit(ino, info->si_imap);
 	info->si_freei--;
 	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_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_blocks = 0;
 	inode->i_blocks = 0;
 	inode->i_op = &bfs_file_inops;
 	inode->i_op = &bfs_file_inops;

+ 1 - 1
fs/binfmt_aout.c

@@ -320,7 +320,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 	current->mm->free_area_cache = current->mm->mmap_base;
 	current->mm->free_area_cache = current->mm->mmap_base;
 	current->mm->cached_hole_size = 0;
 	current->mm->cached_hole_size = 0;
 
 
-	compute_creds(bprm);
+	install_exec_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
  	current->flags &= ~PF_FORKNOEXEC;
 #ifdef __sparc__
 #ifdef __sparc__
 	if (N_MAGIC(ex) == NMAGIC) {
 	if (N_MAGIC(ex) == NMAGIC) {

+ 12 - 8
fs/binfmt_elf.c

@@ -157,7 +157,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 	int items;
 	int items;
 	elf_addr_t *elf_info;
 	elf_addr_t *elf_info;
 	int ei_index = 0;
 	int ei_index = 0;
-	struct task_struct *tsk = current;
+	const struct cred *cred = current_cred();
 	struct vm_area_struct *vma;
 	struct vm_area_struct *vma;
 
 
 	/*
 	/*
@@ -223,10 +223,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 	NEW_AUX_ENT(AT_BASE, interp_load_addr);
 	NEW_AUX_ENT(AT_BASE, interp_load_addr);
 	NEW_AUX_ENT(AT_FLAGS, 0);
 	NEW_AUX_ENT(AT_FLAGS, 0);
 	NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
 	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, cred->uid);
+	NEW_AUX_ENT(AT_EUID, cred->euid);
+	NEW_AUX_ENT(AT_GID, cred->gid);
+	NEW_AUX_ENT(AT_EGID, cred->egid);
  	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
  	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
 	NEW_AUX_ENT(AT_EXECFN, bprm->exec);
 	NEW_AUX_ENT(AT_EXECFN, bprm->exec);
 	if (k_platform) {
 	if (k_platform) {
@@ -956,7 +956,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 	}
 	}
 #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
 #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
 
 
-	compute_creds(bprm);
+	install_exec_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
 	current->flags &= ~PF_FORKNOEXEC;
 	retval = create_elf_tables(bprm, &loc->elf_ex,
 	retval = create_elf_tables(bprm, &loc->elf_ex,
 			  load_addr, interp_load_addr);
 			  load_addr, interp_load_addr);
@@ -1361,6 +1361,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
 static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
 static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
 		       struct mm_struct *mm)
 		       struct mm_struct *mm)
 {
 {
+	const struct cred *cred;
 	unsigned int i, len;
 	unsigned int i, len;
 	
 	
 	/* first copy the parameters from user space */
 	/* first copy the parameters from user space */
@@ -1388,8 +1389,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
 	psinfo->pr_zomb = psinfo->pr_sname == 'Z';
 	psinfo->pr_zomb = psinfo->pr_sname == 'Z';
 	psinfo->pr_nice = task_nice(p);
 	psinfo->pr_nice = task_nice(p);
 	psinfo->pr_flag = p->flags;
 	psinfo->pr_flag = p->flags;
-	SET_UID(psinfo->pr_uid, p->uid);
-	SET_GID(psinfo->pr_gid, p->gid);
+	rcu_read_lock();
+	cred = __task_cred(p);
+	SET_UID(psinfo->pr_uid, cred->uid);
+	SET_GID(psinfo->pr_gid, cred->gid);
+	rcu_read_unlock();
 	strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
 	strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
 	
 	
 	return 0;
 	return 0;

+ 12 - 7
fs/binfmt_elf_fdpic.c

@@ -404,7 +404,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
 	current->mm->start_stack = current->mm->start_brk + stack_size;
 	current->mm->start_stack = current->mm->start_brk + stack_size;
 #endif
 #endif
 
 
-	compute_creds(bprm);
+	install_exec_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
 	current->flags &= ~PF_FORKNOEXEC;
 	if (create_elf_fdpic_tables(bprm, current->mm,
 	if (create_elf_fdpic_tables(bprm, current->mm,
 				    &exec_params, &interp_params) < 0)
 				    &exec_params, &interp_params) < 0)
@@ -475,6 +475,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
 				   struct elf_fdpic_params *exec_params,
 				   struct elf_fdpic_params *exec_params,
 				   struct elf_fdpic_params *interp_params)
 				   struct elf_fdpic_params *interp_params)
 {
 {
+	const struct cred *cred = current_cred();
 	unsigned long sp, csp, nitems;
 	unsigned long sp, csp, nitems;
 	elf_caddr_t __user *argv, *envp;
 	elf_caddr_t __user *argv, *envp;
 	size_t platform_len = 0, len;
 	size_t platform_len = 0, len;
@@ -623,10 +624,10 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
 	NEW_AUX_ENT(AT_BASE,	interp_params->elfhdr_addr);
 	NEW_AUX_ENT(AT_BASE,	interp_params->elfhdr_addr);
 	NEW_AUX_ENT(AT_FLAGS,	0);
 	NEW_AUX_ENT(AT_FLAGS,	0);
 	NEW_AUX_ENT(AT_ENTRY,	exec_params->entry_addr);
 	NEW_AUX_ENT(AT_ENTRY,	exec_params->entry_addr);
-	NEW_AUX_ENT(AT_UID,	(elf_addr_t) current->uid);
-	NEW_AUX_ENT(AT_EUID,	(elf_addr_t) current->euid);
-	NEW_AUX_ENT(AT_GID,	(elf_addr_t) current->gid);
-	NEW_AUX_ENT(AT_EGID,	(elf_addr_t) current->egid);
+	NEW_AUX_ENT(AT_UID,	(elf_addr_t) cred->uid);
+	NEW_AUX_ENT(AT_EUID,	(elf_addr_t) cred->euid);
+	NEW_AUX_ENT(AT_GID,	(elf_addr_t) cred->gid);
+	NEW_AUX_ENT(AT_EGID,	(elf_addr_t) cred->egid);
 	NEW_AUX_ENT(AT_SECURE,	security_bprm_secureexec(bprm));
 	NEW_AUX_ENT(AT_SECURE,	security_bprm_secureexec(bprm));
 	NEW_AUX_ENT(AT_EXECFN,	bprm->exec);
 	NEW_AUX_ENT(AT_EXECFN,	bprm->exec);
 
 
@@ -1413,6 +1414,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
 static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
 static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
 		       struct mm_struct *mm)
 		       struct mm_struct *mm)
 {
 {
+	const struct cred *cred;
 	unsigned int i, len;
 	unsigned int i, len;
 
 
 	/* first copy the parameters from user space */
 	/* first copy the parameters from user space */
@@ -1440,8 +1442,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
 	psinfo->pr_zomb = psinfo->pr_sname == 'Z';
 	psinfo->pr_zomb = psinfo->pr_sname == 'Z';
 	psinfo->pr_nice = task_nice(p);
 	psinfo->pr_nice = task_nice(p);
 	psinfo->pr_flag = p->flags;
 	psinfo->pr_flag = p->flags;
-	SET_UID(psinfo->pr_uid, p->uid);
-	SET_GID(psinfo->pr_gid, p->gid);
+	rcu_read_lock();
+	cred = __task_cred(p);
+	SET_UID(psinfo->pr_uid, cred->uid);
+	SET_GID(psinfo->pr_gid, cred->gid);
+	rcu_read_unlock();
 	strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
 	strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
 
 
 	return 0;
 	return 0;

+ 1 - 1
fs/binfmt_flat.c

@@ -880,7 +880,7 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 					(libinfo.lib_list[j].loaded)?
 					(libinfo.lib_list[j].loaded)?
 						libinfo.lib_list[j].start_data:UNLOADED_LIB;
 						libinfo.lib_list[j].start_data:UNLOADED_LIB;
 
 
-	compute_creds(bprm);
+	install_exec_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
  	current->flags &= ~PF_FORKNOEXEC;
 
 
 	set_binfmt(&flat_format);
 	set_binfmt(&flat_format);

+ 1 - 1
fs/binfmt_som.c

@@ -255,7 +255,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 	kfree(hpuxhdr);
 	kfree(hpuxhdr);
 
 
 	set_binfmt(&som_format);
 	set_binfmt(&som_format);
-	compute_creds(bprm);
+	install_exec_creds(bprm);
 	setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 	setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 
 
 	create_som_tables(bprm);
 	create_som_tables(bprm);

+ 1 - 1
fs/cifs/cifs_fs_sb.h

@@ -19,7 +19,7 @@
 #define _CIFS_FS_SB_H
 #define _CIFS_FS_SB_H
 
 
 #define CIFS_MOUNT_NO_PERM      1 /* do not do client vfs_perm check */
 #define CIFS_MOUNT_NO_PERM      1 /* do not do client vfs_perm check */
-#define CIFS_MOUNT_SET_UID      2 /* set current->euid in create etc. */
+#define CIFS_MOUNT_SET_UID      2 /* set current's euid in create etc. */
 #define CIFS_MOUNT_SERVER_INUM  4 /* inode numbers from uniqueid from server */
 #define CIFS_MOUNT_SERVER_INUM  4 /* inode numbers from uniqueid from server */
 #define CIFS_MOUNT_DIRECT_IO    8 /* do not write nor read through page cache */
 #define CIFS_MOUNT_DIRECT_IO    8 /* do not write nor read through page cache */
 #define CIFS_MOUNT_NO_XATTR     0x10  /* if set - disable xattr support       */
 #define CIFS_MOUNT_NO_XATTR     0x10  /* if set - disable xattr support       */

+ 1 - 1
fs/cifs/cifsproto.h

@@ -39,7 +39,7 @@ extern int smb_send(struct socket *, struct smb_hdr *,
 			unsigned int /* length */ , struct sockaddr *, bool);
 			unsigned int /* length */ , struct sockaddr *, bool);
 extern unsigned int _GetXid(void);
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
 extern void _FreeXid(unsigned int);
-#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid));
+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);

+ 2 - 2
fs/cifs/connect.c

@@ -836,8 +836,8 @@ cifs_parse_mount_options(char *options, const char *devname,
 	/* null target name indicates to use *SMBSERVR default called name
 	/* null target name indicates to use *SMBSERVR default called name
 	   if we end up sending RFC1001 session initialize */
 	   if we end up sending RFC1001 session initialize */
 	vol->target_rfc1001_name[0] = 0;
 	vol->target_rfc1001_name[0] = 0;
-	vol->linux_uid = current->uid;	/* current->euid instead? */
-	vol->linux_gid = current->gid;
+	vol->linux_uid = current_uid();  /* use current_euid() instead? */
+	vol->linux_gid = current_gid();
 	vol->dir_mode = S_IRWXUGO;
 	vol->dir_mode = S_IRWXUGO;
 	/* 2767 perms indicate mandatory locking support */
 	/* 2767 perms indicate mandatory locking support */
 	vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
 	vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);

+ 6 - 6
fs/cifs/dir.c

@@ -235,11 +235,11 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 			};
 			};
 
 
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
-				args.uid = (__u64) current->fsuid;
+				args.uid = (__u64) current_fsuid();
 				if (inode->i_mode & S_ISGID)
 				if (inode->i_mode & S_ISGID)
 					args.gid = (__u64) inode->i_gid;
 					args.gid = (__u64) inode->i_gid;
 				else
 				else
-					args.gid = (__u64) current->fsgid;
+					args.gid = (__u64) current_fsgid();
 			} else {
 			} else {
 				args.uid = NO_CHANGE_64;
 				args.uid = NO_CHANGE_64;
 				args.gid = NO_CHANGE_64;
 				args.gid = NO_CHANGE_64;
@@ -271,13 +271,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 				if ((oplock & CIFS_CREATE_ACTION) &&
 				if ((oplock & CIFS_CREATE_ACTION) &&
 				    (cifs_sb->mnt_cifs_flags &
 				    (cifs_sb->mnt_cifs_flags &
 				     CIFS_MOUNT_SET_UID)) {
 				     CIFS_MOUNT_SET_UID)) {
-					newinode->i_uid = current->fsuid;
+					newinode->i_uid = current_fsuid();
 					if (inode->i_mode & S_ISGID)
 					if (inode->i_mode & S_ISGID)
 						newinode->i_gid =
 						newinode->i_gid =
 							inode->i_gid;
 							inode->i_gid;
 					else
 					else
 						newinode->i_gid =
 						newinode->i_gid =
-							current->fsgid;
+							current_fsgid();
 				}
 				}
 			}
 			}
 		}
 		}
@@ -375,8 +375,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
 			.device	= device_number,
 			.device	= device_number,
 		};
 		};
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
-			args.uid = (__u64) current->fsuid;
-			args.gid = (__u64) current->fsgid;
+			args.uid = (__u64) current_fsuid();
+			args.gid = (__u64) current_fsgid();
 		} else {
 		} else {
 			args.uid = NO_CHANGE_64;
 			args.uid = NO_CHANGE_64;
 			args.gid = NO_CHANGE_64;
 			args.gid = NO_CHANGE_64;

+ 4 - 4
fs/cifs/inode.c

@@ -1143,11 +1143,11 @@ mkdir_get_info:
 				.device	= 0,
 				.device	= 0,
 			};
 			};
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
-				args.uid = (__u64)current->fsuid;
+				args.uid = (__u64)current_fsuid();
 				if (inode->i_mode & S_ISGID)
 				if (inode->i_mode & S_ISGID)
 					args.gid = (__u64)inode->i_gid;
 					args.gid = (__u64)inode->i_gid;
 				else
 				else
-					args.gid = (__u64)current->fsgid;
+					args.gid = (__u64)current_fsgid();
 			} else {
 			} else {
 				args.uid = NO_CHANGE_64;
 				args.uid = NO_CHANGE_64;
 				args.gid = NO_CHANGE_64;
 				args.gid = NO_CHANGE_64;
@@ -1184,13 +1184,13 @@ mkdir_get_info:
 				if (cifs_sb->mnt_cifs_flags &
 				if (cifs_sb->mnt_cifs_flags &
 				     CIFS_MOUNT_SET_UID) {
 				     CIFS_MOUNT_SET_UID) {
 					direntry->d_inode->i_uid =
 					direntry->d_inode->i_uid =
-						current->fsuid;
+						current_fsuid();
 					if (inode->i_mode & S_ISGID)
 					if (inode->i_mode & S_ISGID)
 						direntry->d_inode->i_gid =
 						direntry->d_inode->i_gid =
 							inode->i_gid;
 							inode->i_gid;
 					else
 					else
 						direntry->d_inode->i_gid =
 						direntry->d_inode->i_gid =
-							current->fsgid;
+							current_fsgid();
 				}
 				}
 			}
 			}
 		}
 		}

+ 1 - 1
fs/cifs/ioctl.c

@@ -65,7 +65,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
 	switch (command) {
 	switch (command) {
 		case CIFS_IOC_CHECKUMOUNT:
 		case CIFS_IOC_CHECKUMOUNT:
 			cFYI(1, ("User unmount attempted"));
 			cFYI(1, ("User unmount attempted"));
-			if (cifs_sb->mnt_uid == current->uid)
+			if (cifs_sb->mnt_uid == current_uid())
 				rc = 0;
 				rc = 0;
 			else {
 			else {
 				rc = -EACCES;
 				rc = -EACCES;

+ 2 - 2
fs/cifs/misc.c

@@ -338,13 +338,13 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
 		/*  BB Add support for establishing new tCon and SMB Session  */
 		/*  BB Add support for establishing new tCon and SMB Session  */
 		/*      with userid/password pairs found on the smb session   */
 		/*      with userid/password pairs found on the smb session   */
 		/*	for other target tcp/ip addresses 		BB    */
 		/*	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 "
 					cFYI(1, ("Multiuser mode and UID "
 						 "did not match tcon uid"));
 						 "did not match tcon uid"));
 					read_lock(&cifs_tcp_ses_lock);
 					read_lock(&cifs_tcp_ses_lock);
 					list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
 					list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
 						ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
 						ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
-						if (ses->linux_uid == current->fsuid) {
+						if (ses->linux_uid == current_fsuid()) {
 							if (ses->server == treeCon->ses->server) {
 							if (ses->server == treeCon->ses->server) {
 								cFYI(1, ("found matching uid substitute right smb_uid"));
 								cFYI(1, ("found matching uid substitute right smb_uid"));
 								buffer->Uid = ses->Suid;
 								buffer->Uid = ses->Suid;

+ 3 - 3
fs/coda/cache.c

@@ -32,8 +32,8 @@ void coda_cache_enter(struct inode *inode, int mask)
 	struct coda_inode_info *cii = ITOC(inode);
 	struct coda_inode_info *cii = ITOC(inode);
 
 
 	cii->c_cached_epoch = atomic_read(&permission_epoch);
 	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;
                 cii->c_cached_perm = mask;
         } else
         } else
                 cii->c_cached_perm |= mask;
                 cii->c_cached_perm |= mask;
@@ -60,7 +60,7 @@ int coda_cache_check(struct inode *inode, int mask)
         int hit;
         int hit;
 	
 	
         hit = (mask & cii->c_cached_perm) == mask &&
         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);
 		cii->c_cached_epoch == atomic_read(&permission_epoch);
 
 
         return hit;
         return hit;

+ 2 - 1
fs/coda/file.c

@@ -13,6 +13,7 @@
 #include <linux/file.h>
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/stat.h>
+#include <linux/cred.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/smp_lock.h>
 #include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/string.h>
@@ -174,7 +175,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
 
 
 	err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
 	err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
-			  coda_flags, coda_file->f_uid);
+			  coda_flags, coda_file->f_cred->fsuid);
 
 
 	host_inode = cfi->cfi_container->f_path.dentry->d_inode;
 	host_inode = cfi->cfi_container->f_path.dentry->d_inode;
 	cii = ITOC(coda_inode);
 	cii = ITOC(coda_inode);

+ 1 - 1
fs/coda/upcall.c

@@ -52,7 +52,7 @@ static void *alloc_upcall(int opcode, int size)
         inp->ih.opcode = opcode;
         inp->ih.opcode = opcode;
 	inp->ih.pid = current->pid;
 	inp->ih.pid = current->pid;
 	inp->ih.pgid = task_pgrp_nr(current);
 	inp->ih.pgid = task_pgrp_nr(current);
-	inp->ih.uid = current->fsuid;
+	inp->ih.uid = current_fsuid();
 
 
 	return (void*)inp;
 	return (void*)inp;
 }
 }

+ 24 - 18
fs/compat.c

@@ -1393,10 +1393,20 @@ int compat_do_execve(char * filename,
 	if (!bprm)
 	if (!bprm)
 		goto out_ret;
 		goto out_ret;
 
 
+	retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+	if (retval < 0)
+		goto out_free;
+
+	retval = -ENOMEM;
+	bprm->cred = prepare_exec_creds();
+	if (!bprm->cred)
+		goto out_unlock;
+	check_unsafe_exec(bprm);
+
 	file = open_exec(filename);
 	file = open_exec(filename);
 	retval = PTR_ERR(file);
 	retval = PTR_ERR(file);
 	if (IS_ERR(file))
 	if (IS_ERR(file))
-		goto out_kfree;
+		goto out_unlock;
 
 
 	sched_exec();
 	sched_exec();
 
 
@@ -1410,14 +1420,10 @@ int compat_do_execve(char * filename,
 
 
 	bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
 	bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
 	if ((retval = bprm->argc) < 0)
 	if ((retval = bprm->argc) < 0)
-		goto out_mm;
+		goto out;
 
 
 	bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
 	bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
 	if ((retval = bprm->envc) < 0)
 	if ((retval = bprm->envc) < 0)
-		goto out_mm;
-
-	retval = security_bprm_alloc(bprm);
-	if (retval)
 		goto out;
 		goto out;
 
 
 	retval = prepare_binprm(bprm);
 	retval = prepare_binprm(bprm);
@@ -1438,19 +1444,16 @@ int compat_do_execve(char * filename,
 		goto out;
 		goto out;
 
 
 	retval = search_binary_handler(bprm, regs);
 	retval = search_binary_handler(bprm, regs);
-	if (retval >= 0) {
-		/* execve success */
-		security_bprm_free(bprm);
-		acct_update_integrals(current);
-		free_bprm(bprm);
-		return retval;
-	}
+	if (retval < 0)
+		goto out;
 
 
-out:
-	if (bprm->security)
-		security_bprm_free(bprm);
+	/* execve succeeded */
+	mutex_unlock(&current->cred_exec_mutex);
+	acct_update_integrals(current);
+	free_bprm(bprm);
+	return retval;
 
 
-out_mm:
+out:
 	if (bprm->mm)
 	if (bprm->mm)
 		mmput(bprm->mm);
 		mmput(bprm->mm);
 
 
@@ -1460,7 +1463,10 @@ out_file:
 		fput(bprm->file);
 		fput(bprm->file);
 	}
 	}
 
 
-out_kfree:
+out_unlock:
+	mutex_unlock(&current->cred_exec_mutex);
+
+out_free:
 	free_bprm(bprm);
 	free_bprm(bprm);
 
 
 out_ret:
 out_ret:

+ 2 - 2
fs/devpts/inode.c

@@ -222,8 +222,8 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	inode->i_ino = number+2;
 	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;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	inode->i_private = tty;
 	inode->i_private = tty;

+ 2 - 2
fs/dquot.c

@@ -874,7 +874,7 @@ static inline int need_print_warning(struct dquot *dquot)
 
 
 	switch (dquot->dq_type) {
 	switch (dquot->dq_type) {
 		case USRQUOTA:
 		case USRQUOTA:
-			return current->fsuid == dquot->dq_id;
+			return current_fsuid() == dquot->dq_id;
 		case GRPQUOTA:
 		case GRPQUOTA:
 			return in_group_p(dquot->dq_id);
 			return in_group_p(dquot->dq_id);
 	}
 	}
@@ -981,7 +981,7 @@ static void send_warning(const struct dquot *dquot, const char warntype)
 		MINOR(dquot->dq_sb->s_dev));
 		MINOR(dquot->dq_sb->s_dev));
 	if (ret)
 	if (ret)
 		goto attr_err_out;
 		goto attr_err_out;
-	ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current->user->uid);
+	ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid());
 	if (ret)
 	if (ret)
 		goto attr_err_out;
 		goto attr_err_out;
 	genlmsg_end(skb, msg_head);
 	genlmsg_end(skb, msg_head);

+ 2 - 1
fs/ecryptfs/ecryptfs_kernel.h

@@ -691,7 +691,8 @@ int ecryptfs_init_kthread(void);
 void ecryptfs_destroy_kthread(void);
 void ecryptfs_destroy_kthread(void);
 int ecryptfs_privileged_open(struct file **lower_file,
 int ecryptfs_privileged_open(struct file **lower_file,
 			     struct dentry *lower_dentry,
 			     struct dentry *lower_dentry,
-			     struct vfsmount *lower_mnt);
+			     struct vfsmount *lower_mnt,
+			     const struct cred *cred);
 int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
 int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
 
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
 #endif /* #ifndef ECRYPTFS_KERNEL_H */

+ 5 - 4
fs/ecryptfs/kthread.c

@@ -73,7 +73,7 @@ static int ecryptfs_threadfn(void *ignored)
 				mntget(req->lower_mnt);
 				mntget(req->lower_mnt);
 				(*req->lower_file) = dentry_open(
 				(*req->lower_file) = dentry_open(
 					req->lower_dentry, req->lower_mnt,
 					req->lower_dentry, req->lower_mnt,
-					(O_RDWR | O_LARGEFILE));
+					(O_RDWR | O_LARGEFILE), current_cred());
 				req->flags |= ECRYPTFS_REQ_PROCESSED;
 				req->flags |= ECRYPTFS_REQ_PROCESSED;
 			}
 			}
 			wake_up(&req->wait);
 			wake_up(&req->wait);
@@ -132,7 +132,8 @@ void ecryptfs_destroy_kthread(void)
  */
  */
 int ecryptfs_privileged_open(struct file **lower_file,
 int ecryptfs_privileged_open(struct file **lower_file,
 			     struct dentry *lower_dentry,
 			     struct dentry *lower_dentry,
-			     struct vfsmount *lower_mnt)
+			     struct vfsmount *lower_mnt,
+			     const struct cred *cred)
 {
 {
 	struct ecryptfs_open_req *req;
 	struct ecryptfs_open_req *req;
 	int rc = 0;
 	int rc = 0;
@@ -143,7 +144,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
 	dget(lower_dentry);
 	dget(lower_dentry);
 	mntget(lower_mnt);
 	mntget(lower_mnt);
 	(*lower_file) = dentry_open(lower_dentry, lower_mnt,
 	(*lower_file) = dentry_open(lower_dentry, lower_mnt,
-				    (O_RDWR | O_LARGEFILE));
+				    (O_RDWR | O_LARGEFILE), cred);
 	if (!IS_ERR(*lower_file))
 	if (!IS_ERR(*lower_file))
 		goto out;
 		goto out;
 	req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
 	req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
@@ -184,7 +185,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
 		dget(lower_dentry);
 		dget(lower_dentry);
 		mntget(lower_mnt);
 		mntget(lower_mnt);
 		(*lower_file) = dentry_open(lower_dentry, lower_mnt,
 		(*lower_file) = dentry_open(lower_dentry, lower_mnt,
-					    (O_RDONLY | O_LARGEFILE));
+					    (O_RDONLY | O_LARGEFILE), cred);
 		if (IS_ERR(*lower_file)) {
 		if (IS_ERR(*lower_file)) {
 			rc = PTR_ERR(*req->lower_file);
 			rc = PTR_ERR(*req->lower_file);
 			(*lower_file) = NULL;
 			(*lower_file) = NULL;

+ 2 - 1
fs/ecryptfs/main.c

@@ -115,6 +115,7 @@ void __ecryptfs_printk(const char *fmt, ...)
  */
  */
 int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
 int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
 {
 {
+	const struct cred *cred = current_cred();
 	struct ecryptfs_inode_info *inode_info =
 	struct ecryptfs_inode_info *inode_info =
 		ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
 		ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
 	int rc = 0;
 	int rc = 0;
@@ -127,7 +128,7 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
 
 
 		lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
 		lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
 		rc = ecryptfs_privileged_open(&inode_info->lower_file,
 		rc = ecryptfs_privileged_open(&inode_info->lower_file,
-						     lower_dentry, lower_mnt);
+					      lower_dentry, lower_mnt, cred);
 		if (rc || IS_ERR(inode_info->lower_file)) {
 		if (rc || IS_ERR(inode_info->lower_file)) {
 			printk(KERN_ERR "Error opening lower persistent file "
 			printk(KERN_ERR "Error opening lower persistent file "
 			       "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
 			       "for lower_dentry [0x%p] and lower_mnt [0x%p]; "

+ 14 - 13
fs/ecryptfs/messaging.c

@@ -360,7 +360,8 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
 	struct ecryptfs_msg_ctx *msg_ctx;
 	struct ecryptfs_msg_ctx *msg_ctx;
 	size_t msg_size;
 	size_t msg_size;
 	struct nsproxy *nsproxy;
 	struct nsproxy *nsproxy;
-	struct user_namespace *current_user_ns;
+	struct user_namespace *tsk_user_ns;
+	uid_t ctx_euid;
 	int rc;
 	int rc;
 
 
 	if (msg->index >= ecryptfs_message_buf_len) {
 	if (msg->index >= ecryptfs_message_buf_len) {
@@ -384,9 +385,9 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
 		mutex_unlock(&ecryptfs_daemon_hash_mux);
 		mutex_unlock(&ecryptfs_daemon_hash_mux);
 		goto wake_up;
 		goto wake_up;
 	}
 	}
-	current_user_ns = nsproxy->user_ns;
-	rc = ecryptfs_find_daemon_by_euid(&daemon, msg_ctx->task->euid,
-					  current_user_ns);
+	tsk_user_ns = __task_cred(msg_ctx->task)->user->user_ns;
+	ctx_euid = task_euid(msg_ctx->task);
+	rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns);
 	rcu_read_unlock();
 	rcu_read_unlock();
 	mutex_unlock(&ecryptfs_daemon_hash_mux);
 	mutex_unlock(&ecryptfs_daemon_hash_mux);
 	if (rc) {
 	if (rc) {
@@ -394,28 +395,28 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
 		printk(KERN_WARNING "%s: User [%d] received a "
 		printk(KERN_WARNING "%s: User [%d] received a "
 		       "message response from process [0x%p] but does "
 		       "message response from process [0x%p] but does "
 		       "not have a registered daemon\n", __func__,
 		       "not have a registered daemon\n", __func__,
-		       msg_ctx->task->euid, pid);
+		       ctx_euid, pid);
 		goto wake_up;
 		goto wake_up;
 	}
 	}
-	if (msg_ctx->task->euid != euid) {
+	if (ctx_euid != euid) {
 		rc = -EBADMSG;
 		rc = -EBADMSG;
 		printk(KERN_WARNING "%s: Received message from user "
 		printk(KERN_WARNING "%s: Received message from user "
 		       "[%d]; expected message from user [%d]\n", __func__,
 		       "[%d]; expected message from user [%d]\n", __func__,
-		       euid, msg_ctx->task->euid);
+		       euid, ctx_euid);
 		goto unlock;
 		goto unlock;
 	}
 	}
-	if (current_user_ns != user_ns) {
+	if (tsk_user_ns != user_ns) {
 		rc = -EBADMSG;
 		rc = -EBADMSG;
 		printk(KERN_WARNING "%s: Received message from user_ns "
 		printk(KERN_WARNING "%s: Received message from user_ns "
 		       "[0x%p]; expected message from user_ns [0x%p]\n",
 		       "[0x%p]; expected message from user_ns [0x%p]\n",
-		       __func__, user_ns, nsproxy->user_ns);
+		       __func__, user_ns, tsk_user_ns);
 		goto unlock;
 		goto unlock;
 	}
 	}
 	if (daemon->pid != pid) {
 	if (daemon->pid != pid) {
 		rc = -EBADMSG;
 		rc = -EBADMSG;
 		printk(KERN_ERR "%s: User [%d] sent a message response "
 		printk(KERN_ERR "%s: User [%d] sent a message response "
 		       "from an unrecognized process [0x%p]\n",
 		       "from an unrecognized process [0x%p]\n",
-		       __func__, msg_ctx->task->euid, pid);
+		       __func__, ctx_euid, pid);
 		goto unlock;
 		goto unlock;
 	}
 	}
 	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
 	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
@@ -464,14 +465,14 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,
 			     struct ecryptfs_msg_ctx **msg_ctx)
 			     struct ecryptfs_msg_ctx **msg_ctx)
 {
 {
 	struct ecryptfs_daemon *daemon;
 	struct ecryptfs_daemon *daemon;
+	uid_t euid = current_euid();
 	int rc;
 	int rc;
 
 
-	rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
-					  current->nsproxy->user_ns);
+	rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
 	if (rc || !daemon) {
 	if (rc || !daemon) {
 		rc = -ENOTCONN;
 		rc = -ENOTCONN;
 		printk(KERN_ERR "%s: User [%d] does not have a daemon "
 		printk(KERN_ERR "%s: User [%d] does not have a daemon "
-		       "registered\n", __func__, current->euid);
+		       "registered\n", __func__, euid);
 		goto out;
 		goto out;
 	}
 	}
 	mutex_lock(&ecryptfs_msg_ctx_lists_mux);
 	mutex_lock(&ecryptfs_msg_ctx_lists_mux);

+ 13 - 14
fs/ecryptfs/miscdev.c

@@ -42,12 +42,12 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
 {
 {
 	struct ecryptfs_daemon *daemon;
 	struct ecryptfs_daemon *daemon;
 	unsigned int mask = 0;
 	unsigned int mask = 0;
+	uid_t euid = current_euid();
 	int rc;
 	int rc;
 
 
 	mutex_lock(&ecryptfs_daemon_hash_mux);
 	mutex_lock(&ecryptfs_daemon_hash_mux);
 	/* TODO: Just use file->private_data? */
 	/* TODO: Just use file->private_data? */
-	rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
-					  current->nsproxy->user_ns);
+	rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
 	BUG_ON(rc || !daemon);
 	BUG_ON(rc || !daemon);
 	mutex_lock(&daemon->mux);
 	mutex_lock(&daemon->mux);
 	mutex_unlock(&ecryptfs_daemon_hash_mux);
 	mutex_unlock(&ecryptfs_daemon_hash_mux);
@@ -83,6 +83,7 @@ static int
 ecryptfs_miscdev_open(struct inode *inode, struct file *file)
 ecryptfs_miscdev_open(struct inode *inode, struct file *file)
 {
 {
 	struct ecryptfs_daemon *daemon = NULL;
 	struct ecryptfs_daemon *daemon = NULL;
+	uid_t euid = current_euid();
 	int rc;
 	int rc;
 
 
 	mutex_lock(&ecryptfs_daemon_hash_mux);
 	mutex_lock(&ecryptfs_daemon_hash_mux);
@@ -93,11 +94,9 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
 		       "count; rc = [%d]\n", __func__, rc);
 		       "count; rc = [%d]\n", __func__, rc);
 		goto out_unlock_daemon_list;
 		goto out_unlock_daemon_list;
 	}
 	}
-	rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
-					  current->nsproxy->user_ns);
+	rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
 	if (rc || !daemon) {
 	if (rc || !daemon) {
-		rc = ecryptfs_spawn_daemon(&daemon, current->euid,
-					   current->nsproxy->user_ns,
+		rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(),
 					   task_pid(current));
 					   task_pid(current));
 		if (rc) {
 		if (rc) {
 			printk(KERN_ERR "%s: Error attempting to spawn daemon; "
 			printk(KERN_ERR "%s: Error attempting to spawn daemon; "
@@ -147,11 +146,11 @@ static int
 ecryptfs_miscdev_release(struct inode *inode, struct file *file)
 ecryptfs_miscdev_release(struct inode *inode, struct file *file)
 {
 {
 	struct ecryptfs_daemon *daemon = NULL;
 	struct ecryptfs_daemon *daemon = NULL;
+	uid_t euid = current_euid();
 	int rc;
 	int rc;
 
 
 	mutex_lock(&ecryptfs_daemon_hash_mux);
 	mutex_lock(&ecryptfs_daemon_hash_mux);
-	rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
-					  current->nsproxy->user_ns);
+	rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
 	BUG_ON(rc || !daemon);
 	BUG_ON(rc || !daemon);
 	mutex_lock(&daemon->mux);
 	mutex_lock(&daemon->mux);
 	BUG_ON(daemon->pid != task_pid(current));
 	BUG_ON(daemon->pid != task_pid(current));
@@ -246,12 +245,12 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
 	char packet_length[3];
 	char packet_length[3];
 	size_t i;
 	size_t i;
 	size_t total_length;
 	size_t total_length;
+	uid_t euid = current_euid();
 	int rc;
 	int rc;
 
 
 	mutex_lock(&ecryptfs_daemon_hash_mux);
 	mutex_lock(&ecryptfs_daemon_hash_mux);
 	/* TODO: Just use file->private_data? */
 	/* TODO: Just use file->private_data? */
-	rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
-					  current->nsproxy->user_ns);
+	rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
 	BUG_ON(rc || !daemon);
 	BUG_ON(rc || !daemon);
 	mutex_lock(&daemon->mux);
 	mutex_lock(&daemon->mux);
 	if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
 	if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
@@ -290,8 +289,8 @@ check_list:
 		 * message from the queue; try again */
 		 * message from the queue; try again */
 		goto check_list;
 		goto check_list;
 	}
 	}
-	BUG_ON(current->euid != daemon->euid);
-	BUG_ON(current->nsproxy->user_ns != daemon->user_ns);
+	BUG_ON(euid != daemon->euid);
+	BUG_ON(current_user_ns() != daemon->user_ns);
 	BUG_ON(task_pid(current) != daemon->pid);
 	BUG_ON(task_pid(current) != daemon->pid);
 	msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
 	msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
 				   struct ecryptfs_msg_ctx, daemon_out_list);
 				   struct ecryptfs_msg_ctx, daemon_out_list);
@@ -414,6 +413,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
 	size_t packet_size, packet_size_length, i;
 	size_t packet_size, packet_size_length, i;
 	ssize_t sz = 0;
 	ssize_t sz = 0;
 	char *data;
 	char *data;
+	uid_t euid = current_euid();
 	int rc;
 	int rc;
 
 
 	if (count == 0)
 	if (count == 0)
@@ -463,8 +463,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
 			goto out_free;
 			goto out_free;
 		}
 		}
 		rc = ecryptfs_miscdev_response(&data[i], packet_size,
 		rc = ecryptfs_miscdev_response(&data[i], packet_size,
-					       current->euid,
-					       current->nsproxy->user_ns,
+					       euid, current_user_ns(),
 					       task_pid(current), seq);
 					       task_pid(current), seq);
 		if (rc)
 		if (rc)
 			printk(KERN_WARNING "%s: Failed to deliver miscdev "
 			printk(KERN_WARNING "%s: Failed to deliver miscdev "

+ 109 - 74
fs/exec.c

@@ -55,6 +55,7 @@
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 #include <asm/tlb.h>
+#include "internal.h"
 
 
 #ifdef __alpha__
 #ifdef __alpha__
 /* for /sbin/loader handling in search_binary_handler() */
 /* for /sbin/loader handling in search_binary_handler() */
@@ -980,7 +981,7 @@ int flush_old_exec(struct linux_binprm * bprm)
 	/* This is the point of no return */
 	/* This is the point of no return */
 	current->sas_ss_sp = current->sas_ss_size = 0;
 	current->sas_ss_sp = current->sas_ss_size = 0;
 
 
-	if (current->euid == current->uid && current->egid == current->gid)
+	if (current_euid() == current_uid() && current_egid() == current_gid())
 		set_dumpable(current->mm, 1);
 		set_dumpable(current->mm, 1);
 	else
 	else
 		set_dumpable(current->mm, suid_dumpable);
 		set_dumpable(current->mm, suid_dumpable);
@@ -1007,16 +1008,17 @@ int flush_old_exec(struct linux_binprm * bprm)
 	 */
 	 */
 	current->mm->task_size = TASK_SIZE;
 	current->mm->task_size = TASK_SIZE;
 
 
-	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) {
-		suid_keys(current);
-		set_dumpable(current->mm, suid_dumpable);
+	/* install the new credentials */
+	if (bprm->cred->uid != current_euid() ||
+	    bprm->cred->gid != current_egid()) {
 		current->pdeath_signal = 0;
 		current->pdeath_signal = 0;
 	} else if (file_permission(bprm->file, MAY_READ) ||
 	} else if (file_permission(bprm->file, MAY_READ) ||
-			(bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
-		suid_keys(current);
+		   bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) {
 		set_dumpable(current->mm, suid_dumpable);
 		set_dumpable(current->mm, suid_dumpable);
 	}
 	}
 
 
+	current->personality &= ~bprm->per_clear;
+
 	/* An exec changes our domain. We are no longer part of the thread
 	/* An exec changes our domain. We are no longer part of the thread
 	   group */
 	   group */
 
 
@@ -1033,13 +1035,50 @@ out:
 
 
 EXPORT_SYMBOL(flush_old_exec);
 EXPORT_SYMBOL(flush_old_exec);
 
 
+/*
+ * install the new credentials for this executable
+ */
+void install_exec_creds(struct linux_binprm *bprm)
+{
+	security_bprm_committing_creds(bprm);
+
+	commit_creds(bprm->cred);
+	bprm->cred = NULL;
+
+	/* cred_exec_mutex must be held at least to this point to prevent
+	 * ptrace_attach() from altering our determination of the task's
+	 * credentials; any time after this it may be unlocked */
+
+	security_bprm_committed_creds(bprm);
+}
+EXPORT_SYMBOL(install_exec_creds);
+
+/*
+ * determine how safe it is to execute the proposed program
+ * - the caller must hold current->cred_exec_mutex to protect against
+ *   PTRACE_ATTACH
+ */
+void check_unsafe_exec(struct linux_binprm *bprm)
+{
+	struct task_struct *p = current;
+
+	bprm->unsafe = tracehook_unsafe_exec(p);
+
+	if (atomic_read(&p->fs->count) > 1 ||
+	    atomic_read(&p->files->count) > 1 ||
+	    atomic_read(&p->sighand->count) > 1)
+		bprm->unsafe |= LSM_UNSAFE_SHARE;
+}
+
 /* 
 /* 
  * Fill the binprm structure from the inode. 
  * Fill the binprm structure from the inode. 
  * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
  * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
+ *
+ * This may be called multiple times for binary chains (scripts for example).
  */
  */
 int prepare_binprm(struct linux_binprm *bprm)
 int prepare_binprm(struct linux_binprm *bprm)
 {
 {
-	int mode;
+	umode_t mode;
 	struct inode * inode = bprm->file->f_path.dentry->d_inode;
 	struct inode * inode = bprm->file->f_path.dentry->d_inode;
 	int retval;
 	int retval;
 
 
@@ -1047,14 +1086,15 @@ int prepare_binprm(struct linux_binprm *bprm)
 	if (bprm->file->f_op == NULL)
 	if (bprm->file->f_op == NULL)
 		return -EACCES;
 		return -EACCES;
 
 
-	bprm->e_uid = current->euid;
-	bprm->e_gid = current->egid;
+	/* clear any previous set[ug]id data from a previous binary */
+	bprm->cred->euid = current_euid();
+	bprm->cred->egid = current_egid();
 
 
-	if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
+	if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
 		/* Set-uid? */
 		/* Set-uid? */
 		if (mode & S_ISUID) {
 		if (mode & S_ISUID) {
-			current->personality &= ~PER_CLEAR_ON_SETID;
-			bprm->e_uid = inode->i_uid;
+			bprm->per_clear |= PER_CLEAR_ON_SETID;
+			bprm->cred->euid = inode->i_uid;
 		}
 		}
 
 
 		/* Set-gid? */
 		/* Set-gid? */
@@ -1064,52 +1104,23 @@ int prepare_binprm(struct linux_binprm *bprm)
 		 * executable.
 		 * executable.
 		 */
 		 */
 		if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
 		if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
-			current->personality &= ~PER_CLEAR_ON_SETID;
-			bprm->e_gid = inode->i_gid;
+			bprm->per_clear |= PER_CLEAR_ON_SETID;
+			bprm->cred->egid = inode->i_gid;
 		}
 		}
 	}
 	}
 
 
 	/* fill in binprm security blob */
 	/* fill in binprm security blob */
-	retval = security_bprm_set(bprm);
+	retval = security_bprm_set_creds(bprm);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
+	bprm->cred_prepared = 1;
 
 
-	memset(bprm->buf,0,BINPRM_BUF_SIZE);
-	return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
+	memset(bprm->buf, 0, BINPRM_BUF_SIZE);
+	return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
 }
 }
 
 
 EXPORT_SYMBOL(prepare_binprm);
 EXPORT_SYMBOL(prepare_binprm);
 
 
-static int unsafe_exec(struct task_struct *p)
-{
-	int unsafe = tracehook_unsafe_exec(p);
-
-	if (atomic_read(&p->fs->count) > 1 ||
-	    atomic_read(&p->files->count) > 1 ||
-	    atomic_read(&p->sighand->count) > 1)
-		unsafe |= LSM_UNSAFE_SHARE;
-
-	return unsafe;
-}
-
-void compute_creds(struct linux_binprm *bprm)
-{
-	int unsafe;
-
-	if (bprm->e_uid != current->uid) {
-		suid_keys(current);
-		current->pdeath_signal = 0;
-	}
-	exec_keys(current);
-
-	task_lock(current);
-	unsafe = unsafe_exec(current);
-	security_bprm_apply_creds(bprm, unsafe);
-	task_unlock(current);
-	security_bprm_post_apply_creds(bprm);
-}
-EXPORT_SYMBOL(compute_creds);
-
 /*
 /*
  * Arguments are '\0' separated strings found at the location bprm->p
  * Arguments are '\0' separated strings found at the location bprm->p
  * points to; chop off the first by relocating brpm->p to right after
  * points to; chop off the first by relocating brpm->p to right after
@@ -1270,6 +1281,8 @@ EXPORT_SYMBOL(search_binary_handler);
 void free_bprm(struct linux_binprm *bprm)
 void free_bprm(struct linux_binprm *bprm)
 {
 {
 	free_arg_pages(bprm);
 	free_arg_pages(bprm);
+	if (bprm->cred)
+		abort_creds(bprm->cred);
 	kfree(bprm);
 	kfree(bprm);
 }
 }
 
 
@@ -1295,10 +1308,20 @@ int do_execve(char * filename,
 	if (!bprm)
 	if (!bprm)
 		goto out_files;
 		goto out_files;
 
 
+	retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+	if (retval < 0)
+		goto out_free;
+
+	retval = -ENOMEM;
+	bprm->cred = prepare_exec_creds();
+	if (!bprm->cred)
+		goto out_unlock;
+	check_unsafe_exec(bprm);
+
 	file = open_exec(filename);
 	file = open_exec(filename);
 	retval = PTR_ERR(file);
 	retval = PTR_ERR(file);
 	if (IS_ERR(file))
 	if (IS_ERR(file))
-		goto out_kfree;
+		goto out_unlock;
 
 
 	sched_exec();
 	sched_exec();
 
 
@@ -1312,14 +1335,10 @@ int do_execve(char * filename,
 
 
 	bprm->argc = count(argv, MAX_ARG_STRINGS);
 	bprm->argc = count(argv, MAX_ARG_STRINGS);
 	if ((retval = bprm->argc) < 0)
 	if ((retval = bprm->argc) < 0)
-		goto out_mm;
+		goto out;
 
 
 	bprm->envc = count(envp, MAX_ARG_STRINGS);
 	bprm->envc = count(envp, MAX_ARG_STRINGS);
 	if ((retval = bprm->envc) < 0)
 	if ((retval = bprm->envc) < 0)
-		goto out_mm;
-
-	retval = security_bprm_alloc(bprm);
-	if (retval)
 		goto out;
 		goto out;
 
 
 	retval = prepare_binprm(bprm);
 	retval = prepare_binprm(bprm);
@@ -1341,21 +1360,18 @@ int do_execve(char * filename,
 
 
 	current->flags &= ~PF_KTHREAD;
 	current->flags &= ~PF_KTHREAD;
 	retval = search_binary_handler(bprm,regs);
 	retval = search_binary_handler(bprm,regs);
-	if (retval >= 0) {
-		/* execve success */
-		security_bprm_free(bprm);
-		acct_update_integrals(current);
-		free_bprm(bprm);
-		if (displaced)
-			put_files_struct(displaced);
-		return retval;
-	}
+	if (retval < 0)
+		goto out;
 
 
-out:
-	if (bprm->security)
-		security_bprm_free(bprm);
+	/* execve succeeded */
+	mutex_unlock(&current->cred_exec_mutex);
+	acct_update_integrals(current);
+	free_bprm(bprm);
+	if (displaced)
+		put_files_struct(displaced);
+	return retval;
 
 
-out_mm:
+out:
 	if (bprm->mm)
 	if (bprm->mm)
 		mmput (bprm->mm);
 		mmput (bprm->mm);
 
 
@@ -1364,7 +1380,11 @@ out_file:
 		allow_write_access(bprm->file);
 		allow_write_access(bprm->file);
 		fput(bprm->file);
 		fput(bprm->file);
 	}
 	}
-out_kfree:
+
+out_unlock:
+	mutex_unlock(&current->cred_exec_mutex);
+
+out_free:
 	free_bprm(bprm);
 	free_bprm(bprm);
 
 
 out_files:
 out_files:
@@ -1396,6 +1416,7 @@ EXPORT_SYMBOL(set_binfmt);
  */
  */
 static int format_corename(char *corename, long signr)
 static int format_corename(char *corename, long signr)
 {
 {
+	const struct cred *cred = current_cred();
 	const char *pat_ptr = core_pattern;
 	const char *pat_ptr = core_pattern;
 	int ispipe = (*pat_ptr == '|');
 	int ispipe = (*pat_ptr == '|');
 	char *out_ptr = corename;
 	char *out_ptr = corename;
@@ -1432,7 +1453,7 @@ static int format_corename(char *corename, long signr)
 			/* uid */
 			/* uid */
 			case 'u':
 			case 'u':
 				rc = snprintf(out_ptr, out_end - out_ptr,
 				rc = snprintf(out_ptr, out_end - out_ptr,
-					      "%d", current->uid);
+					      "%d", cred->uid);
 				if (rc > out_end - out_ptr)
 				if (rc > out_end - out_ptr)
 					goto out;
 					goto out;
 				out_ptr += rc;
 				out_ptr += rc;
@@ -1440,7 +1461,7 @@ static int format_corename(char *corename, long signr)
 			/* gid */
 			/* gid */
 			case 'g':
 			case 'g':
 				rc = snprintf(out_ptr, out_end - out_ptr,
 				rc = snprintf(out_ptr, out_end - out_ptr,
-					      "%d", current->gid);
+					      "%d", cred->gid);
 				if (rc > out_end - out_ptr)
 				if (rc > out_end - out_ptr)
 					goto out;
 					goto out;
 				out_ptr += rc;
 				out_ptr += rc;
@@ -1716,8 +1737,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	struct linux_binfmt * binfmt;
 	struct linux_binfmt * binfmt;
 	struct inode * inode;
 	struct inode * inode;
 	struct file * file;
 	struct file * file;
+	const struct cred *old_cred;
+	struct cred *cred;
 	int retval = 0;
 	int retval = 0;
-	int fsuid = current->fsuid;
 	int flag = 0;
 	int flag = 0;
 	int ispipe = 0;
 	int ispipe = 0;
 	unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
 	unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
@@ -1730,12 +1752,20 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	binfmt = current->binfmt;
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
 	if (!binfmt || !binfmt->core_dump)
 		goto fail;
 		goto fail;
+
+	cred = prepare_creds();
+	if (!cred) {
+		retval = -ENOMEM;
+		goto fail;
+	}
+
 	down_write(&mm->mmap_sem);
 	down_write(&mm->mmap_sem);
 	/*
 	/*
 	 * If another thread got here first, or we are not dumpable, bail out.
 	 * If another thread got here first, or we are not dumpable, bail out.
 	 */
 	 */
 	if (mm->core_state || !get_dumpable(mm)) {
 	if (mm->core_state || !get_dumpable(mm)) {
 		up_write(&mm->mmap_sem);
 		up_write(&mm->mmap_sem);
+		put_cred(cred);
 		goto fail;
 		goto fail;
 	}
 	}
 
 
@@ -1746,12 +1776,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	 */
 	 */
 	if (get_dumpable(mm) == 2) {	/* Setuid core dump mode */
 	if (get_dumpable(mm) == 2) {	/* Setuid core dump mode */
 		flag = O_EXCL;		/* Stop rewrite attacks */
 		flag = O_EXCL;		/* Stop rewrite attacks */
-		current->fsuid = 0;	/* Dump root private */
+		cred->fsuid = 0;	/* Dump root private */
 	}
 	}
 
 
 	retval = coredump_wait(exit_code, &core_state);
 	retval = coredump_wait(exit_code, &core_state);
-	if (retval < 0)
+	if (retval < 0) {
+		put_cred(cred);
 		goto fail;
 		goto fail;
+	}
+
+	old_cred = override_creds(cred);
 
 
 	/*
 	/*
 	 * Clear any false indication of pending signals that might
 	 * Clear any false indication of pending signals that might
@@ -1823,7 +1857,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	 * Dont allow local users get cute and trick others to coredump
 	 * Dont allow local users get cute and trick others to coredump
 	 * into their pre-created files:
 	 * into their pre-created files:
 	 */
 	 */
-	if (inode->i_uid != current->fsuid)
+	if (inode->i_uid != current_fsuid())
 		goto close_fail;
 		goto close_fail;
 	if (!file->f_op)
 	if (!file->f_op)
 		goto close_fail;
 		goto close_fail;
@@ -1842,7 +1876,8 @@ fail_unlock:
 	if (helper_argv)
 	if (helper_argv)
 		argv_free(helper_argv);
 		argv_free(helper_argv);
 
 
-	current->fsuid = fsuid;
+	revert_creds(old_cred);
+	put_cred(cred);
 	coredump_finish(mm);
 	coredump_finish(mm);
 fail:
 fail:
 	return retval;
 	return retval;

+ 3 - 1
fs/exportfs/expfs.c

@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/namei.h>
+#include <linux/sched.h>
 
 
 #define dprintk(fmt, args...) do{}while(0)
 #define dprintk(fmt, args...) do{}while(0)
 
 
@@ -249,6 +250,7 @@ static int filldir_one(void * __buf, const char * name, int len,
 static int get_name(struct vfsmount *mnt, struct dentry *dentry,
 static int get_name(struct vfsmount *mnt, struct dentry *dentry,
 		char *name, struct dentry *child)
 		char *name, struct dentry *child)
 {
 {
+	const struct cred *cred = current_cred();
 	struct inode *dir = dentry->d_inode;
 	struct inode *dir = dentry->d_inode;
 	int error;
 	int error;
 	struct file *file;
 	struct file *file;
@@ -263,7 +265,7 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry,
 	/*
 	/*
 	 * Open the directory ...
 	 * Open the directory ...
 	 */
 	 */
-	file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY);
+	file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, cred);
 	error = PTR_ERR(file);
 	error = PTR_ERR(file);
 	if (IS_ERR(file))
 	if (IS_ERR(file))
 		goto out;
 		goto out;

+ 1 - 1
fs/ext2/balloc.c

@@ -1193,7 +1193,7 @@ static int ext2_has_free_blocks(struct ext2_sb_info *sbi)
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
 	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))) {
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		return 0;
 		return 0;
 	}
 	}

+ 2 - 2
fs/ext2/ialloc.c

@@ -550,7 +550,7 @@ got:
 
 
 	sb->s_dirt = 1;
 	sb->s_dirt = 1;
 	mark_buffer_dirty(bh2);
 	mark_buffer_dirty(bh2);
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (test_opt (sb, GRPID))
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
 	else if (dir->i_mode & S_ISGID) {
@@ -558,7 +558,7 @@ got:
 		if (S_ISDIR(mode))
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 			mode |= S_ISGID;
 	} else
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 	inode->i_mode = mode;
 	inode->i_mode = mode;
 
 
 	inode->i_ino = ino;
 	inode->i_ino = ino;

+ 1 - 1
fs/ext3/balloc.c

@@ -1422,7 +1422,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
 	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))) {
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		return 0;
 		return 0;
 	}
 	}

+ 2 - 2
fs/ext3/ialloc.c

@@ -539,7 +539,7 @@ got:
 		percpu_counter_inc(&sbi->s_dirs_counter);
 		percpu_counter_inc(&sbi->s_dirs_counter);
 	sb->s_dirt = 1;
 	sb->s_dirt = 1;
 
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (test_opt (sb, GRPID))
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
 	else if (dir->i_mode & S_ISGID) {
@@ -547,7 +547,7 @@ got:
 		if (S_ISDIR(mode))
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 			mode |= S_ISGID;
 	} else
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 	inode->i_mode = mode;
 	inode->i_mode = mode;
 
 
 	inode->i_ino = ino;
 	inode->i_ino = ino;

+ 1 - 1
fs/ext4/balloc.c

@@ -624,7 +624,7 @@ int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
 		return 1;
 		return 1;
 
 
 	/* Hm, nope.  Are (enough) root reserved blocks available? */
 	/* Hm, nope.  Are (enough) root reserved blocks available? */
-	if (sbi->s_resuid == current->fsuid ||
+	if (sbi->s_resuid == current_fsuid() ||
 	    ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) ||
 	    ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) ||
 	    capable(CAP_SYS_RESOURCE)) {
 	    capable(CAP_SYS_RESOURCE)) {
 		if (free_blocks >= (nblocks + dirty_blocks))
 		if (free_blocks >= (nblocks + dirty_blocks))

+ 2 - 2
fs/ext4/ialloc.c

@@ -787,7 +787,7 @@ got:
 		spin_unlock(sb_bgl_lock(sbi, flex_group));
 		spin_unlock(sb_bgl_lock(sbi, flex_group));
 	}
 	}
 
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (test_opt(sb, GRPID))
 	if (test_opt(sb, GRPID))
 		inode->i_gid = dir->i_gid;
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
 	else if (dir->i_mode & S_ISGID) {
@@ -795,7 +795,7 @@ got:
 		if (S_ISDIR(mode))
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 			mode |= S_ISGID;
 	} else
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 	inode->i_mode = mode;
 	inode->i_mode = mode;
 
 
 	inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
 	inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);

+ 1 - 1
fs/fat/file.c

@@ -304,7 +304,7 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
 {
 {
 	mode_t allow_utime = sbi->options.allow_utime;
 	mode_t allow_utime = sbi->options.allow_utime;
 
 
-	if (current->fsuid != inode->i_uid) {
+	if (current_fsuid() != inode->i_uid) {
 		if (in_group_p(inode->i_gid))
 		if (in_group_p(inode->i_gid))
 			allow_utime >>= 3;
 			allow_utime >>= 3;
 		if (allow_utime & MAY_WRITE)
 		if (allow_utime & MAY_WRITE)

+ 2 - 2
fs/fat/inode.c

@@ -926,8 +926,8 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
 
 
 	opts->isvfat = is_vfat;
 	opts->isvfat = is_vfat;
 
 
-	opts->fs_uid = current->uid;
-	opts->fs_gid = current->gid;
+	opts->fs_uid = current_uid();
+	opts->fs_gid = current_gid();
 	opts->fs_fmask = opts->fs_dmask = current->fs->umask;
 	opts->fs_fmask = opts->fs_dmask = current->fs->umask;
 	opts->allow_utime = -1;
 	opts->allow_utime = -1;
 	opts->codepage = fat_default_codepage;
 	opts->codepage = fat_default_codepage;

+ 13 - 5
fs/fcntl.c

@@ -212,13 +212,14 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
 int __f_setown(struct file *filp, struct pid *pid, enum pid_type type,
 int __f_setown(struct file *filp, struct pid *pid, enum pid_type type,
 		int force)
 		int force)
 {
 {
+	const struct cred *cred = current_cred();
 	int err;
 	int err;
 	
 	
 	err = security_file_set_fowner(filp);
 	err = security_file_set_fowner(filp);
 	if (err)
 	if (err)
 		return err;
 		return err;
 
 
-	f_modown(filp, pid, type, current->uid, current->euid, force);
+	f_modown(filp, pid, type, cred->uid, cred->euid, force);
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL(__f_setown);
 EXPORT_SYMBOL(__f_setown);
@@ -407,10 +408,17 @@ static const long band_table[NSIGPOLL] = {
 static inline int sigio_perm(struct task_struct *p,
 static inline int sigio_perm(struct task_struct *p,
                              struct fown_struct *fown, int sig)
                              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)) &&
-		!security_file_send_sigiotask(p, fown, sig));
+	const struct cred *cred;
+	int ret;
+
+	rcu_read_lock();
+	cred = __task_cred(p);
+	ret = ((fown->euid == 0 ||
+		fown->euid == cred->suid || fown->euid == cred->uid ||
+		fown->uid  == cred->suid || fown->uid  == cred->uid) &&
+	       !security_file_send_sigiotask(p, fown, sig));
+	rcu_read_unlock();
+	return ret;
 }
 }
 
 
 static void send_sigio_to_task(struct task_struct *p,
 static void send_sigio_to_task(struct task_struct *p,

+ 5 - 5
fs/file_table.c

@@ -36,7 +36,9 @@ static struct percpu_counter nr_files __cacheline_aligned_in_smp;
 
 
 static inline void file_free_rcu(struct rcu_head *head)
 static inline void file_free_rcu(struct rcu_head *head)
 {
 {
-	struct file *f =  container_of(head, struct file, f_u.fu_rcuhead);
+	struct file *f = container_of(head, struct file, f_u.fu_rcuhead);
+
+	put_cred(f->f_cred);
 	kmem_cache_free(filp_cachep, f);
 	kmem_cache_free(filp_cachep, f);
 }
 }
 
 
@@ -94,7 +96,7 @@ int proc_nr_files(ctl_table *table, int write, struct file *filp,
  */
  */
 struct file *get_empty_filp(void)
 struct file *get_empty_filp(void)
 {
 {
-	struct task_struct *tsk;
+	const struct cred *cred = current_cred();
 	static int old_max;
 	static int old_max;
 	struct file * f;
 	struct file * f;
 
 
@@ -118,12 +120,10 @@ struct file *get_empty_filp(void)
 	if (security_file_alloc(f))
 	if (security_file_alloc(f))
 		goto fail_sec;
 		goto fail_sec;
 
 
-	tsk = current;
 	INIT_LIST_HEAD(&f->f_u.fu_list);
 	INIT_LIST_HEAD(&f->f_u.fu_list);
 	atomic_long_set(&f->f_count, 1);
 	atomic_long_set(&f->f_count, 1);
 	rwlock_init(&f->f_owner.lock);
 	rwlock_init(&f->f_owner.lock);
-	f->f_uid = tsk->fsuid;
-	f->f_gid = tsk->fsgid;
+	f->f_cred = get_cred(cred);
 	eventpoll_init_file(f);
 	eventpoll_init_file(f);
 	/* f->f_version: 0 */
 	/* f->f_version: 0 */
 	return f;
 	return f;

+ 2 - 2
fs/fuse/dev.c

@@ -87,8 +87,8 @@ static void __fuse_put_request(struct fuse_req *req)
 
 
 static void fuse_req_init_context(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;
 	req->in.h.pid = current->pid;
 }
 }
 
 

+ 15 - 8
fs/fuse/dir.c

@@ -869,18 +869,25 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
  */
  */
 int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
 int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
 {
 {
+	const struct cred *cred;
+	int ret;
+
 	if (fc->flags & FUSE_ALLOW_OTHER)
 	if (fc->flags & FUSE_ALLOW_OTHER)
 		return 1;
 		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)
-		return 1;
+	rcu_read_lock();
+	ret = 0;
+	cred = __task_cred(task);
+	if (cred->euid == fc->user_id &&
+	    cred->suid == fc->user_id &&
+	    cred->uid  == fc->user_id &&
+	    cred->egid == fc->group_id &&
+	    cred->sgid == fc->group_id &&
+	    cred->gid  == fc->group_id)
+		ret = 1;
+	rcu_read_unlock();
 
 
-	return 0;
+	return ret;
 }
 }
 
 
 static int fuse_access(struct inode *inode, int mask)
 static int fuse_access(struct inode *inode, int mask)

+ 5 - 5
fs/gfs2/inode.c

@@ -705,18 +705,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) {
 	    (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
 		if (S_ISDIR(*mode))
 		if (S_ISDIR(*mode))
 			*mode |= S_ISUID;
 			*mode |= S_ISUID;
-		else if (dip->i_inode.i_uid != current->fsuid)
+		else if (dip->i_inode.i_uid != current_fsuid())
 			*mode &= ~07111;
 			*mode &= ~07111;
 		*uid = dip->i_inode.i_uid;
 		*uid = dip->i_inode.i_uid;
 	} else
 	} else
-		*uid = current->fsuid;
+		*uid = current_fsuid();
 
 
 	if (dip->i_inode.i_mode & S_ISGID) {
 	if (dip->i_inode.i_mode & S_ISGID) {
 		if (S_ISDIR(*mode))
 		if (S_ISDIR(*mode))
 			*mode |= S_ISGID;
 			*mode |= S_ISGID;
 		*gid = dip->i_inode.i_gid;
 		*gid = dip->i_inode.i_gid;
 	} else
 	} else
-		*gid = current->fsgid;
+		*gid = current_fsgid();
 }
 }
 
 
 static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
 static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
@@ -1124,8 +1124,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
 		return -EPERM;
 		return -EPERM;
 
 
 	if ((dip->i_inode.i_mode & S_ISVTX) &&
 	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;
 		return -EPERM;
 
 
 	if (IS_APPEND(&dip->i_inode))
 	if (IS_APPEND(&dip->i_inode))

+ 2 - 2
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);
 	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_ino = HFS_SB(sb)->next_id++;
 	inode->i_mode = mode;
 	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_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	HFS_I(inode)->flags = 0;
 	HFS_I(inode)->flags = 0;

+ 2 - 2
fs/hfs/super.c

@@ -210,8 +210,8 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
 	int tmp, token;
 	int tmp, token;
 
 
 	/* initialize the sb with defaults */
 	/* initialize the sb with defaults */
-	hsb->s_uid = current->uid;
-	hsb->s_gid = current->gid;
+	hsb->s_uid = current_uid();
+	hsb->s_gid = current_gid();
 	hsb->s_file_umask = 0133;
 	hsb->s_file_umask = 0133;
 	hsb->s_dir_umask = 0022;
 	hsb->s_dir_umask = 0022;
 	hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f);	/* == '????' */
 	hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f);	/* == '????' */

+ 2 - 2
fs/hfsplus/inode.c

@@ -296,8 +296,8 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
 
 
 	inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
 	inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
 	inode->i_mode = mode;
 	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_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
 	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);

+ 2 - 2
fs/hfsplus/options.c

@@ -49,8 +49,8 @@ void hfsplus_fill_defaults(struct hfsplus_sb_info *opts)
 	opts->creator = HFSPLUS_DEF_CR_TYPE;
 	opts->creator = HFSPLUS_DEF_CR_TYPE;
 	opts->type = HFSPLUS_DEF_CR_TYPE;
 	opts->type = HFSPLUS_DEF_CR_TYPE;
 	opts->umask = current->fs->umask;
 	opts->umask = current->fs->umask;
-	opts->uid = current->uid;
-	opts->gid = current->gid;
+	opts->uid = current_uid();
+	opts->gid = current_gid();
 	opts->part = -1;
 	opts->part = -1;
 	opts->session = -1;
 	opts->session = -1;
 }
 }

+ 12 - 12
fs/hpfs/namei.c

@@ -92,11 +92,11 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	inc_nlink(dir);
 	inc_nlink(dir);
 	insert_inode_hash(result);
 	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_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;
 		result->i_mode = mode | S_IFDIR;
 		hpfs_write_inode_nolock(result);
 		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);
 	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_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;
 		result->i_mode = mode | S_IFREG;
 		hpfs_write_inode_nolock(result);
 		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_mtime.tv_nsec = 0;
 	result->i_atime.tv_nsec = 0;
 	result->i_atime.tv_nsec = 0;
 	hpfs_i(result)->i_ea_size = 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_nlink = 1;
 	result->i_size = 0;
 	result->i_size = 0;
 	result->i_blocks = 1;
 	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;
 	result->i_atime.tv_nsec = 0;
 	hpfs_i(result)->i_ea_size = 0;
 	hpfs_i(result)->i_ea_size = 0;
 	result->i_mode = S_IFLNK | 0777;
 	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_blocks = 1;
 	result->i_nlink = 1;
 	result->i_nlink = 1;
 	result->i_size = strlen(symlink);
 	result->i_size = strlen(symlink);

+ 2 - 2
fs/hpfs/super.c

@@ -475,8 +475,8 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
 
 	init_MUTEX(&sbi->hpfs_creation_de);
 	init_MUTEX(&sbi->hpfs_creation_de);
 
 
-	uid = current->uid;
-	gid = current->gid;
+	uid = current_uid();
+	gid = current_gid();
 	umask = current->fs->umask;
 	umask = current->fs->umask;
 	lowercase = 0;
 	lowercase = 0;
 	conv = CONV_BINARY;
 	conv = CONV_BINARY;

+ 4 - 2
fs/hppfs/hppfs.c

@@ -426,6 +426,7 @@ static int file_mode(int fmode)
 
 
 static int hppfs_open(struct inode *inode, struct file *file)
 static int hppfs_open(struct inode *inode, struct file *file)
 {
 {
+	const struct cred *cred = file->f_cred;
 	struct hppfs_private *data;
 	struct hppfs_private *data;
 	struct vfsmount *proc_mnt;
 	struct vfsmount *proc_mnt;
 	struct dentry *proc_dentry;
 	struct dentry *proc_dentry;
@@ -446,7 +447,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
 
 
 	/* XXX This isn't closed anywhere */
 	/* XXX This isn't closed anywhere */
 	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
 	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
-				      file_mode(file->f_mode));
+				      file_mode(file->f_mode), cred);
 	err = PTR_ERR(data->proc_file);
 	err = PTR_ERR(data->proc_file);
 	if (IS_ERR(data->proc_file))
 	if (IS_ERR(data->proc_file))
 		goto out_free1;
 		goto out_free1;
@@ -489,6 +490,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
 
 
 static int hppfs_dir_open(struct inode *inode, struct file *file)
 static int hppfs_dir_open(struct inode *inode, struct file *file)
 {
 {
+	const struct cred *cred = file->f_cred;
 	struct hppfs_private *data;
 	struct hppfs_private *data;
 	struct vfsmount *proc_mnt;
 	struct vfsmount *proc_mnt;
 	struct dentry *proc_dentry;
 	struct dentry *proc_dentry;
@@ -502,7 +504,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
 	proc_dentry = HPPFS_I(inode)->proc_dentry;
 	proc_dentry = HPPFS_I(inode)->proc_dentry;
 	proc_mnt = inode->i_sb->s_fs_info;
 	proc_mnt = inode->i_sb->s_fs_info;
 	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
 	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
-				      file_mode(file->f_mode));
+				      file_mode(file->f_mode), cred);
 	err = PTR_ERR(data->proc_file);
 	err = PTR_ERR(data->proc_file);
 	if (IS_ERR(data->proc_file))
 	if (IS_ERR(data->proc_file))
 		goto out_free;
 		goto out_free;

+ 11 - 10
fs/hugetlbfs/inode.c

@@ -551,9 +551,9 @@ static int hugetlbfs_mknod(struct inode *dir,
 		if (S_ISDIR(mode))
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 			mode |= S_ISGID;
 	} else {
 	} 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) {
 	if (inode) {
 		dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 		dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 		d_instantiate(dentry, inode);
 		d_instantiate(dentry, inode);
@@ -586,9 +586,9 @@ static int hugetlbfs_symlink(struct inode *dir,
 	if (dir->i_mode & S_ISGID)
 	if (dir->i_mode & S_ISGID)
 		gid = dir->i_gid;
 		gid = dir->i_gid;
 	else
 	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);
 					gid, S_IFLNK|S_IRWXUGO, 0);
 	if (inode) {
 	if (inode) {
 		int l = strlen(symname)+1;
 		int l = strlen(symname)+1;
@@ -854,8 +854,8 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
 
 
 	config.nr_blocks = -1; /* No limit on size by default */
 	config.nr_blocks = -1; /* No limit on size by default */
 	config.nr_inodes = -1; /* No limit on number of inodes 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;
 	config.mode = 0755;
 	config.hstate = &default_hstate;
 	config.hstate = &default_hstate;
 	ret = hugetlbfs_parse_options(data, &config);
 	ret = hugetlbfs_parse_options(data, &config);
@@ -951,6 +951,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
 	struct inode *inode;
 	struct inode *inode;
 	struct dentry *dentry, *root;
 	struct dentry *dentry, *root;
 	struct qstr quick_string;
 	struct qstr quick_string;
+	struct user_struct *user = current_user();
 
 
 	if (!hugetlbfs_vfsmount)
 	if (!hugetlbfs_vfsmount)
 		return ERR_PTR(-ENOENT);
 		return ERR_PTR(-ENOENT);
@@ -958,7 +959,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
 	if (!can_do_hugetlb_shm())
 	if (!can_do_hugetlb_shm())
 		return ERR_PTR(-EPERM);
 		return ERR_PTR(-EPERM);
 
 
-	if (!user_shm_lock(size, current->user))
+	if (!user_shm_lock(size, user))
 		return ERR_PTR(-ENOMEM);
 		return ERR_PTR(-ENOMEM);
 
 
 	root = hugetlbfs_vfsmount->mnt_root;
 	root = hugetlbfs_vfsmount->mnt_root;
@@ -970,8 +971,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
 		goto out_shm_unlock;
 		goto out_shm_unlock;
 
 
 	error = -ENOSPC;
 	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)
 	if (!inode)
 		goto out_dentry;
 		goto out_dentry;
 
 
@@ -998,7 +999,7 @@ out_inode:
 out_dentry:
 out_dentry:
 	dput(dentry);
 	dput(dentry);
 out_shm_unlock:
 out_shm_unlock:
-	user_shm_unlock(size, current->user);
+	user_shm_unlock(size, user);
 	return ERR_PTR(error);
 	return ERR_PTR(error);
 }
 }
 
 

+ 1 - 1
fs/inotify_user.c

@@ -601,7 +601,7 @@ asmlinkage long sys_inotify_init1(int flags)
 		goto out_put_fd;
 		goto out_put_fd;
 	}
 	}
 
 
-	user = get_uid(current->user);
+	user = get_current_user();
 	if (unlikely(atomic_read(&user->inotify_devs) >=
 	if (unlikely(atomic_read(&user->inotify_devs) >=
 			inotify_max_user_instances)) {
 			inotify_max_user_instances)) {
 		ret = -EMFILE;
 		ret = -EMFILE;

+ 6 - 0
fs/internal.h

@@ -10,6 +10,7 @@
  */
  */
 
 
 struct super_block;
 struct super_block;
+struct linux_binprm;
 
 
 /*
 /*
  * block_dev.c
  * block_dev.c
@@ -39,6 +40,11 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
  */
  */
 extern void __init chrdev_init(void);
 extern void __init chrdev_init(void);
 
 
+/*
+ * exec.c
+ */
+extern void check_unsafe_exec(struct linux_binprm *);
+
 /*
 /*
  * namespace.c
  * namespace.c
  */
  */

+ 12 - 6
fs/ioprio.c

@@ -31,10 +31,16 @@ static int set_task_ioprio(struct task_struct *task, int ioprio)
 {
 {
 	int err;
 	int err;
 	struct io_context *ioc;
 	struct io_context *ioc;
+	const struct cred *cred = current_cred(), *tcred;
 
 
-	if (task->uid != current->euid &&
-	    task->uid != current->uid && !capable(CAP_SYS_NICE))
+	rcu_read_lock();
+	tcred = __task_cred(task);
+	if (tcred->uid != cred->euid &&
+	    tcred->uid != cred->uid && !capable(CAP_SYS_NICE)) {
+		rcu_read_unlock();
 		return -EPERM;
 		return -EPERM;
+	}
+	rcu_read_unlock();
 
 
 	err = security_task_setioprio(task, ioprio);
 	err = security_task_setioprio(task, ioprio);
 	if (err)
 	if (err)
@@ -123,7 +129,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
 			break;
 			break;
 		case IOPRIO_WHO_USER:
 		case IOPRIO_WHO_USER:
 			if (!who)
 			if (!who)
-				user = current->user;
+				user = current_user();
 			else
 			else
 				user = find_user(who);
 				user = find_user(who);
 
 
@@ -131,7 +137,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
 				break;
 				break;
 
 
 			do_each_thread(g, p) {
 			do_each_thread(g, p) {
-				if (p->uid != who)
+				if (__task_cred(p)->uid != who)
 					continue;
 					continue;
 				ret = set_task_ioprio(p, ioprio);
 				ret = set_task_ioprio(p, ioprio);
 				if (ret)
 				if (ret)
@@ -216,7 +222,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
 			break;
 			break;
 		case IOPRIO_WHO_USER:
 		case IOPRIO_WHO_USER:
 			if (!who)
 			if (!who)
-				user = current->user;
+				user = current_user();
 			else
 			else
 				user = find_user(who);
 				user = find_user(who);
 
 
@@ -224,7 +230,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
 				break;
 				break;
 
 
 			do_each_thread(g, p) {
 			do_each_thread(g, p) {
-				if (p->uid != user->uid)
+				if (__task_cred(p)->uid != user->uid)
 					continue;
 					continue;
 				tmpio = get_task_ioprio(p);
 				tmpio = get_task_ioprio(p);
 				if (tmpio < 0)
 				if (tmpio < 0)

+ 2 - 2
fs/jfs/jfs_inode.c

@@ -93,13 +93,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
 		return ERR_PTR(rc);
 		return ERR_PTR(rc);
 	}
 	}
 
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current_fsuid();
 	if (parent->i_mode & S_ISGID) {
 	if (parent->i_mode & S_ISGID) {
 		inode->i_gid = parent->i_gid;
 		inode->i_gid = parent->i_gid;
 		if (S_ISDIR(mode))
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 			mode |= S_ISGID;
 	} else
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current_fsgid();
 
 
 	/*
 	/*
 	 * New inodes need to save sane values on disk when
 	 * New inodes need to save sane values on disk when

+ 1 - 1
fs/locks.c

@@ -1349,7 +1349,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 	struct inode *inode = dentry->d_inode;
 	struct inode *inode = dentry->d_inode;
 	int error, rdlease_count = 0, wrlease_count = 0;
 	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;
 		return -EACCES;
 	if (!S_ISREG(inode->i_mode))
 	if (!S_ISREG(inode->i_mode))
 		return -EINVAL;
 		return -EINVAL;

+ 2 - 2
fs/minix/bitmap.c

@@ -262,8 +262,8 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
 		iput(inode);
 		iput(inode);
 		return NULL;
 		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_ino = j;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_blocks = 0;
 	inode->i_blocks = 0;

+ 6 - 4
fs/namei.c

@@ -186,7 +186,7 @@ int generic_permission(struct inode *inode, int mask,
 
 
 	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
 	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
 
 
-	if (current->fsuid == inode->i_uid)
+	if (current_fsuid() == inode->i_uid)
 		mode >>= 6;
 		mode >>= 6;
 	else {
 	else {
 		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
 		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
@@ -441,7 +441,7 @@ static int exec_permission_lite(struct inode *inode)
 	if (inode->i_op && inode->i_op->permission)
 	if (inode->i_op && inode->i_op->permission)
 		return -EAGAIN;
 		return -EAGAIN;
 
 
-	if (current->fsuid == inode->i_uid)
+	if (current_fsuid() == inode->i_uid)
 		mode >>= 6;
 		mode >>= 6;
 	else if (in_group_p(inode->i_gid))
 	else if (in_group_p(inode->i_gid))
 		mode >>= 3;
 		mode >>= 3;
@@ -1334,11 +1334,13 @@ static int user_path_parent(int dfd, const char __user *path,
  */
  */
 static inline int check_sticky(struct inode *dir, struct inode *inode)
 static inline int check_sticky(struct inode *dir, struct inode *inode)
 {
 {
+	uid_t fsuid = current_fsuid();
+
 	if (!(dir->i_mode & S_ISVTX))
 	if (!(dir->i_mode & S_ISVTX))
 		return 0;
 		return 0;
-	if (inode->i_uid == current->fsuid)
+	if (inode->i_uid == fsuid)
 		return 0;
 		return 0;
-	if (dir->i_uid == current->fsuid)
+	if (dir->i_uid == fsuid)
 		return 0;
 		return 0;
 	return !capable(CAP_FOWNER);
 	return !capable(CAP_FOWNER);
 }
 }

+ 1 - 1
fs/namespace.c

@@ -1176,7 +1176,7 @@ static int mount_is_safe(struct path *path)
 	if (S_ISLNK(path->dentry->d_inode->i_mode))
 	if (S_ISLNK(path->dentry->d_inode->i_mode))
 		return -EPERM;
 		return -EPERM;
 	if (path->dentry->d_inode->i_mode & S_ISVTX) {
 	if (path->dentry->d_inode->i_mode & S_ISVTX) {
-		if (current->uid != path->dentry->d_inode->i_uid)
+		if (current_uid() != path->dentry->d_inode->i_uid)
 			return -EPERM;
 			return -EPERM;
 	}
 	}
 	if (inode_permission(path->dentry->d_inode, MAY_WRITE))
 	if (inode_permission(path->dentry->d_inode, MAY_WRITE))

+ 44 - 47
fs/ncpfs/ioctl.c

@@ -40,10 +40,10 @@ ncp_get_fs_info(struct ncp_server * server, struct file *file,
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct ncp_fs_info info;
 	struct ncp_fs_info info;
 
 
-	if ((file_permission(file, MAY_WRITE) != 0)
-	    && (current->uid != server->m.mounted_uid)) {
+	if (file_permission(file, MAY_WRITE) != 0
+	    && current_uid() != server->m.mounted_uid)
 		return -EACCES;
 		return -EACCES;
-	}
+
 	if (copy_from_user(&info, arg, sizeof(info)))
 	if (copy_from_user(&info, arg, sizeof(info)))
 		return -EFAULT;
 		return -EFAULT;
 
 
@@ -70,10 +70,10 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct ncp_fs_info_v2 info2;
 	struct ncp_fs_info_v2 info2;
 
 
-	if ((file_permission(file, MAY_WRITE) != 0)
-	    && (current->uid != server->m.mounted_uid)) {
+	if (file_permission(file, MAY_WRITE) != 0
+	    && current_uid() != server->m.mounted_uid)
 		return -EACCES;
 		return -EACCES;
-	}
+
 	if (copy_from_user(&info2, arg, sizeof(info2)))
 	if (copy_from_user(&info2, arg, sizeof(info2)))
 		return -EFAULT;
 		return -EFAULT;
 
 
@@ -141,10 +141,10 @@ ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct compat_ncp_fs_info_v2 info2;
 	struct compat_ncp_fs_info_v2 info2;
 
 
-	if ((file_permission(file, MAY_WRITE) != 0)
-	    && (current->uid != server->m.mounted_uid)) {
+	if (file_permission(file, MAY_WRITE) != 0
+	    && current_uid() != server->m.mounted_uid)
 		return -EACCES;
 		return -EACCES;
-	}
+
 	if (copy_from_user(&info2, arg, sizeof(info2)))
 	if (copy_from_user(&info2, arg, sizeof(info2)))
 		return -EFAULT;
 		return -EFAULT;
 
 
@@ -270,16 +270,17 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
 	struct ncp_ioctl_request request;
 	struct ncp_ioctl_request request;
 	char* bouncebuffer;
 	char* bouncebuffer;
 	void __user *argp = (void __user *)arg;
 	void __user *argp = (void __user *)arg;
+	uid_t uid = current_uid();
 
 
 	switch (cmd) {
 	switch (cmd) {
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_NCPREQUEST_32:
 	case NCP_IOC_NCPREQUEST_32:
 #endif
 #endif
 	case NCP_IOC_NCPREQUEST:
 	case NCP_IOC_NCPREQUEST:
-		if ((file_permission(filp, MAY_WRITE) != 0)
-		    && (current->uid != server->m.mounted_uid)) {
+		if (file_permission(filp, MAY_WRITE) != 0
+		    && uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
+
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 		if (cmd == NCP_IOC_NCPREQUEST_32) {
 		if (cmd == NCP_IOC_NCPREQUEST_32) {
 			struct compat_ncp_ioctl_request request32;
 			struct compat_ncp_ioctl_request request32;
@@ -356,10 +357,10 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
 	case NCP_IOC_GETMOUNTUID16:
 	case NCP_IOC_GETMOUNTUID16:
 	case NCP_IOC_GETMOUNTUID32:
 	case NCP_IOC_GETMOUNTUID32:
 	case NCP_IOC_GETMOUNTUID64:
 	case NCP_IOC_GETMOUNTUID64:
-		if ((file_permission(filp, MAY_READ) != 0)
-			&& (current->uid != server->m.mounted_uid)) {
+		if (file_permission(filp, MAY_READ) != 0
+			&& uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
+
 		if (cmd == NCP_IOC_GETMOUNTUID16) {
 		if (cmd == NCP_IOC_GETMOUNTUID16) {
 			u16 uid;
 			u16 uid;
 			SET_UID(uid, server->m.mounted_uid);
 			SET_UID(uid, server->m.mounted_uid);
@@ -380,11 +381,10 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
 		{
 		{
 			struct ncp_setroot_ioctl sr;
 			struct ncp_setroot_ioctl sr;
 
 
-			if ((file_permission(filp, MAY_READ) != 0)
-			    && (current->uid != server->m.mounted_uid))
-			{
+			if (file_permission(filp, MAY_READ) != 0
+			    && uid != server->m.mounted_uid)
 				return -EACCES;
 				return -EACCES;
-			}
+
 			if (server->m.mounted_vol[0]) {
 			if (server->m.mounted_vol[0]) {
 				struct dentry* dentry = inode->i_sb->s_root;
 				struct dentry* dentry = inode->i_sb->s_root;
 
 
@@ -408,6 +408,7 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
 				return -EFAULT;
 				return -EFAULT;
 			return 0;
 			return 0;
 		}
 		}
+
 	case NCP_IOC_SETROOT:
 	case NCP_IOC_SETROOT:
 		{
 		{
 			struct ncp_setroot_ioctl sr;
 			struct ncp_setroot_ioctl sr;
@@ -455,11 +456,10 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
 
 
 #ifdef CONFIG_NCPFS_PACKET_SIGNING	
 #ifdef CONFIG_NCPFS_PACKET_SIGNING	
 	case NCP_IOC_SIGN_INIT:
 	case NCP_IOC_SIGN_INIT:
-		if ((file_permission(filp, MAY_WRITE) != 0)
-		    && (current->uid != server->m.mounted_uid))
-		{
+		if (file_permission(filp, MAY_WRITE) != 0
+		    && uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
+
 		if (argp) {
 		if (argp) {
 			if (server->sign_wanted)
 			if (server->sign_wanted)
 			{
 			{
@@ -478,24 +478,22 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
 		return 0;		
 		return 0;		
 		
 		
         case NCP_IOC_SIGN_WANTED:
         case NCP_IOC_SIGN_WANTED:
-		if ((file_permission(filp, MAY_READ) != 0)
-		    && (current->uid != server->m.mounted_uid))
-		{
+		if (file_permission(filp, MAY_READ) != 0
+		    && uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
 		
 		
                 if (put_user(server->sign_wanted, (int __user *)argp))
                 if (put_user(server->sign_wanted, (int __user *)argp))
 			return -EFAULT;
 			return -EFAULT;
                 return 0;
                 return 0;
+
 	case NCP_IOC_SET_SIGN_WANTED:
 	case NCP_IOC_SET_SIGN_WANTED:
 		{
 		{
 			int newstate;
 			int newstate;
 
 
-			if ((file_permission(filp, MAY_WRITE) != 0)
-			    && (current->uid != server->m.mounted_uid))
-			{
+			if (file_permission(filp, MAY_WRITE) != 0
+			    && uid != server->m.mounted_uid)
 				return -EACCES;
 				return -EACCES;
-			}
+
 			/* get only low 8 bits... */
 			/* get only low 8 bits... */
 			if (get_user(newstate, (unsigned char __user *)argp))
 			if (get_user(newstate, (unsigned char __user *)argp))
 				return -EFAULT;
 				return -EFAULT;
@@ -512,11 +510,10 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
 
 
 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
 	case NCP_IOC_LOCKUNLOCK:
 	case NCP_IOC_LOCKUNLOCK:
-		if ((file_permission(filp, MAY_WRITE) != 0)
-		    && (current->uid != server->m.mounted_uid))
-		{
+		if (file_permission(filp, MAY_WRITE) != 0
+		    && uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
+
 		{
 		{
 			struct ncp_lock_ioctl	 rqdata;
 			struct ncp_lock_ioctl	 rqdata;
 
 
@@ -585,9 +582,8 @@ outrel:
 
 
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_GETOBJECTNAME_32:
 	case NCP_IOC_GETOBJECTNAME_32:
-		if (current->uid != server->m.mounted_uid) {
+		if (uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
 		{
 		{
 			struct compat_ncp_objectname_ioctl user;
 			struct compat_ncp_objectname_ioctl user;
 			size_t outl;
 			size_t outl;
@@ -609,10 +605,10 @@ outrel:
 			return 0;
 			return 0;
 		}
 		}
 #endif
 #endif
+
 	case NCP_IOC_GETOBJECTNAME:
 	case NCP_IOC_GETOBJECTNAME:
-		if (current->uid != server->m.mounted_uid) {
+		if (uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
 		{
 		{
 			struct ncp_objectname_ioctl user;
 			struct ncp_objectname_ioctl user;
 			size_t outl;
 			size_t outl;
@@ -633,13 +629,13 @@ outrel:
 				return -EFAULT;
 				return -EFAULT;
 			return 0;
 			return 0;
 		}
 		}
+
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_SETOBJECTNAME_32:
 	case NCP_IOC_SETOBJECTNAME_32:
 #endif
 #endif
 	case NCP_IOC_SETOBJECTNAME:
 	case NCP_IOC_SETOBJECTNAME:
-		if (current->uid != server->m.mounted_uid) {
+		if (uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
 		{
 		{
 			struct ncp_objectname_ioctl user;
 			struct ncp_objectname_ioctl user;
 			void* newname;
 			void* newname;
@@ -691,13 +687,13 @@ outrel:
 			kfree(oldname);
 			kfree(oldname);
 			return 0;
 			return 0;
 		}
 		}
+
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_GETPRIVATEDATA_32:
 	case NCP_IOC_GETPRIVATEDATA_32:
 #endif
 #endif
 	case NCP_IOC_GETPRIVATEDATA:
 	case NCP_IOC_GETPRIVATEDATA:
-		if (current->uid != server->m.mounted_uid) {
+		if (uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
 		{
 		{
 			struct ncp_privatedata_ioctl user;
 			struct ncp_privatedata_ioctl user;
 			size_t outl;
 			size_t outl;
@@ -736,13 +732,13 @@ outrel:
 
 
 			return 0;
 			return 0;
 		}
 		}
+
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_SETPRIVATEDATA_32:
 	case NCP_IOC_SETPRIVATEDATA_32:
 #endif
 #endif
 	case NCP_IOC_SETPRIVATEDATA:
 	case NCP_IOC_SETPRIVATEDATA:
-		if (current->uid != server->m.mounted_uid) {
+		if (uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
-		}
 		{
 		{
 			struct ncp_privatedata_ioctl user;
 			struct ncp_privatedata_ioctl user;
 			void* new;
 			void* new;
@@ -794,9 +790,10 @@ outrel:
 #endif /* CONFIG_NCPFS_NLS */
 #endif /* CONFIG_NCPFS_NLS */
 
 
 	case NCP_IOC_SETDENTRYTTL:
 	case NCP_IOC_SETDENTRYTTL:
-		if ((file_permission(filp, MAY_WRITE) != 0) &&
-				 (current->uid != server->m.mounted_uid))
+		if (file_permission(filp, MAY_WRITE) != 0 &&
+		    uid != server->m.mounted_uid)
 			return -EACCES;
 			return -EACCES;
+
 		{
 		{
 			u_int32_t user;
 			u_int32_t user;
 
 

+ 4 - 1
fs/nfsctl.c

@@ -10,6 +10,8 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/nfsd/syscall.h>
+#include <linux/cred.h>
+#include <linux/sched.h>
 #include <linux/linkage.h>
 #include <linux/linkage.h>
 #include <linux/namei.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/mount.h>
@@ -41,7 +43,8 @@ static struct file *do_open(char *name, int flags)
 		error = may_open(&nd, MAY_WRITE, FMODE_WRITE);
 		error = may_open(&nd, MAY_WRITE, FMODE_WRITE);
 
 
 	if (!error)
 	if (!error)
-		return dentry_open(nd.path.dentry, nd.path.mnt, flags);
+		return dentry_open(nd.path.dentry, nd.path.mnt, flags,
+				   current_cred());
 
 
 	path_put(&nd.path);
 	path_put(&nd.path);
 	return ERR_PTR(error);
 	return ERR_PTR(error);

+ 56 - 39
fs/nfsd/auth.c

@@ -27,53 +27,70 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
 
 
 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
 {
-	struct svc_cred	cred = rqstp->rq_cred;
+	struct group_info *rqgi;
+	struct group_info *gi;
+	struct cred *new;
 	int i;
 	int i;
 	int flags = nfsexp_flags(rqstp, exp);
 	int flags = nfsexp_flags(rqstp, exp);
 	int ret;
 	int ret;
 
 
+	/* discard any old override before preparing the new set */
+	revert_creds(get_cred(current->real_cred));
+	new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	new->fsuid = rqstp->rq_cred.cr_uid;
+	new->fsgid = rqstp->rq_cred.cr_gid;
+
+	rqgi = rqstp->rq_cred.cr_group_info;
+
 	if (flags & NFSEXP_ALLSQUASH) {
 	if (flags & NFSEXP_ALLSQUASH) {
-		cred.cr_uid = exp->ex_anon_uid;
-		cred.cr_gid = exp->ex_anon_gid;
-		cred.cr_group_info = groups_alloc(0);
+		new->fsuid = exp->ex_anon_uid;
+		new->fsgid = exp->ex_anon_gid;
+		gi = groups_alloc(0);
 	} else if (flags & NFSEXP_ROOTSQUASH) {
 	} else if (flags & NFSEXP_ROOTSQUASH) {
-		struct group_info *gi;
-		if (!cred.cr_uid)
-			cred.cr_uid = exp->ex_anon_uid;
-		if (!cred.cr_gid)
-			cred.cr_gid = exp->ex_anon_gid;
-		gi = groups_alloc(cred.cr_group_info->ngroups);
-		if (gi)
-			for (i = 0; i < cred.cr_group_info->ngroups; i++) {
-				if (!GROUP_AT(cred.cr_group_info, i))
-					GROUP_AT(gi, i) = exp->ex_anon_gid;
-				else
-					GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i);
-			}
-		cred.cr_group_info = gi;
-	} else
-		get_group_info(cred.cr_group_info);
-
-	if (cred.cr_uid != (uid_t) -1)
-		current->fsuid = cred.cr_uid;
-	else
-		current->fsuid = exp->ex_anon_uid;
-	if (cred.cr_gid != (gid_t) -1)
-		current->fsgid = cred.cr_gid;
-	else
-		current->fsgid = exp->ex_anon_gid;
+		if (!new->fsuid)
+			new->fsuid = exp->ex_anon_uid;
+		if (!new->fsgid)
+			new->fsgid = exp->ex_anon_gid;
 
 
-	if (!cred.cr_group_info)
-		return -ENOMEM;
-	ret = set_current_groups(cred.cr_group_info);
-	put_group_info(cred.cr_group_info);
-	if ((cred.cr_uid)) {
-		current->cap_effective =
-			cap_drop_nfsd_set(current->cap_effective);
+		gi = groups_alloc(rqgi->ngroups);
+		if (!gi)
+			goto oom;
+
+		for (i = 0; i < rqgi->ngroups; i++) {
+			if (!GROUP_AT(rqgi, i))
+				GROUP_AT(gi, i) = exp->ex_anon_gid;
+			else
+				GROUP_AT(gi, i) = GROUP_AT(rqgi, i);
+		}
 	} else {
 	} else {
-		current->cap_effective =
-			cap_raise_nfsd_set(current->cap_effective,
-					   current->cap_permitted);
+		gi = get_group_info(rqgi);
 	}
 	}
+
+	if (new->fsuid == (uid_t) -1)
+		new->fsuid = exp->ex_anon_uid;
+	if (new->fsgid == (gid_t) -1)
+		new->fsgid = exp->ex_anon_gid;
+
+	ret = set_groups(new, gi);
+	put_group_info(gi);
+	if (!ret)
+		goto error;
+
+	if (new->uid)
+		new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
+	else
+		new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
+							new->cap_permitted);
+	put_cred(override_creds(new));
+	return 0;
+
+oom:
+	ret = -ENOMEM;
+error:
+	abort_creds(new);
 	return ret;
 	return ret;
 }
 }
+

+ 45 - 27
fs/nfsd/nfs4recover.c

@@ -54,20 +54,26 @@
 static struct path rec_dir;
 static struct path rec_dir;
 static int rec_dir_init = 0;
 static int rec_dir_init = 0;
 
 
-static void
-nfs4_save_user(uid_t *saveuid, gid_t *savegid)
+static int
+nfs4_save_creds(const struct cred **original_creds)
 {
 {
-	*saveuid = current->fsuid;
-	*savegid = current->fsgid;
-	current->fsuid = 0;
-	current->fsgid = 0;
+	struct cred *new;
+
+	new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	new->fsuid = 0;
+	new->fsgid = 0;
+	*original_creds = override_creds(new);
+	put_cred(new);
+	return 0;
 }
 }
 
 
 static void
 static void
-nfs4_reset_user(uid_t saveuid, gid_t savegid)
+nfs4_reset_creds(const struct cred *original)
 {
 {
-	current->fsuid = saveuid;
-	current->fsgid = savegid;
+	revert_creds(original);
 }
 }
 
 
 static void
 static void
@@ -129,10 +135,9 @@ nfsd4_sync_rec_dir(void)
 int
 int
 nfsd4_create_clid_dir(struct nfs4_client *clp)
 nfsd4_create_clid_dir(struct nfs4_client *clp)
 {
 {
+	const struct cred *original_cred;
 	char *dname = clp->cl_recdir;
 	char *dname = clp->cl_recdir;
 	struct dentry *dentry;
 	struct dentry *dentry;
-	uid_t uid;
-	gid_t gid;
 	int status;
 	int status;
 
 
 	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
 	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
@@ -140,7 +145,9 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
 	if (!rec_dir_init || clp->cl_firststate)
 	if (!rec_dir_init || clp->cl_firststate)
 		return 0;
 		return 0;
 
 
-	nfs4_save_user(&uid, &gid);
+	status = nfs4_save_creds(&original_cred);
+	if (status < 0)
+		return status;
 
 
 	/* lock the parent */
 	/* lock the parent */
 	mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
 	mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
@@ -168,7 +175,7 @@ out_unlock:
 		clp->cl_firststate = 1;
 		clp->cl_firststate = 1;
 		nfsd4_sync_rec_dir();
 		nfsd4_sync_rec_dir();
 	}
 	}
-	nfs4_reset_user(uid, gid);
+	nfs4_reset_creds(original_cred);
 	dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
 	dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
 	return status;
 	return status;
 }
 }
@@ -211,26 +218,29 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
 static int
 static int
 nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
 nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
 {
 {
+	const struct cred *original_cred;
 	struct file *filp;
 	struct file *filp;
 	struct dentry_list_arg dla = {
 	struct dentry_list_arg dla = {
 		.parent = dir,
 		.parent = dir,
 	};
 	};
 	struct list_head *dentries = &dla.dentries;
 	struct list_head *dentries = &dla.dentries;
 	struct dentry_list *child;
 	struct dentry_list *child;
-	uid_t uid;
-	gid_t gid;
 	int status;
 	int status;
 
 
 	if (!rec_dir_init)
 	if (!rec_dir_init)
 		return 0;
 		return 0;
 
 
-	nfs4_save_user(&uid, &gid);
+	status = nfs4_save_creds(&original_cred);
+	if (status < 0)
+		return status;
 	INIT_LIST_HEAD(dentries);
 	INIT_LIST_HEAD(dentries);
 
 
-	filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
+	filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY,
+			   current_cred());
 	status = PTR_ERR(filp);
 	status = PTR_ERR(filp);
 	if (IS_ERR(filp))
 	if (IS_ERR(filp))
 		goto out;
 		goto out;
+	INIT_LIST_HEAD(dentries);
 	status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
 	status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
 	fput(filp);
 	fput(filp);
 	while (!list_empty(dentries)) {
 	while (!list_empty(dentries)) {
@@ -249,7 +259,7 @@ out:
 		dput(child->dentry);
 		dput(child->dentry);
 		kfree(child);
 		kfree(child);
 	}
 	}
-	nfs4_reset_user(uid, gid);
+	nfs4_reset_creds(original_cred);
 	return status;
 	return status;
 }
 }
 
 
@@ -311,8 +321,7 @@ out:
 void
 void
 nfsd4_remove_clid_dir(struct nfs4_client *clp)
 nfsd4_remove_clid_dir(struct nfs4_client *clp)
 {
 {
-	uid_t uid;
-	gid_t gid;
+	const struct cred *original_cred;
 	int status;
 	int status;
 
 
 	if (!rec_dir_init || !clp->cl_firststate)
 	if (!rec_dir_init || !clp->cl_firststate)
@@ -322,9 +331,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
 	if (status)
 	if (status)
 		goto out;
 		goto out;
 	clp->cl_firststate = 0;
 	clp->cl_firststate = 0;
-	nfs4_save_user(&uid, &gid);
+
+	status = nfs4_save_creds(&original_cred);
+	if (status < 0)
+		goto out;
+
 	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
 	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
-	nfs4_reset_user(uid, gid);
+	nfs4_reset_creds(original_cred);
 	if (status == 0)
 	if (status == 0)
 		nfsd4_sync_rec_dir();
 		nfsd4_sync_rec_dir();
 	mnt_drop_write(rec_dir.mnt);
 	mnt_drop_write(rec_dir.mnt);
@@ -401,16 +414,21 @@ nfsd4_recdir_load(void) {
 void
 void
 nfsd4_init_recdir(char *rec_dirname)
 nfsd4_init_recdir(char *rec_dirname)
 {
 {
-	uid_t			uid = 0;
-	gid_t			gid = 0;
-	int 			status;
+	const struct cred *original_cred;
+	int status;
 
 
 	printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
 	printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
 			rec_dirname);
 			rec_dirname);
 
 
 	BUG_ON(rec_dir_init);
 	BUG_ON(rec_dir_init);
 
 
-	nfs4_save_user(&uid, &gid);
+	status = nfs4_save_creds(&original_cred);
+	if (status < 0) {
+		printk("NFSD: Unable to change credentials to find recovery"
+		       " directory: error %d\n",
+		       status);
+		return;
+	}
 
 
 	status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
 	status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
 			&rec_dir);
 			&rec_dir);
@@ -420,7 +438,7 @@ nfsd4_init_recdir(char *rec_dirname)
 
 
 	if (!status)
 	if (!status)
 		rec_dir_init = 1;
 		rec_dir_init = 1;
-	nfs4_reset_user(uid, gid);
+	nfs4_reset_creds(original_cred);
 }
 }
 
 
 void
 void

+ 8 - 3
fs/nfsd/nfsfh.c

@@ -186,9 +186,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
 		 * access control settings being in effect, we cannot
 		 * access control settings being in effect, we cannot
 		 * fix that case easily.
 		 * fix that case easily.
 		 */
 		 */
-		current->cap_effective =
-			cap_raise_nfsd_set(current->cap_effective,
-					   current->cap_permitted);
+		struct cred *new = prepare_creds();
+		if (!new)
+			return nfserrno(-ENOMEM);
+		new->cap_effective =
+			cap_raise_nfsd_set(new->cap_effective,
+					   new->cap_permitted);
+		put_cred(override_creds(new));
+		put_cred(new);
 	} else {
 	} else {
 		error = nfsd_setuser_and_check_port(rqstp, exp);
 		error = nfsd_setuser_and_check_port(rqstp, exp);
 		if (error)
 		if (error)

Some files were not shown because too many files changed in this diff