All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/52] Introduce credential record
@ 2007-10-12 16:05 David Howells
  2007-10-12 16:05 ` [PATCH 01/52] CRED: Introduce a COW credentials record David Howells
                   ` (53 more replies)
  0 siblings, 54 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:05 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells


Hi Al,

Here's a set of patches to partially implement cred passing.  This is in no
way complete yet.

The only complete chain is mkdir(), and only Ext3 and NFS are fully altered,
though I think NFS really needs redoing.  I'd like to come up with a way of
caching the rpc_cred struct inside the struct cred, but that needs some
thought.

Most of the vfs_xxxx() structs grab current->cred and pass it on down.
vfs_mkdir() is currently the only one that gets given it.

There are also holes in fs/buffer.c that need patching up, and most of the
other filesystems haven't yet been touched.

Note that I haven't included keyrings or capabilties or LSM data at this time.

Note also that this patch set is built on top of the iget patch set I've
posted to LKML earlier today.

David

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

* [PATCH 01/52] CRED: Introduce a COW credentials record
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
@ 2007-10-12 16:05 ` David Howells
  2007-10-15  1:53   ` David Chinner
  2007-10-12 16:05 ` [PATCH 02/52] CRED: Give in_group_p() a cred pointer David Howells
                   ` (52 subsequent siblings)
  53 siblings, 1 reply; 57+ messages in thread
From: David Howells @ 2007-10-12 16:05 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Introduce a copy on write credentials record (struct cred).  The fsuid, fsgid,
supplementary groups list move into it (DAC security).  The session, process
and thread keyrings are reflected in it, but don't primarily reside there as
they aren't per-thread and occasionally need to be instantiated or replaced by
other threads or processes.

The LSM security information (MAC security) does *not* migrate from task_struct
at this point, but will be addressed by a later patch.

task_struct then gains an RCU-governed pointer to the credentials as a
replacement to the members it lost.

struct file gains a pointer to (f_cred) and a reference on the cred struct that
the opener was using at the time the file was opened.  This replaces f_uid and
f_gid.

To alter the credentials record, a copy must be made.  This copy may then be
altered and then the pointer in the task_struct redirected to it.  From that
point on the new record should be considered immutable.

In addition, the default setting of i_uid and i_gid to fsuid and fsgid has been
moved from the callers of new_inode() into new_inode() itself.

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

 arch/ia64/kernel/perfmon.c                |    4 -
 arch/mips/kernel/kspd.c                   |    9 +-
 arch/powerpc/platforms/cell/spufs/inode.c |    4 -
 drivers/isdn/capi/capifs.c                |    4 -
 drivers/usb/core/inode.c                  |    4 -
 fs/9p/vfs_inode.c                         |    4 -
 fs/9p/vfs_super.c                         |    4 -
 fs/affs/inode.c                           |    4 -
 fs/anon_inodes.c                          |    4 -
 fs/attr.c                                 |    4 -
 fs/bfs/dir.c                              |    4 -
 fs/cifs/cifsproto.h                       |    2 
 fs/cifs/dir.c                             |   12 +-
 fs/cifs/inode.c                           |    8 +
 fs/cifs/misc.c                            |    4 -
 fs/coda/cache.c                           |    6 +
 fs/coda/file.c                            |    2 
 fs/coda/upcall.c                          |    4 -
 fs/devpts/inode.c                         |    4 -
 fs/dquot.c                                |    2 
 fs/exec.c                                 |   29 ++++-
 fs/ext2/balloc.c                          |    2 
 fs/ext2/ialloc.c                          |    4 -
 fs/ext3/balloc.c                          |    2 
 fs/ext3/ialloc.c                          |    4 -
 fs/ext4/balloc.c                          |    2 
 fs/ext4/ialloc.c                          |    4 -
 fs/file_table.c                           |    3 -
 fs/fuse/dev.c                             |    4 -
 fs/gfs2/inode.c                           |   10 +-
 fs/hfs/inode.c                            |    4 -
 fs/hfsplus/inode.c                        |    4 -
 fs/hpfs/namei.c                           |   24 ++--
 fs/hugetlbfs/inode.c                      |   16 +--
 fs/jffs2/fs.c                             |    4 -
 fs/jfs/jfs_inode.c                        |    4 -
 fs/locks.c                                |    2 
 fs/minix/bitmap.c                         |    4 -
 fs/namei.c                                |    8 +
 fs/nfsd/auth.c                            |   32 ++++--
 fs/nfsd/nfs4callback.c                    |   16 ++-
 fs/nfsd/nfs4recover.c                     |   54 +++++-----
 fs/nfsd/vfs.c                             |    4 -
 fs/ocfs2/dlm/dlmfs.c                      |    8 +
 fs/ocfs2/namei.c                          |    4 -
 fs/open.c                                 |   21 ++--
 fs/pipe.c                                 |    4 -
 fs/posix_acl.c                            |    4 -
 fs/proc/array.c                           |   12 +-
 fs/ramfs/inode.c                          |    4 -
 fs/reiserfs/namei.c                       |    4 -
 fs/sysv/ialloc.c                          |    4 -
 fs/udf/ialloc.c                           |    4 -
 fs/udf/namei.c                            |    2 
 fs/ufs/ialloc.c                           |    4 -
 fs/xfs/linux-2.6/xfs_cred.h               |    4 -
 fs/xfs/linux-2.6/xfs_linux.h              |    4 -
 fs/xfs/xfs_acl.c                          |    6 +
 include/linux/binfmts.h                   |    1 
 include/linux/cred.h                      |  163 +++++++++++++++++++++++++++++
 include/linux/fs.h                        |    5 +
 include/linux/init_task.h                 |    4 -
 include/linux/sched.h                     |    7 +
 include/linux/sunrpc/auth.h               |   18 +--
 ipc/mqueue.c                              |    4 -
 kernel/Makefile                           |    2 
 kernel/auditsc.c                          |   13 ++
 kernel/cpuset.c                           |    4 -
 kernel/cred.c                             |  123 ++++++++++++++++++++++
 kernel/exit.c                             |    1 
 kernel/fork.c                             |   22 +++-
 kernel/kernel-int.h                       |   15 +++
 kernel/sys.c                              |  144 +++++++++++++++++++-------
 kernel/uid16.c                            |    7 +
 mm/shmem.c                                |    8 +
 net/9p/client.c                           |    2 
 net/socket.c                              |    4 -
 net/sunrpc/auth.c                         |   25 +---
 net/sunrpc/auth_gss/auth_gss.c            |    6 +
 net/sunrpc/auth_null.c                    |    4 -
 net/sunrpc/auth_unix.c                    |    6 +
 security/commoncap.c                      |    8 +
 security/dummy.c                          |   13 ++
 security/keys/key.c                       |    3 -
 security/keys/keyctl.c                    |    2 
 security/keys/permission.c                |   16 ++-
 security/keys/process_keys.c              |    6 +
 security/keys/request_key.c               |   14 +-
 security/keys/request_key_auth.c          |    2 
 89 files changed, 740 insertions(+), 334 deletions(-)

diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 14b8e5a..b063444 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2212,8 +2212,8 @@ pfm_alloc_fd(struct file **cfile)
 	DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode));
 
 	inode->i_mode = S_IFCHR|S_IRUGO;
-	inode->i_uid  = current->fsuid;
-	inode->i_gid  = current->fsgid;
+	inode->i_uid  = current->cred->uid;
+	inode->i_gid  = current->cred->gid;
 
 	sprintf(name, "[%lu]", inode->i_ino);
 	this.name = name;
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index d2c2e00..96eca0b 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -174,11 +174,10 @@ static unsigned int translate_open_flags(int flags)
 
 static void sp_setfsuidgid( uid_t uid, gid_t gid)
 {
-	current->fsuid = uid;
-	current->fsgid = gid;
-
-	key_fsuid_changed(current);
-	key_fsgid_changed(current);
+	struct cred *cred = dup_cred(current->cred);
+	change_fsuid(cred, uid);
+	change_fsgid(cred, gid);
+	set_current_cred(cred);
 }
 
 /*
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 1109874..274f08b 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -85,8 +85,8 @@ spufs_new_inode(struct super_block *sb, int mode)
 		goto out;
 
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = current->cred->gid;
 	inode->i_blocks = 0;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 out:
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index 2dd1b57..1b99663 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -148,8 +148,8 @@ void capifs_new_ncci(unsigned int number, dev_t device)
 	if (!inode)
 		return;
 	inode->i_ino = number+2;
-	inode->i_uid = config.setuid ? config.uid : current->fsuid;
-	inode->i_gid = config.setgid ? config.gid : current->fsgid;
+	inode->i_uid = config.setuid ? config.uid : current->cred->uid;
+	inode->i_gid = config.setgid ? config.gid : current->cred->gid;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	//inode->i_op = &capifs_file_inode_operations;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index cd4f111..1f0e75d 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -246,8 +246,8 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
 
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current->cred->uid;
+		inode->i_gid = current->cred->gid;
 		inode->i_blocks = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		switch (mode & S_IFMT) {
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 53444f0..d08fcef 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -202,8 +202,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 	inode = new_inode(sb);
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current->cred->uid;
+		inode->i_gid = current->cred->gid;
 		inode->i_blocks = 0;
 		inode->i_rdev = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index ba90437..fe32357 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -112,8 +112,8 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
 	struct v9fs_session_info *v9ses = NULL;
 	struct p9_stat *st = NULL;
 	int mode = S_IRWXUGO | S_ISVTX;
-	uid_t uid = current->fsuid;
-	gid_t gid = current->fsgid;
+	uid_t uid = current->cred->uid;
+	gid_t gid = current->cred->gid;
 	struct p9_fid *fid;
 	int retval = 0;
 
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index edea76c..c0998c1 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -311,8 +311,8 @@ affs_new_inode(struct inode *dir)
 	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
 
-	inode->i_uid     = current->fsuid;
-	inode->i_gid     = current->fsgid;
+	inode->i_uid     = current->cred->uid;
+	inode->i_gid     = current->cred->gid;
 	inode->i_ino     = block;
 	inode->i_nlink   = 1;
 	inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index b4a7588..de05856 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -163,8 +163,8 @@ static struct inode *anon_inode_mkinode(void)
 	 */
 	inode->i_state = I_DIRTY;
 	inode->i_mode = S_IRUSR | S_IWUSR;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = current->cred->gid;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	return inode;
 }
diff --git a/fs/attr.c b/fs/attr.c
index f8dfc22..3e6b911 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -29,13 +29,13 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
 
 	/* Make sure a caller can chown. */
 	if ((ia_valid & ATTR_UID) &&
-	    (current->fsuid != inode->i_uid ||
+	    (current->cred->uid != inode->i_uid ||
 	     attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
 		goto error;
 
 	/* Make sure caller can chgrp. */
 	if ((ia_valid & ATTR_GID) &&
-	    (current->fsuid != inode->i_uid ||
+	    (current->cred->uid != inode->i_uid ||
 	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
 	    !capable(CAP_CHOWN))
 		goto error;
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 03c8bdb..275de1e 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -99,8 +99,8 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
 	}
 	set_bit(ino, info->si_imap);	
 	info->si_freei--;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->cred->gid;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_blocks = 0;
 	inode->i_op = &bfs_file_inops;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 04a69da..8a79ce3 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -39,7 +39,7 @@ extern int smb_send(struct socket *, struct smb_hdr *,
 			unsigned int /* length */ , struct sockaddr *);
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
-#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->cred->uid));
 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4830acc..f1b6808 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -211,8 +211,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 			mode &= ~current->fs->umask;
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
-					(__u64)current->fsuid,
-					(__u64)current->fsgid,
+					(__u64)current->cred->uid,
+					(__u64)current->cred->gid,
 					0 /* dev */,
 					cifs_sb->local_nls,
 					cifs_sb->mnt_cifs_flags &
@@ -246,8 +246,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 				if ((oplock & CIFS_CREATE_ACTION) &&
 				    (cifs_sb->mnt_cifs_flags &
 				     CIFS_MOUNT_SET_UID)) {
-					newinode->i_uid = current->fsuid;
-					newinode->i_gid = current->fsgid;
+					newinode->i_uid = current->cred->uid;
+					newinode->i_gid = current->cred->gid;
 				}
 			}
 		}
@@ -340,8 +340,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
 		mode &= ~current->fs->umask;
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
-				mode, (__u64)current->fsuid,
-				(__u64)current->fsgid,
+				mode, (__u64)current->cred->uid,
+				(__u64)current->cred->gid,
 				device_number, cifs_sb->local_nls,
 				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 48966b9..7f31094 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1020,8 +1020,8 @@ mkdir_get_info:
 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
 						    mode,
-						    (__u64)current->fsuid,
-						    (__u64)current->fsgid,
+						    (__u64)current->cred->uid,
+						    (__u64)current->cred->gid,
 						    0 /* dev_t */,
 						    cifs_sb->local_nls,
 						    cifs_sb->mnt_cifs_flags &
@@ -1044,9 +1044,9 @@ mkdir_get_info:
 				if (cifs_sb->mnt_cifs_flags &
 				     CIFS_MOUNT_SET_UID) {
 					direntry->d_inode->i_uid =
-						current->fsuid;
+						current->cred->uid;
 					direntry->d_inode->i_gid =
-						current->fsgid;
+						current->cred->gid;
 				}
 			}
 		}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 0bcec08..8ed3d16 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -352,13 +352,13 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
 		/*  BB Add support for establishing new tCon and SMB Session  */
 		/*      with userid/password pairs found on the smb session   */
 		/*	for other target tcp/ip addresses 		BB    */
-				if (current->fsuid != treeCon->ses->linux_uid) {
+				if (current->cred->uid != treeCon->ses->linux_uid) {
 					cFYI(1, ("Multiuser mode and UID "
 						 "did not match tcon uid"));
 					read_lock(&GlobalSMBSeslock);
 					list_for_each(temp_item, &GlobalSMBSessionList) {
 						ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
-						if (ses->linux_uid == current->fsuid) {
+						if (ses->linux_uid == current->cred->uid) {
 							if (ses->server == treeCon->ses->server) {
 								cFYI(1, ("found matching uid substitute right smb_uid"));
 								buffer->Uid = ses->Suid;
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 8a23703..10120dd 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -32,8 +32,8 @@ void coda_cache_enter(struct inode *inode, int mask)
 	struct coda_inode_info *cii = ITOC(inode);
 
 	cii->c_cached_epoch = atomic_read(&permission_epoch);
-	if (cii->c_uid != current->fsuid) {
-                cii->c_uid = current->fsuid;
+	if (cii->c_uid != current->cred->uid) {
+                cii->c_uid = current->cred->uid;
                 cii->c_cached_perm = mask;
         } else
                 cii->c_cached_perm |= mask;
@@ -60,7 +60,7 @@ int coda_cache_check(struct inode *inode, int mask)
         int hit;
 	
         hit = (mask & cii->c_cached_perm) == mask &&
-		cii->c_uid == current->fsuid &&
+		cii->c_uid == current->cred->uid &&
 		cii->c_cached_epoch == atomic_read(&permission_epoch);
 
         return hit;
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 29137ff..9d8f92c 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -174,7 +174,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
 
 	err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
-			  coda_flags, coda_file->f_uid);
+			  coda_flags, coda_file->f_cred->uid);
 
 	host_inode = cfi->cfi_container->f_path.dentry->d_inode;
 	cii = ITOC(coda_inode);
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index cdb4c07..0e978ba 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -54,9 +54,9 @@ static void *alloc_upcall(int opcode, int size)
 	inp->ih.pgid = process_group(current);
 #ifdef CONFIG_CODA_FS_OLD_API
 	memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
-	inp->ih.cred.cr_fsuid = current->fsuid;
+	inp->ih.cred.cr_fsuid = current->cred->uid;
 #else
-	inp->ih.uid = current->fsuid;
+	inp->ih.uid = current->cred->uid;
 #endif
 	return (void*)inp;
 }
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 06ef9a2..b6829ab 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -172,8 +172,8 @@ int devpts_pty_new(struct tty_struct *tty)
 		return -ENOMEM;
 
 	inode->i_ino = number+2;
-	inode->i_uid = config.setuid ? config.uid : current->fsuid;
-	inode->i_gid = config.setgid ? config.gid : current->fsgid;
+	inode->i_uid = config.setuid ? config.uid : current->cred->uid;
+	inode->i_gid = config.setgid ? config.gid : current->cred->gid;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|config.mode, device);
 	inode->i_private = tty;
diff --git a/fs/dquot.c b/fs/dquot.c
index de9a29f..f1748c6 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -832,7 +832,7 @@ static inline int need_print_warning(struct dquot *dquot)
 
 	switch (dquot->dq_type) {
 		case USRQUOTA:
-			return current->fsuid == dquot->dq_id;
+			return current->cred->uid == dquot->dq_id;
 		case GRPQUOTA:
 			return in_group_p(dquot->dq_id);
 	}
diff --git a/fs/exec.c b/fs/exec.c
index 073b0b8..3faef59 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1137,6 +1137,11 @@ int prepare_binprm(struct linux_binprm *bprm)
 		}
 	}
 
+	/* prepare the new credentials */
+	bprm->cred = dup_cred(current->cred);
+	if (!bprm->cred)
+		return -ENOMEM;
+
 	/* fill in binprm security blob */
 	retval = security_bprm_set(bprm);
 	if (retval)
@@ -1178,7 +1183,9 @@ void compute_creds(struct linux_binprm *bprm)
 	task_lock(current);
 	unsafe = unsafe_exec(current);
 	security_bprm_apply_creds(bprm, unsafe);
+	set_current_cred(bprm->cred);
 	task_unlock(current);
+	bprm->cred = NULL;
 	security_bprm_post_apply_creds(bprm);
 }
 EXPORT_SYMBOL(compute_creds);
@@ -1409,6 +1416,8 @@ out:
 	free_arg_pages(bprm);
 	if (bprm->security)
 		security_bprm_free(bprm);
+	if (bprm->cred)
+		put_cred(bprm->cred);
 
 out_mm:
 	if (bprm->mm)
@@ -1716,8 +1725,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	struct linux_binfmt * binfmt;
 	struct inode * inode;
 	struct file * file;
+	struct cred *cred;
 	int retval = 0;
-	int fsuid = current->fsuid;
 	int flag = 0;
 	int ispipe = 0;
 
@@ -1732,6 +1741,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 		goto fail;
 	}
 
+	cred = dup_cred(current->cred);
+	if (!cred)
+		goto fail;
+
 	/*
 	 *	We cannot trust fsuid as being the "true" uid of the
 	 *	process nor do we know its entire history. We only know it
@@ -1739,13 +1752,13 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	 */
 	if (get_dumpable(mm) == 2) {	/* Setuid core dump mode */
 		flag = O_EXCL;		/* Stop rewrite attacks */
-		current->fsuid = 0;	/* Dump root private */
+		change_fsuid(cred, 0);	/* Dump root private */
 	}
 	set_dumpable(mm, 0);
 
 	retval = coredump_wait(exit_code);
 	if (retval < 0)
-		goto fail;
+		goto fail_cred;
 
 	/*
 	 * Clear any false indication of pending signals that might
@@ -1763,19 +1776,20 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
  	lock_kernel();
 	ispipe = format_corename(corename, core_pattern, signr);
 	unlock_kernel();
+	cred = __set_current_cred(cred);
  	if (ispipe) {
 		/* SIGPIPE can happen, but it's just never processed */
  		if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
  			printk(KERN_INFO "Core dump to %s pipe failed\n",
 			       corename);
- 			goto fail_unlock;
+			goto fail_restore_cred;
  		}
  	} else
  		file = filp_open(corename,
 				 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
 				 0600);
 	if (IS_ERR(file))
-		goto fail_unlock;
+		goto fail_restore_cred;
 	inode = file->f_path.dentry->d_inode;
 	if (inode->i_nlink > 1)
 		goto close_fail;	/* multiple links - don't dump */
@@ -1799,9 +1813,12 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 		current->signal->group_exit_code |= 0x80;
 close_fail:
 	filp_close(file, NULL);
+fail_restore_cred:
+	set_current_cred(cred);
 fail_unlock:
-	current->fsuid = fsuid;
 	complete_all(&mm->core_done);
+fail_cred:
+	put_cred(cred);
 fail:
 	return retval;
 }
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index baf71dd..3517fce 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -112,7 +112,7 @@ static int reserve_blocks(struct super_block *sb, int count)
 		count = free_blocks;
 
 	if (free_blocks < root_blocks + count && !capable(CAP_SYS_RESOURCE) &&
-	    sbi->s_resuid != current->fsuid &&
+	    sbi->s_resuid != current->cred->uid &&
 	    (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		/*
 		 * We are too close to reserve and we are not privileged.
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 2cb545b..03b9287 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -562,7 +562,7 @@ got:
 
 	sb->s_dirt = 1;
 	mark_buffer_dirty(bh2);
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -570,7 +570,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current->cred->gid;
 	inode->i_mode = mode;
 
 	inode->i_ino = ino;
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index ca8aee6..6c4e82f 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1360,7 +1360,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current->fsuid &&
+		sbi->s_resuid != current->cred->uid &&
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		return 0;
 	}
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 5724adb..195e9e8 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -546,7 +546,7 @@ got:
 		percpu_counter_inc(&sbi->s_dirs_counter);
 	sb->s_dirt = 1;
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -554,7 +554,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current->cred->gid;
 	inode->i_mode = mode;
 
 	inode->i_ino = ino;
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index e53b4af..1628c1b 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1377,7 +1377,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = ext4_r_blocks_count(sbi->s_es);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current->fsuid &&
+		sbi->s_resuid != current->cred->uid &&
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		return 0;
 	}
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 4fba007..488cc2b 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -549,7 +549,7 @@ got:
 		percpu_counter_inc(&sbi->s_dirs_counter);
 	sb->s_dirt = 1;
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -557,7 +557,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current->cred->gid;
 	inode->i_mode = mode;
 
 	inode->i_ino = ino;
diff --git a/fs/file_table.c b/fs/file_table.c
index d17fd69..f4c772c 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -115,8 +115,7 @@ struct file *get_empty_filp(void)
 	INIT_LIST_HEAD(&f->f_u.fu_list);
 	atomic_set(&f->f_count, 1);
 	rwlock_init(&f->f_owner.lock);
-	f->f_uid = tsk->fsuid;
-	f->f_gid = tsk->fsgid;
+	f->f_cred = get_current_cred();
 	eventpoll_init_file(f);
 	/* f->f_version: 0 */
 	return f;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 3ad22be..6436840 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -79,8 +79,8 @@ static void __fuse_put_request(struct fuse_req *req)
 
 static void fuse_req_init_context(struct fuse_req *req)
 {
-	req->in.h.uid = current->fsuid;
-	req->in.h.gid = current->fsgid;
+	req->in.h.uid = current->cred->uid;
+	req->in.h.gid = current->cred->gid;
 	req->in.h.pid = current->pid;
 }
 
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 498844f..6dbd255 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -633,18 +633,18 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
 	    (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
 		if (S_ISDIR(*mode))
 			*mode |= S_ISUID;
-		else if (dip->i_inode.i_uid != current->fsuid)
+		else if (dip->i_inode.i_uid != current->cred->uid)
 			*mode &= ~07111;
 		*uid = dip->i_inode.i_uid;
 	} else
-		*uid = current->fsuid;
+		*uid = current->cred->uid;
 
 	if (dip->i_inode.i_mode & S_ISGID) {
 		if (S_ISDIR(*mode))
 			*mode |= S_ISGID;
 		*gid = dip->i_inode.i_gid;
 	} else
-		*gid = current->fsgid;
+		*gid = current->cred->gid;
 }
 
 static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
@@ -1048,8 +1048,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
 		return -EPERM;
 
 	if ((dip->i_inode.i_mode & S_ISVTX) &&
-	    dip->i_inode.i_uid != current->fsuid &&
-	    ip->i_inode.i_uid != current->fsuid && !capable(CAP_FOWNER))
+	    dip->i_inode.i_uid != current->cred->uid &&
+	    ip->i_inode.i_uid != current->cred->uid && !capable(CAP_FOWNER))
 		return -EPERM;
 
 	if (IS_APPEND(&dip->i_inode))
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index bc835f2..43fe09f 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -151,8 +151,8 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
 	hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
 	inode->i_ino = HFS_SB(sb)->next_id++;
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = current->cred->gid;
 	inode->i_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	HFS_I(inode)->flags = 0;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 6f7c662..e7ccd30 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -308,8 +308,8 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
 
 	inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = current->cred->gid;
 	inode->i_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index d256559..121d7d5 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -92,11 +92,11 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	inc_nlink(dir);
 	insert_inode_hash(result);
 
-	if (result->i_uid != current->fsuid ||
-	    result->i_gid != current->fsgid ||
+	if (result->i_uid != current->cred->uid ||
+	    result->i_gid != current->cred->gid ||
 	    result->i_mode != (mode | S_IFDIR)) {
-		result->i_uid = current->fsuid;
-		result->i_gid = current->fsgid;
+		result->i_uid = current->cred->uid;
+		result->i_gid = current->cred->gid;
 		result->i_mode = mode | S_IFDIR;
 		hpfs_write_inode_nolock(result);
 	}
@@ -184,11 +184,11 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
 
 	insert_inode_hash(result);
 
-	if (result->i_uid != current->fsuid ||
-	    result->i_gid != current->fsgid ||
+	if (result->i_uid != current->cred->uid ||
+	    result->i_gid != current->cred->gid ||
 	    result->i_mode != (mode | S_IFREG)) {
-		result->i_uid = current->fsuid;
-		result->i_gid = current->fsgid;
+		result->i_uid = current->cred->uid;
+		result->i_gid = current->cred->gid;
 		result->i_mode = mode | S_IFREG;
 		hpfs_write_inode_nolock(result);
 	}
@@ -247,8 +247,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
 	result->i_mtime.tv_nsec = 0;
 	result->i_atime.tv_nsec = 0;
 	hpfs_i(result)->i_ea_size = 0;
-	result->i_uid = current->fsuid;
-	result->i_gid = current->fsgid;
+	result->i_uid = current->cred->uid;
+	result->i_gid = current->cred->gid;
 	result->i_nlink = 1;
 	result->i_size = 0;
 	result->i_blocks = 1;
@@ -325,8 +325,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
 	result->i_atime.tv_nsec = 0;
 	hpfs_i(result)->i_ea_size = 0;
 	result->i_mode = S_IFLNK | 0777;
-	result->i_uid = current->fsuid;
-	result->i_gid = current->fsgid;
+	result->i_uid = current->cred->uid;
+	result->i_gid = current->cred->gid;
 	result->i_blocks = 1;
 	result->i_nlink = 1;
 	result->i_size = strlen(symlink);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 950c2fb..354f545 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -422,9 +422,9 @@ static int hugetlbfs_mknod(struct inode *dir,
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else {
-		gid = current->fsgid;
+		gid = current->cred->gid;
 	}
-	inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid, gid, mode, dev);
+	inode = hugetlbfs_get_inode(dir->i_sb, current->cred->uid, gid, mode, dev);
 	if (inode) {
 		dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 		d_instantiate(dentry, inode);
@@ -457,9 +457,9 @@ static int hugetlbfs_symlink(struct inode *dir,
 	if (dir->i_mode & S_ISGID)
 		gid = dir->i_gid;
 	else
-		gid = current->fsgid;
+		gid = current->cred->gid;
 
-	inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid,
+	inode = hugetlbfs_get_inode(dir->i_sb, current->cred->uid,
 					gid, S_IFLNK|S_IRWXUGO, 0);
 	if (inode) {
 		int l = strlen(symname)+1;
@@ -697,8 +697,8 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
 
 	config.nr_blocks = -1; /* No limit on size by default */
 	config.nr_inodes = -1; /* No limit on number of inodes by default */
-	config.uid = current->fsuid;
-	config.gid = current->fsgid;
+	config.uid = current->cred->uid;
+	config.gid = current->cred->gid;
 	config.mode = 0755;
 	ret = hugetlbfs_parse_options(data, &config);
 	if (ret)
@@ -816,8 +816,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
 		goto out_dentry;
 
 	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->cred->uid,
+				current->cred->gid, S_IFREG | S_IRWXUGO, 0);
 	if (!inode)
 		goto out_file;
 
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 900be8b..a3ae187 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -434,14 +434,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
 
 	memset(ri, 0, sizeof(*ri));
 	/* Set OS-specific defaults for new inodes */
-	ri->uid = cpu_to_je16(current->fsuid);
+	ri->uid = cpu_to_je16(current->cred->uid);
 
 	if (dir_i->i_mode & S_ISGID) {
 		ri->gid = cpu_to_je16(dir_i->i_gid);
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else {
-		ri->gid = cpu_to_je16(current->fsgid);
+		ri->gid = cpu_to_je16(current->cred->gid);
 	}
 	ri->mode =  cpu_to_jemode(mode);
 	ret = jffs2_do_new_inode (c, f, mode, ri);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index ed6574b..c913156 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -93,13 +93,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
 		return ERR_PTR(rc);
 	}
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	if (parent->i_mode & S_ISGID) {
 		inode->i_gid = parent->i_gid;
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current->cred->gid;
 
 	/*
 	 * New inodes need to save sane values on disk when
diff --git a/fs/locks.c b/fs/locks.c
index c795eaa..6d82706 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1341,7 +1341,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 	struct inode *inode = dentry->d_inode;
 	int error, rdlease_count = 0, wrlease_count = 0;
 
-	if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
+	if ((current->cred->uid != inode->i_uid) && !capable(CAP_LEASE))
 		return -EACCES;
 	if (!S_ISREG(inode->i_mode))
 		return -EINVAL;
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 99a12f1..daacbf0 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -262,8 +262,8 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
 		iput(inode);
 		return NULL;
 	}
-	inode->i_uid = current->fsuid;
-	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->cred->gid;
 	inode->i_ino = j;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_blocks = 0;
diff --git a/fs/namei.c b/fs/namei.c
index a83160a..3e10fff 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -185,7 +185,7 @@ int generic_permission(struct inode *inode, int mask,
 {
 	umode_t			mode = inode->i_mode;
 
-	if (current->fsuid == inode->i_uid)
+	if (current->cred->uid == inode->i_uid)
 		mode >>= 6;
 	else {
 		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
@@ -437,7 +437,7 @@ static int exec_permission_lite(struct inode *inode,
 	if (inode->i_op && inode->i_op->permission)
 		return -EAGAIN;
 
-	if (current->fsuid == inode->i_uid)
+	if (current->cred->uid == inode->i_uid)
 		mode >>= 6;
 	else if (in_group_p(inode->i_gid))
 		mode >>= 3;
@@ -1406,9 +1406,9 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
 {
 	if (!(dir->i_mode & S_ISVTX))
 		return 0;
-	if (inode->i_uid == current->fsuid)
+	if (inode->i_uid == current->cred->uid)
 		return 0;
-	if (dir->i_uid == current->fsuid)
+	if (dir->i_uid == current->cred->uid)
 		return 0;
 	return !capable(CAP_FOWNER);
 }
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 2192805..2024f96 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -29,9 +29,13 @@ int nfsexp_flags(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 cred *vfscred;
 	int i;
 	int flags = nfsexp_flags(rqstp, exp);
-	int ret;
+
+	vfscred = dup_cred(current->cred);
+	if (!vfscred)
+		return -ENOMEM;
 
 	if (flags & NFSEXP_ALLSQUASH) {
 		cred.cr_uid = exp->ex_anon_uid;
@@ -55,24 +59,30 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 	} else
 		get_group_info(cred.cr_group_info);
 
+	if (!cred.cr_group_info) {
+		put_cred(vfscred);
+		return -ENOMEM;
+	}
+
 	if (cred.cr_uid != (uid_t) -1)
-		current->fsuid = cred.cr_uid;
+		change_fsuid(vfscred, cred.cr_uid);
 	else
-		current->fsuid = exp->ex_anon_uid;
+		change_fsuid(vfscred, exp->ex_anon_uid);
 	if (cred.cr_gid != (gid_t) -1)
-		current->fsgid = cred.cr_gid;
+		change_fsgid(vfscred, cred.cr_gid);
 	else
-		current->fsgid = exp->ex_anon_gid;
+		change_fsgid(vfscred, exp->ex_anon_gid);
 
-	if (!cred.cr_group_info)
-		return -ENOMEM;
-	ret = set_current_groups(cred.cr_group_info);
+	change_groups(vfscred, cred.cr_group_info);
 	put_group_info(cred.cr_group_info);
 	if ((cred.cr_uid)) {
-		cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
+		cap_t(vfscred->cap_effective) &= ~CAP_NFSD_MASK;
 	} else {
-		cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
+		cap_t(vfscred->cap_effective) |= (CAP_NFSD_MASK &
 						  current->cap_permitted);
 	}
-	return ret;
+
+	current->_cap_effective = vfscred->cap_effective;
+	set_current_cred(vfscred);
+	return 0;
 }
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 31d6633..29c566c 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -349,19 +349,21 @@ static struct rpc_version *	nfs_cb_version[] = {
 static struct rpc_cred *
 nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
 {
-        struct auth_cred acred;
+        struct cred *acred;
 	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
 	struct rpc_cred *ret;
 
-        get_group_info(clp->cl_cred.cr_group_info);
-        acred.uid = clp->cl_cred.cr_uid;
-        acred.gid = clp->cl_cred.cr_gid;
-        acred.group_info = clp->cl_cred.cr_group_info;
+	acred = dup_cred(&init_cred);
+	if (!acred)
+		return ERR_PTR(-ENOMEM);
+        change_fsuid(acred, clp->cl_cred.cr_uid);
+        change_fsgid(acred, clp->cl_cred.cr_gid);
+        change_groups(acred, clp->cl_cred.cr_group_info);
 
         dprintk("NFSD:     looking up %s cred\n",
                 clnt->cl_auth->au_ops->au_name);
-        ret = rpcauth_lookup_credcache(clnt->cl_auth, &acred, taskflags);
-        put_group_info(clp->cl_cred.cr_group_info);
+        ret = rpcauth_lookup_credcache(clnt->cl_auth, acred, taskflags);
+	put_cred(acred);
         return ret;
 }
 
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index ebd03cc..4935871 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -53,20 +53,26 @@
 static struct nameidata rec_dir;
 static int rec_dir_init = 0;
 
-static void
-nfs4_save_user(uid_t *saveuid, gid_t *savegid)
+static struct cred nfs4recover_cred = {
+	.usage	= ATOMIC_INIT(1),
+	.uid	= 0,
+	.gid	= 0,
+};
+
+static struct cred *
+nfs4_save_user(void)
 {
-	*saveuid = current->fsuid;
-	*savegid = current->fsgid;
-	current->fsuid = 0;
-	current->fsgid = 0;
+	/* swap in the recovery creds without adjusting the usage count on
+	 * either */
+	return __set_current_cred(&nfs4recover_cred);
 }
 
 static void
-nfs4_reset_user(uid_t saveuid, gid_t savegid)
+nfs4_reset_user(struct cred *orig_cred)
 {
-	current->fsuid = saveuid;
-	current->fsgid = savegid;
+	/* swap back the original creds without adjusting the usage count on
+	 * either */
+	__set_current_cred(orig_cred);
 }
 
 static void
@@ -132,8 +138,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
 {
 	char *dname = clp->cl_recdir;
 	struct dentry *dentry;
-	uid_t uid;
-	gid_t gid;
+	struct cred *orig_cred;
 	int status;
 
 	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
@@ -141,7 +146,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
 	if (!rec_dir_init || clp->cl_firststate)
 		return 0;
 
-	nfs4_save_user(&uid, &gid);
+	orig_cred = nfs4_save_user();
 
 	/* lock the parent */
 	mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
@@ -165,7 +170,7 @@ out_unlock:
 		clp->cl_firststate = 1;
 		nfsd4_sync_rec_dir();
 	}
-	nfs4_reset_user(uid, gid);
+	nfs4_reset_user(orig_cred);
 	dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
 	return status;
 }
@@ -214,14 +219,13 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
 	};
 	struct list_head *dentries = &dla.dentries;
 	struct dentry_list *child;
-	uid_t uid;
-	gid_t gid;
+	struct cred *orig_cred;
 	int status;
 
 	if (!rec_dir_init)
 		return 0;
 
-	nfs4_save_user(&uid, &gid);
+	orig_cred = nfs4_save_user();
 
 	filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
 	status = PTR_ERR(filp);
@@ -246,7 +250,7 @@ out:
 		dput(child->dentry);
 		kfree(child);
 	}
-	nfs4_reset_user(uid, gid);
+	nfs4_reset_user(orig_cred);
 	return status;
 }
 
@@ -308,17 +312,16 @@ out:
 void
 nfsd4_remove_clid_dir(struct nfs4_client *clp)
 {
-	uid_t uid;
-	gid_t gid;
+	struct cred *orig_cred;
 	int status;
 
 	if (!rec_dir_init || !clp->cl_firststate)
 		return;
 
 	clp->cl_firststate = 0;
-	nfs4_save_user(&uid, &gid);
+	orig_cred = nfs4_save_user();
 	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
-	nfs4_reset_user(uid, gid);
+	nfs4_reset_user(orig_cred);
 	if (status == 0)
 		nfsd4_sync_rec_dir();
 	if (status)
@@ -389,16 +392,15 @@ nfsd4_recdir_load(void) {
 void
 nfsd4_init_recdir(char *rec_dirname)
 {
-	uid_t			uid = 0;
-	gid_t			gid = 0;
-	int 			status;
+	struct cred *orig_cred;
+	int status;
 
 	printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
 			rec_dirname);
 
 	BUG_ON(rec_dir_init);
 
-	nfs4_save_user(&uid, &gid);
+	orig_cred = nfs4_save_user();
 
 	status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
 			&rec_dir);
@@ -408,7 +410,7 @@ nfsd4_init_recdir(char *rec_dirname)
 
 	if (!status)
 		rec_dir_init = 1;
-	nfs4_reset_user(uid, gid);
+	nfs4_reset_user(orig_cred);
 }
 
 void
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7867151..6452ca1 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1833,7 +1833,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
 		IS_APPEND(inode)?	" append" : "",
 		IS_RDONLY(inode)?	" ro" : "");
 	dprintk("      owner %d/%d user %d/%d\n",
-		inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
+		inode->i_uid, inode->i_gid, current->cred->uid, current->cred->gid);
 #endif
 
 	/* Normally we reject any write/sattr etc access on a read-only file
@@ -1875,7 +1875,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
 	 * with NFSv3.
 	 */
 	if ((acc & MAY_OWNER_OVERRIDE) &&
-	    inode->i_uid == current->fsuid)
+	    inode->i_uid == current->cred->uid)
 		return 0;
 
 	err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 7418dc8..708c87a 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -329,8 +329,8 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
 		ip = DLMFS_I(inode);
 
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current->cred->uid;
+		inode->i_gid = current->cred->gid;
 		inode->i_blocks = 0;
 		inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -355,8 +355,8 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
 		return NULL;
 
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = current->cred->gid;
 	inode->i_blocks = 0;
 	inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 701e6d0..f1c81e9 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -542,13 +542,13 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
 	fe->i_blkno = cpu_to_le64(fe_blkno);
 	fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
 	fe->i_suballoc_slot = cpu_to_le16(osb->slot_num);
-	fe->i_uid = cpu_to_le32(current->fsuid);
+	fe->i_uid = cpu_to_le32(current->cred->uid);
 	if (dir->i_mode & S_ISGID) {
 		fe->i_gid = cpu_to_le32(dir->i_gid);
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		fe->i_gid = cpu_to_le32(current->fsgid);
+		fe->i_gid = cpu_to_le32(current->cred->gid);
 	fe->i_mode = cpu_to_le16(mode);
 	if (S_ISCHR(mode) || S_ISBLK(mode))
 		fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
diff --git a/fs/open.c b/fs/open.c
index 1d9e5e9..c383efe 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -421,19 +421,26 @@ out:
 asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 {
 	struct nameidata nd;
-	int old_fsuid, old_fsgid;
 	kernel_cap_t old_cap;
+	struct cred *cred;
 	int res;
 
 	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
 		return -EINVAL;
 
-	old_fsuid = current->fsuid;
-	old_fsgid = current->fsgid;
 	old_cap = current->cap_effective;
 
-	current->fsuid = current->uid;
-	current->fsgid = current->gid;
+	if (current->cred->uid != current->uid ||
+	    current->cred->gid != current->gid) {
+		cred = dup_cred(current->cred);
+		if (!cred)
+			return -ENOMEM;
+
+		change_fsuid(cred, current->uid);
+		change_fsgid(cred, current->gid);
+	} else {
+		cred = get_current_cred();
+	}
 
 	/*
 	 * Clear the capabilities if we switch to a non-root user
@@ -448,6 +455,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 	else
 		current->cap_effective = current->cap_permitted;
 
+	cred = __set_current_cred(cred);
 	res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
 	if (res)
 		goto out;
@@ -464,8 +472,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 out_path_release:
 	path_release(&nd);
 out:
-	current->fsuid = old_fsuid;
-	current->fsgid = old_fsgid;
+	set_current_cred(cred);
 	current->cap_effective = old_cap;
 
 	return res;
diff --git a/fs/pipe.c b/fs/pipe.c
index 6b3d91a..5143262 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -939,8 +939,8 @@ static struct inode * get_pipe_inode(void)
 	 */
 	inode->i_state = I_DIRTY;
 	inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = current->cred->gid;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
 	return inode;
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index aec931e..b36c79f 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -217,11 +217,11 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
                 switch(pa->e_tag) {
                         case ACL_USER_OBJ:
 				/* (May have been checked already) */
-                                if (inode->i_uid == current->fsuid)
+				if (inode->i_uid == current->cred->uid)
                                         goto check_perm;
                                 break;
                         case ACL_USER:
-                                if (pa->e_id == current->fsuid)
+				if (pa->e_id == current->cred->uid)
                                         goto mask;
 				break;
                         case ACL_GROUP_OBJ:
diff --git a/fs/proc/array.c b/fs/proc/array.c
index ee4814d..dc2f83a 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -159,10 +159,12 @@ static inline const char *get_task_state(struct task_struct *tsk)
 static inline char *task_state(struct task_struct *p, char *buffer)
 {
 	struct group_info *group_info;
+	struct cred *cred;
 	int g;
 	struct fdtable *fdt = NULL;
 
 	rcu_read_lock();
+	cred = get_task_cred(p);
 	buffer += sprintf(buffer,
 		"State:\t%s\n"
 		"Tgid:\t%d\n"
@@ -175,8 +177,8 @@ static inline char *task_state(struct task_struct *p, char *buffer)
 		p->tgid, p->pid,
 		pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
 		pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
-		p->uid, p->euid, p->suid, p->fsuid,
-		p->gid, p->egid, p->sgid, p->fsgid);
+		p->uid, p->euid, p->suid, cred->uid,
+		p->gid, p->egid, p->sgid, cred->gid);
 
 	task_lock(p);
 	if (p->files)
@@ -186,14 +188,12 @@ static inline char *task_state(struct task_struct *p, char *buffer)
 		"Groups:\t",
 		fdt ? fdt->max_fds : 0);
 	rcu_read_unlock();
-
-	group_info = p->group_info;
-	get_group_info(group_info);
 	task_unlock(p);
 
+	group_info = cred->group_info;
 	for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
 		buffer += sprintf(buffer, "%d ", GROUP_AT(group_info, g));
-	put_group_info(group_info);
+	put_cred(cred);
 
 	buffer += sprintf(buffer, "\n");
 	return buffer;
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index ef2b46d..fe3642a 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -55,8 +55,8 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
 
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current->cred->uid;
+		inode->i_gid = current->cred->gid;
 		inode->i_blocks = 0;
 		inode->i_mapping->a_ops = &ramfs_aops;
 		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index b378eea..f5fbd5f 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -582,7 +582,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
 	/* the quota init calls have to know who to charge the quota to, so
 	 ** we have to set uid and gid here
 	 */
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	inode->i_mode = mode;
 	/* Make inode invalid - just in case we are going to drop it before
 	 * the initialization happens */
@@ -593,7 +593,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
 		if (S_ISDIR(mode))
 			inode->i_mode |= S_ISGID;
 	} else {
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current->cred->gid;
 	}
 	DQUOT_INIT(inode);
 	return 0;
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index 115ab0d..bbde666 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -165,9 +165,9 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current->cred->gid;
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	inode->i_ino = fs16_to_cpu(sbi, ino);
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	inode->i_blocks = 0;
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 636d8f6..875fde7 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -105,13 +105,13 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
 		mark_buffer_dirty(UDF_SB_LVIDBH(sb));
 	}
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	if (dir->i_mode & S_ISGID) {
 		inode->i_gid = dir->i_gid;
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else {
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current->cred->gid;
 	}
 
 	UDF_I_LOCATION(inode).logicalBlockNum = block;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index bec96a6..acb3570 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -636,7 +636,7 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
 	if (!inode)
 		goto out;
 
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	init_special_inode(inode, mode, rdev);
 	if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
 		inode->i_nlink--;
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index c28a8b6..f0fc61d 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -303,13 +303,13 @@ cg_found:
 
 	inode->i_ino = cg * uspi->s_ipg + bit;
 	inode->i_mode = mode;
-	inode->i_uid = current->fsuid;
+	inode->i_uid = current->cred->uid;
 	if (dir->i_mode & S_ISGID) {
 		inode->i_gid = dir->i_gid;
 		if (S_ISDIR(mode))
 			inode->i_mode |= S_ISGID;
 	} else
-		inode->i_gid = current->fsgid;
+		inode->i_gid = current->cred->gid;
 
 	inode->i_blocks = 0;
 	inode->i_generation = 0;
diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h
index e7f3da6..957bbe3 100644
--- a/fs/xfs/linux-2.6/xfs_cred.h
+++ b/fs/xfs/linux-2.6/xfs_cred.h
@@ -23,9 +23,7 @@
 /*
  * Credentials
  */
-typedef struct cred {
-	/* EMPTY */
-} cred_t;
+typedef struct cred cred_t;
 
 extern struct cred *sys_cred;
 
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 330c4ba..73ac671 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -127,8 +127,8 @@
 
 #define current_cpu()		(raw_smp_processor_id())
 #define current_pid()		(current->pid)
-#define current_fsuid(cred)	(current->fsuid)
-#define current_fsgid(cred)	(current->fsgid)
+#define current_fsuid(_cred)	(current->cred->uid)
+#define current_fsgid(_cred)	(current->cred->gid)
 #define current_test_flags(f)	(current->flags & (f))
 #define current_set_flags_nested(sp, f)		\
 		(*(sp) = current->flags, current->flags |= (f))
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 4ca4beb..a460508 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -383,7 +383,7 @@ xfs_acl_allow_set(
 	error = bhv_vop_getattr(vp, &va, 0, NULL);
 	if (error)
 		return error;
-	if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
+	if (va.va_uid != current->cred->uid && !capable(CAP_FOWNER))
 		return EPERM;
 	return error;
 }
@@ -457,13 +457,13 @@ xfs_acl_access(
 		switch (fap->acl_entry[i].ae_tag) {
 		case ACL_USER_OBJ:
 			seen_userobj = 1;
-			if (fuid != current->fsuid)
+			if (fuid != current->cred->uid)
 				continue;
 			matched.ae_tag = ACL_USER_OBJ;
 			matched.ae_perm = allows;
 			break;
 		case ACL_USER:
-			if (fap->acl_entry[i].ae_id != current->fsuid)
+			if (fap->acl_entry[i].ae_id != current->cred->uid)
 				continue;
 			matched.ae_tag = ACL_USER;
 			matched.ae_perm = allows;
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 91c8c07..f20f057 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -39,6 +39,7 @@ struct linux_binprm{
 	int e_uid, e_gid;
 	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
 	void *security;
+	struct cred *cred;
 	int argc, envc;
 	char * filename;	/* Name of binary as seen by procps */
 	char * interp;		/* Name of the binary really executed. Most
diff --git a/include/linux/cred.h b/include/linux/cred.h
new file mode 100644
index 0000000..6ec0132
--- /dev/null
+++ b/include/linux/cred.h
@@ -0,0 +1,163 @@
+/* Credentials management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_CRED_H
+#define _LINUX_CRED_H
+
+#include <linux/rcupdate.h>
+
+#ifdef __KERNEL__
+
+/*
+ * credentials record
+ * - COW semantics apply
+ */
+struct cred {
+	atomic_t		usage;
+	uid_t			uid;		/* fsuid as was */
+	gid_t			gid;		/* fsgid as was */
+	struct rcu_head		exterminate;	/* cred destroyer */
+	struct group_info	*group_info;
+};
+
+extern struct cred init_cred;
+
+struct inode;
+
+extern struct cred *dup_cred(const struct cred *);
+extern void put_cred(struct cred *);
+extern void change_fsuid(struct cred *, uid_t);
+extern void change_fsgid(struct cred *, gid_t);
+extern void change_groups(struct cred *, struct group_info *);
+
+/**
+ * get_cred - Get an extra reference on a credentials record
+ * @cred: The credentials record to reference
+ *
+ * Get an extra reference on a credentials record.  This must be released by
+ * calling put_cred().
+ */
+static inline struct cred *get_cred(struct cred *cred)
+{
+	atomic_inc(&cred->usage);
+	return cred;
+}
+
+/**
+ * get_current_cred - Get an extra reference on the current's credentials record
+ *
+ * Get an extra reference on the credentials record attached to the current
+ * task.  This must be released by calling put_cred().
+ */
+#define get_current_cred() \
+	({ get_cred(current->cred); })
+
+/**
+ * task_cred - Access the credentials of another task
+ * @tsk: The task to access
+ *
+ * Get a pointer to the credentials record of the given task.  The caller must
+ * have done rcu_read_lock() first.  The credentials record is can only be
+ * accessed as long as the RCU readlock is held by the caller.  If the
+ * credentials are required for longer, then a reference should be obtained on
+ * the cred struct.
+ *
+ * This is not required for the a task to access its own credentials.  Tasks
+ * may not alter the credentials of other tasks.
+ */
+#define task_cred(tsk) \
+	({ rcu_dereference((tsk)->cred); })
+
+/**
+ * __task_fsuid - Get the FSUID of another task (caller holds RCU read lock)
+ * task_fsuid - Get the FSUID of another task
+ * @tsk: The task to access
+ *
+ * Get the active filesystem access UID of another task.  __task_fsuid()
+ * requires the caller to hold the RCU read lock, task_fsuid() does not.
+ */
+#define __task_fsuid(tsk)	(task_cred(tsk)->uid)
+#define task_fsuid(tsk)				\
+({						\
+	uid_t ____x;				\
+	rcu_read_lock();			\
+	____x = __task_fsuid(tsk);		\
+	rcu_read_unlock();			\
+	____x;					\
+})
+
+/**
+ * __task_fsgid - Get the FSGID of another task (caller holds RCU read lock)
+ * task_fsgid - Get the FSGID of another task
+ * @tsk: The task to access
+ *
+ * Get the active filesystem access GID of another task.  __task_fsgid()
+ * requires the caller to hold the RCU read lock, task_fsgid() does not.
+ */
+#define __task_fsgid(tsk)	(task_cred(tsk)->gid)
+#define task_fsgid(tsk)				\
+({						\
+	gid_t ____x;				\
+	rcu_read_lock();			\
+	____x = __task_fsgid(tsk);		\
+	rcu_read_unlock();			\
+	____x;					\
+})
+
+/**
+ * get_task_cred - Get an extra reference on a credentials record of a task
+ * @tsk: The task to look in
+ *
+ * Get an extra reference on a credentials record of the given task and return
+ * a pointer to it.  This must be released by calling put_cred().  The caller
+ * must have done rcu_read_lock() first.
+ */
+#define get_task_cred(tsk) \
+	({ get_cred(task_cred((tsk))); })
+
+/**
+ * __set_current_cred - Swap the current credentials on the current task
+ * @cred: The revised credentials
+ *
+ * Exchange the credential record of the current task for an updated one.  This
+ * transfers a reference on the passed credential to the current task_struct,
+ * so the caller may need to get an extra reference first.  The old credentials
+ * are returned and must be disposed of appropriately.
+ *
+ * Write-locking is achieved by the fact that a thread's credentials may only
+ * be changed by that thread itself, so no explicit locking is required.
+ */
+#define __set_current_cred(CRED)			\
+({							\
+	struct cred *___old = current->cred;		\
+	rcu_assign_pointer(current->cred, (CRED));	\
+	___old;						\
+})
+
+/**
+ * set_current_cred - Change the current credentials on the current task
+ * @cred: The revised credentials
+ *
+ * Exchange the credential record of the current task for an updated one.  This
+ * transfers a reference on the passed credential to the current task_struct,
+ * so the caller may need to get an extra reference first.  The old credentials
+ * are released.
+ *
+ * Write-locking is achieved by the fact that a thread's credentials may only
+ * be changed by that thread itself, so no explicit locking is required.
+ */
+#define set_current_cred(CRED)				\
+do {							\
+	put_cred(__set_current_cred(CRED));		\
+} while (0)
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_CRED_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 42aabc1..1be33c8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -285,6 +285,7 @@ extern int dir_notify_enable;
 #include <linux/mutex.h>
 #include <linux/sysctl.h>
 #include <linux/capability.h>
+#include <linux/cred.h>
 
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
@@ -736,7 +737,7 @@ struct file {
 	mode_t			f_mode;
 	loff_t			f_pos;
 	struct fown_struct	f_owner;
-	unsigned int		f_uid, f_gid;
+	struct cred		*f_cred;
 	struct file_ra_state	f_ra;
 
 	unsigned long		f_version;
@@ -999,7 +1000,7 @@ enum {
 #define has_fs_excl() atomic_read(&current->fs_excl)
 
 #define is_owner_or_cap(inode)	\
-	((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER))
+	((current->cred->uid == (inode)->i_uid) || capable(CAP_FOWNER))
 
 /* not quite ready to be deprecated, but... */
 extern void lock_super(struct super_block *);
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 513bc3e..2ff9d8e 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -91,8 +91,6 @@ extern struct nsproxy init_nsproxy;
 	.signalfd_wqh	= __WAIT_QUEUE_HEAD_INITIALIZER(sighand.signalfd_wqh),	\
 }
 
-extern struct group_info init_groups;
-
 #define INIT_STRUCT_PID {						\
 	.count 		= ATOMIC_INIT(1),				\
 	.nr		= 0, 						\
@@ -144,7 +142,7 @@ extern struct group_info init_groups;
 	.children	= LIST_HEAD_INIT(tsk.children),			\
 	.sibling	= LIST_HEAD_INIT(tsk.sibling),			\
 	.group_leader	= &tsk,						\
-	.group_info	= &init_groups,					\
+	.cred		= &init_cred,					\
 	.cap_effective	= CAP_INIT_EFF_SET,				\
 	.cap_inheritable = CAP_INIT_INH_SET,				\
 	.cap_permitted	= CAP_FULL_SET,					\
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 833f7dc..fee8b1e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -80,6 +80,7 @@ struct sched_param {
 #include <linux/rcupdate.h>
 #include <linux/futex.h>
 #include <linux/rtmutex.h>
+#include <linux/cred.h>
 
 #include <linux/time.h>
 #include <linux/param.h>
@@ -1034,9 +1035,9 @@ struct task_struct {
 	struct list_head cpu_timers[3];
 
 /* process credentials */
-	uid_t uid,euid,suid,fsuid;
-	gid_t gid,egid,sgid,fsgid;
-	struct group_info *group_info;
+	struct cred *cred;
+	uid_t uid,euid,suid;
+	gid_t gid,egid,sgid;
 	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
 	unsigned keep_capabilities:1;
 	struct user_struct *user;
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 7a69ca3..8f97f9a 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -21,13 +21,6 @@
 /* size of the nodename buffer */
 #define UNX_MAXNODENAME	32
 
-/* Work around the lack of a VFS credential */
-struct auth_cred {
-	uid_t	uid;
-	gid_t	gid;
-	struct group_info *group_info;
-};
-
 /*
  * Client user credentials
  */
@@ -94,6 +87,7 @@ struct rpc_auth {
 /*
  * Client authentication ops
  */
+struct cred;
 struct rpc_authops {
 	struct module		*owner;
 	rpc_authflavor_t	au_flavor;	/* flavor (RPC_AUTH_*) */
@@ -103,8 +97,8 @@ struct rpc_authops {
 	struct rpc_auth *	(*create)(struct rpc_clnt *, rpc_authflavor_t);
 	void			(*destroy)(struct rpc_auth *);
 
-	struct rpc_cred *	(*lookup_cred)(struct rpc_auth *, struct auth_cred *, int);
-	struct rpc_cred *	(*crcreate)(struct rpc_auth*, struct auth_cred *, int);
+	struct rpc_cred *	(*lookup_cred)(struct rpc_auth *, struct cred *, int);
+	struct rpc_cred *	(*crcreate)(struct rpc_auth*, struct cred *, int);
 };
 
 struct rpc_credops {
@@ -112,7 +106,7 @@ struct rpc_credops {
 	int			(*cr_init)(struct rpc_auth *, struct rpc_cred *);
 	void			(*crdestroy)(struct rpc_cred *);
 
-	int			(*crmatch)(struct auth_cred *, struct rpc_cred *, int);
+	int			(*crmatch)(struct cred *, struct rpc_cred *, int);
 	__be32 *		(*crmarshal)(struct rpc_task *, __be32 *);
 	int			(*crrefresh)(struct rpc_task *);
 	__be32 *		(*crvalidate)(struct rpc_task *, __be32 *);
@@ -133,8 +127,8 @@ int			rpcauth_register(const struct rpc_authops *);
 int			rpcauth_unregister(const struct rpc_authops *);
 struct rpc_auth *	rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
 void			rpcauth_release(struct rpc_auth *);
-struct rpc_cred *	rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
-void			rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
+struct rpc_cred *	rpcauth_lookup_credcache(struct rpc_auth *, struct cred *, int);
+void			rpcauth_init_cred(struct rpc_cred *, const struct cred *, struct rpc_auth *, const struct rpc_credops *);
 struct rpc_cred *	rpcauth_lookupcred(struct rpc_auth *, int);
 struct rpc_cred *	rpcauth_bindcred(struct rpc_task *);
 void			rpcauth_holdcred(struct rpc_task *);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 24df334..d3d97ab 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -113,8 +113,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
 	inode = new_inode(sb);
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current->cred->uid;
+		inode->i_gid = current->cred->gid;
 		inode->i_blocks = 0;
 		inode->i_mtime = inode->i_ctime = inode->i_atime =
 				CURRENT_TIME;
diff --git a/kernel/Makefile b/kernel/Makefile
index 2a99983..1f1f17b 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -9,7 +9,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
 	    rcupdate.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o die_notifier.o \
-	    utsname.o
+	    utsname.o cred.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-y += time/
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 04f3ffb..282e041 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -303,7 +303,8 @@ static int audit_filter_rules(struct task_struct *tsk,
 			result = audit_comparator(tsk->suid, f->op, f->val);
 			break;
 		case AUDIT_FSUID:
-			result = audit_comparator(tsk->fsuid, f->op, f->val);
+			result = audit_comparator(task_fsuid(tsk), f->op,
+						  f->val);
 			break;
 		case AUDIT_GID:
 			result = audit_comparator(tsk->gid, f->op, f->val);
@@ -315,7 +316,8 @@ static int audit_filter_rules(struct task_struct *tsk,
 			result = audit_comparator(tsk->sgid, f->op, f->val);
 			break;
 		case AUDIT_FSGID:
-			result = audit_comparator(tsk->fsgid, f->op, f->val);
+			result = audit_comparator(task_fsgid(tsk), f->op,
+						  f->val);
 			break;
 		case AUDIT_PERS:
 			result = audit_comparator(tsk->personality, f->op, f->val);
@@ -885,12 +887,15 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 	context->gid = tsk->gid;
 	context->euid = tsk->euid;
 	context->suid = tsk->suid;
-	context->fsuid = tsk->fsuid;
 	context->egid = tsk->egid;
 	context->sgid = tsk->sgid;
-	context->fsgid = tsk->fsgid;
 	context->personality = tsk->personality;
 
+	rcu_read_lock();
+	context->fsuid = __task_fsuid(tsk);
+	context->fsgid = __task_fsgid(tsk);
+	rcu_read_unlock();
+
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
 	if (!ab)
 		return;		/* audit_panic has been called */
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 57e6448..215eaf8 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -286,8 +286,8 @@ static struct inode *cpuset_new_inode(mode_t mode)
 
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current->cred->uid;
+		inode->i_gid = current->cred->gid;
 		inode->i_blocks = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
diff --git a/kernel/cred.c b/kernel/cred.c
new file mode 100644
index 0000000..35a2d43
--- /dev/null
+++ b/kernel/cred.c
@@ -0,0 +1,123 @@
+/* Credential caching/management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/security.h>
+#include <linux/key.h>
+#include "kernel-int.h"
+
+/*
+ * the credentials for the init task
+ * - the usage count is elevated so that this is never freed
+ */
+struct cred init_cred = {
+	.usage		= ATOMIC_INIT(2),
+	.group_info	= &init_groups,
+};
+
+EXPORT_SYMBOL(init_cred);
+
+/**
+ * dup_cred - Duplicate a credentials structure
+ * @pcred: The credentials record to duplicate
+ *
+ * Duplicate and return a credentials structure so that the copy can be
+ * modified.  NULL is returned if there is insufficient memory to make the
+ * copy.
+ */
+struct cred *dup_cred(const struct cred *pcred)
+{
+	struct cred *cred;
+
+	cred = kmalloc(sizeof(struct cred), GFP_KERNEL);
+	if (likely(cred)) {
+		*cred = *pcred;
+		atomic_set(&cred->usage, 1);
+		get_group_info(cred->group_info);
+	}
+	return cred;
+}
+
+EXPORT_SYMBOL(dup_cred);
+
+/*
+ * RCU-based credentials destroyer
+ */
+static void put_cred_rcu(struct rcu_head *rcu)
+{
+	struct cred *cred = container_of(rcu, struct cred, exterminate);
+
+	put_group_info(cred->group_info);
+	kfree(cred);
+}
+
+/**
+ * put_cred - Release a reference to a credentials record
+ * cred: The credentials record to release
+ *
+ * Release a reference to a credentials record.  When the last reference is
+ * released, the record will be deleted with due care for RCU accesses still
+ * ongoing.
+ */
+void put_cred(struct cred *cred)
+{
+	if (atomic_dec_and_test(&cred->usage))
+		call_rcu(&cred->exterminate, put_cred_rcu);
+}
+
+EXPORT_SYMBOL(put_cred);
+
+/**
+ * change_fsuid - Change the VFS applicable UID in a new credential record
+ * @cred: The credential record to alter
+ * @uid: The user ID to set
+ *
+ * Change the VFS access and creation user ID in a new credential record.
+ */
+void change_fsuid(struct cred *cred, uid_t uid)
+{
+	cred->uid = uid;
+}
+
+EXPORT_SYMBOL(change_fsuid);
+
+/**
+ * change_fsgid - Change the VFS applicable GID in a new credential record
+ * @cred: The credential record to alter
+ * @gid: The group ID to set
+ *
+ * Change the VFS access and creation group ID in a new credential record.
+ */
+void change_fsgid(struct cred *cred, gid_t gid)
+{
+	cred->gid = gid;
+}
+
+EXPORT_SYMBOL(change_fsgid);
+
+/**
+ * change_groups - Change the supplementary groups in a new credential record
+ * @cred: The credential record to alter
+ * @group_info: The supplementary groups to attach
+ *
+ * Change the VFS access supplementary group list in a new credential record.
+ */
+void change_groups(struct cred *cred, struct group_info *group_info)
+{
+	struct group_info *old = cred->group_info;
+
+	get_group_info(group_info);
+	cred->group_info = group_info;
+	put_group_info(old);
+}
+
+EXPORT_SYMBOL(change_groups);
diff --git a/kernel/exit.c b/kernel/exit.c
index 993369e..c366ae7 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -288,6 +288,7 @@ static void reparent_to_kthreadd(void)
 	/* cpus_allowed? */
 	/* rt_priority? */
 	/* signals? */
+	set_current_cred(get_cred(&init_cred));
 	security_task_reparent_to_init(current);
 	memcpy(current->signal->rlim, init_task.signal->rlim,
 	       sizeof(current->signal->rlim));
diff --git a/kernel/fork.c b/kernel/fork.c
index 5e67f90..b1f8899 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -121,7 +121,7 @@ void __put_task_struct(struct task_struct *tsk)
 
 	security_task_free(tsk);
 	free_uid(tsk->user);
-	put_group_info(tsk->group_info);
+	put_cred(tsk->cred);
 	delayacct_tsk_free(tsk);
 
 	if (!profile_handoff_task(tsk))
@@ -949,6 +949,16 @@ static inline void rt_mutex_init_task(struct task_struct *p)
 }
 
 /*
+ * Copy a set of credentials
+ * - share it unless it contains something we can't copy
+ */
+static int copy_cred(struct task_struct *p)
+{
+	atomic_inc(&p->cred->usage);
+	return 0;
+}
+
+/*
  * This creates a new process as a copy of the old one,
  * but does not actually start it yet.
  *
@@ -1010,7 +1020,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 
 	atomic_inc(&p->user->__count);
 	atomic_inc(&p->user->processes);
-	get_group_info(p->group_info);
+	if ((retval = copy_cred(p) < 0))
+		goto bad_fork_cleanup_count;
 
 	/*
 	 * If multiple threads are within copy_process(), then this check
@@ -1018,10 +1029,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	 * to stop root fork bombs.
 	 */
 	if (nr_threads >= max_threads)
-		goto bad_fork_cleanup_count;
+		goto bad_fork_cleanup_cred;
 
 	if (!try_module_get(task_thread_info(p)->exec_domain->module))
-		goto bad_fork_cleanup_count;
+		goto bad_fork_cleanup_cred;
 
 	if (p->binfmt && !try_module_get(p->binfmt->module))
 		goto bad_fork_cleanup_put_domain;
@@ -1309,8 +1320,9 @@ bad_fork_cleanup_delays_binfmt:
 		module_put(p->binfmt->module);
 bad_fork_cleanup_put_domain:
 	module_put(task_thread_info(p)->exec_domain->module);
+bad_fork_cleanup_cred:
+	put_cred(p->cred);
 bad_fork_cleanup_count:
-	put_group_info(p->group_info);
 	atomic_dec(&p->user->processes);
 	free_uid(p->user);
 bad_fork_free:
diff --git a/kernel/kernel-int.h b/kernel/kernel-int.h
new file mode 100644
index 0000000..16c68e3
--- /dev/null
+++ b/kernel/kernel-int.h
@@ -0,0 +1,15 @@
+/* kernel/ internal definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+/*
+ * sys.c
+ */
+extern struct group_info init_groups;
diff --git a/kernel/sys.c b/kernel/sys.c
index 8ae2e63..ff25530 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -42,6 +42,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/unistd.h>
+#include "kernel-int.h"
 
 #ifndef SET_UNALIGN_CTL
 # define SET_UNALIGN_CTL(a,b)	(-EINVAL)
@@ -1013,6 +1014,7 @@ void ctrl_alt_del(void)
  */
 asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
 {
+	struct cred *cred;
 	int old_rgid = current->gid;
 	int old_egid = current->egid;
 	int new_rgid = old_rgid;
@@ -1040,6 +1042,11 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
 		else
 			return -EPERM;
 	}
+
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
+
 	if (new_egid != old_egid) {
 		set_dumpable(current->mm, suid_dumpable);
 		smp_wmb();
@@ -1047,9 +1054,10 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
 	if (rgid != (gid_t) -1 ||
 	    (egid != (gid_t) -1 && egid != old_rgid))
 		current->sgid = new_egid;
-	current->fsgid = new_egid;
 	current->egid = new_egid;
 	current->gid = new_rgid;
+	change_fsgid(cred, new_egid);
+	set_current_cred(cred);
 	key_fsgid_changed(current);
 	proc_id_connector(current, PROC_EVENT_GID);
 	return 0;
@@ -1062,6 +1070,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
  */
 asmlinkage long sys_setgid(gid_t gid)
 {
+	struct cred *cred;
 	int old_egid = current->egid;
 	int retval;
 
@@ -1069,22 +1078,29 @@ asmlinkage long sys_setgid(gid_t gid)
 	if (retval)
 		return retval;
 
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
+
 	if (capable(CAP_SETGID)) {
 		if (old_egid != gid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->gid = current->egid = current->sgid = current->fsgid = gid;
+		current->gid = current->egid = current->sgid = gid;
 	} else if ((gid == current->gid) || (gid == current->sgid)) {
 		if (old_egid != gid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->egid = current->fsgid = gid;
-	}
-	else
+		current->egid = gid;
+	} else {
+		put_cred(cred);
 		return -EPERM;
+	}
 
+	change_fsgid(cred, gid);
+	set_current_cred(cred);
 	key_fsgid_changed(current);
 	proc_id_connector(current, PROC_EVENT_GID);
 	return 0;
@@ -1132,6 +1148,7 @@ static int set_user(uid_t new_ruid, int dumpclear)
  */
 asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 {
+	struct cred *cred;
 	int old_ruid, old_euid, old_suid, new_ruid, new_euid;
 	int retval;
 
@@ -1160,19 +1177,26 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 			return -EPERM;
 	}
 
-	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
+
+	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) {
+		put_cred(cred);
 		return -EAGAIN;
+	}
 
 	if (new_euid != old_euid) {
 		set_dumpable(current->mm, suid_dumpable);
 		smp_wmb();
 	}
-	current->fsuid = current->euid = new_euid;
+	current->euid = new_euid;
 	if (ruid != (uid_t) -1 ||
 	    (euid != (uid_t) -1 && euid != old_ruid))
 		current->suid = current->euid;
-	current->fsuid = current->euid;
 
+	change_fsuid(cred, new_euid);
+	set_current_cred(cred);
 	key_fsuid_changed(current);
 	proc_id_connector(current, PROC_EVENT_UID);
 
@@ -1194,6 +1218,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
  */
 asmlinkage long sys_setuid(uid_t uid)
 {
+	struct cred *cred;
 	int old_euid = current->euid;
 	int old_ruid, old_suid, new_suid;
 	int retval;
@@ -1202,24 +1227,33 @@ asmlinkage long sys_setuid(uid_t uid)
 	if (retval)
 		return retval;
 
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
+
 	old_ruid = current->uid;
 	old_suid = current->suid;
 	new_suid = old_suid;
 	
 	if (capable(CAP_SETUID)) {
-		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
+		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) {
+			put_cred(cred);
 			return -EAGAIN;
+		}
 		new_suid = uid;
-	} else if ((uid != current->uid) && (uid != new_suid))
+	} else if ((uid != current->uid) && (uid != new_suid)) {
+		put_cred(cred);
 		return -EPERM;
+	}
 
 	if (old_euid != uid) {
 		set_dumpable(current->mm, suid_dumpable);
 		smp_wmb();
 	}
-	current->fsuid = current->euid = uid;
+	current->euid = uid;
 	current->suid = new_suid;
-
+	change_fsuid(cred, uid);
+	set_current_cred(cred);
 	key_fsuid_changed(current);
 	proc_id_connector(current, PROC_EVENT_UID);
 
@@ -1233,6 +1267,7 @@ asmlinkage long sys_setuid(uid_t uid)
  */
 asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 {
+	struct cred *cred;
 	int old_ruid = current->uid;
 	int old_euid = current->euid;
 	int old_suid = current->suid;
@@ -1253,9 +1288,16 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 		    (suid != current->euid) && (suid != current->suid))
 			return -EPERM;
 	}
+
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
+
 	if (ruid != (uid_t) -1) {
-		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
+		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) {
+			put_cred(cred);
 			return -EAGAIN;
+		}
 	}
 	if (euid != (uid_t) -1) {
 		if (euid != current->euid) {
@@ -1264,10 +1306,10 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 		}
 		current->euid = euid;
 	}
-	current->fsuid = current->euid;
 	if (suid != (uid_t) -1)
 		current->suid = suid;
-
+	change_fsuid(cred, current->euid);
+	set_current_cred(cred);
 	key_fsuid_changed(current);
 	proc_id_connector(current, PROC_EVENT_UID);
 
@@ -1290,6 +1332,7 @@ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __us
  */
 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 {
+	struct cred *cred;
 	int retval;
 
 	retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
@@ -1307,6 +1350,11 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 		    (sgid != current->egid) && (sgid != current->sgid))
 			return -EPERM;
 	}
+
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
+
 	if (egid != (gid_t) -1) {
 		if (egid != current->egid) {
 			set_dumpable(current->mm, suid_dumpable);
@@ -1314,12 +1362,13 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 		}
 		current->egid = egid;
 	}
-	current->fsgid = current->egid;
 	if (rgid != (gid_t) -1)
 		current->gid = rgid;
 	if (sgid != (gid_t) -1)
 		current->sgid = sgid;
 
+	change_fsgid(cred, current->egid);
+	set_current_cred(cred);
 	key_fsgid_changed(current);
 	proc_id_connector(current, PROC_EVENT_GID);
 	return 0;
@@ -1345,23 +1394,31 @@ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __us
  */
 asmlinkage long sys_setfsuid(uid_t uid)
 {
+	struct cred *cred;
 	int old_fsuid;
 
-	old_fsuid = current->fsuid;
+	old_fsuid = current->cred->uid;
 	if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))
 		return old_fsuid;
 
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
+
 	if (uid == current->uid || uid == current->euid ||
-	    uid == current->suid || uid == current->fsuid || 
+	    uid == current->suid || uid == current->cred->uid ||
 	    capable(CAP_SETUID)) {
 		if (uid != old_fsuid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->fsuid = uid;
+		change_fsuid(cred, uid);
+		set_current_cred(cred);
+		key_fsuid_changed(current);
+	} else {
+		put_cred(cred);
 	}
 
-	key_fsuid_changed(current);
 	proc_id_connector(current, PROC_EVENT_UID);
 
 	security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
@@ -1374,22 +1431,30 @@ asmlinkage long sys_setfsuid(uid_t uid)
  */
 asmlinkage long sys_setfsgid(gid_t gid)
 {
+	struct cred *cred;
 	int old_fsgid;
 
-	old_fsgid = current->fsgid;
+	old_fsgid = current->cred->gid;
 	if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
 		return old_fsgid;
 
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
+
 	if (gid == current->gid || gid == current->egid ||
-	    gid == current->sgid || gid == current->fsgid || 
+	    gid == current->sgid || gid == current->cred->gid ||
 	    capable(CAP_SETGID)) {
 		if (gid != old_fsgid) {
 			set_dumpable(current->mm, suid_dumpable);
 			smp_wmb();
 		}
-		current->fsgid = gid;
+		change_fsgid(cred, gid);
+		set_current_cred(cred);
 		key_fsgid_changed(current);
 		proc_id_connector(current, PROC_EVENT_GID);
+	} else {
+		put_cred(cred);
 	}
 	return old_fsgid;
 }
@@ -1756,23 +1821,20 @@ int groups_search(struct group_info *group_info, gid_t grp)
 /* validate and set current->group_info */
 int set_current_groups(struct group_info *group_info)
 {
+	struct cred *cred;
 	int retval;
-	struct group_info *old_info;
 
 	retval = security_task_setgroups(group_info);
 	if (retval)
 		return retval;
 
-	groups_sort(group_info);
-	get_group_info(group_info);
-
-	task_lock(current);
-	old_info = current->group_info;
-	current->group_info = group_info;
-	task_unlock(current);
-
-	put_group_info(old_info);
+	cred = dup_cred(current->cred);
+	if (!cred)
+		return -ENOMEM;
 
+	groups_sort(group_info);
+	change_groups(cred, group_info);
+	set_current_cred(cred);
 	return 0;
 }
 
@@ -1780,24 +1842,24 @@ EXPORT_SYMBOL(set_current_groups);
 
 asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
 {
+	struct group_info *group_info = current->cred->group_info;
 	int i = 0;
 
 	/*
-	 *	SMP: Nobody else can change our grouplist. Thus we are
-	 *	safe.
+	 *	SMP: Nobody else can change our credentials.  Thus we are safe.
 	 */
 
 	if (gidsetsize < 0)
 		return -EINVAL;
 
 	/* no need to grab task_lock here; it cannot change */
-	i = current->group_info->ngroups;
+	i = group_info->ngroups;
 	if (gidsetsize) {
 		if (i > gidsetsize) {
 			i = -EINVAL;
 			goto out;
 		}
-		if (groups_to_user(grouplist, current->group_info)) {
+		if (groups_to_user(grouplist, group_info)) {
 			i = -EFAULT;
 			goto out;
 		}
@@ -1841,9 +1903,11 @@ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
  */
 int in_group_p(gid_t grp)
 {
+	struct cred *cred = current->cred;
 	int retval = 1;
-	if (grp != current->fsgid)
-		retval = groups_search(current->group_info, grp);
+
+	if (grp != cred->gid)
+		retval = groups_search(cred->group_info, grp);
 	return retval;
 }
 
@@ -1853,7 +1917,7 @@ int in_egroup_p(gid_t grp)
 {
 	int retval = 1;
 	if (grp != current->egid)
-		retval = groups_search(current->group_info, grp);
+		retval = groups_search(current->cred->group_info, grp);
 	return retval;
 }
 
diff --git a/kernel/uid16.c b/kernel/uid16.c
index dd308ba..5a8b95e 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -161,25 +161,24 @@ static int groups16_from_user(struct group_info *group_info,
 
 asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist)
 {
+	struct group_info *group_info = current->cred->group_info;
 	int i = 0;
 
 	if (gidsetsize < 0)
 		return -EINVAL;
 
-	get_group_info(current->group_info);
-	i = current->group_info->ngroups;
+	i = group_info->ngroups;
 	if (gidsetsize) {
 		if (i > gidsetsize) {
 			i = -EINVAL;
 			goto out;
 		}
-		if (groups16_to_user(grouplist, current->group_info)) {
+		if (groups16_to_user(grouplist, group_info)) {
 			i = -EFAULT;
 			goto out;
 		}
 	}
 out:
-	put_group_info(current->group_info);
 	return i;
 }
 
diff --git a/mm/shmem.c b/mm/shmem.c
index fcd19d3..e1fa1c3 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1394,8 +1394,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 	inode = new_inode(sb);
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
+		inode->i_uid = current->cred->uid;
+		inode->i_gid = current->cred->gid;
 		inode->i_blocks = 0;
 		inode->i_mapping->a_ops = &shmem_aops;
 		inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
@@ -2212,8 +2212,8 @@ static int shmem_fill_super(struct super_block *sb,
 	struct inode *inode;
 	struct dentry *root;
 	int mode   = S_IRWXUGO | S_ISVTX;
-	uid_t uid = current->fsuid;
-	gid_t gid = current->fsgid;
+	uid_t uid = current->cred->uid;
+	gid_t gid = current->cred->gid;
 	int err = -ENOMEM;
 	struct shmem_sb_info *sbinfo;
 	unsigned long blocks = 0;
diff --git a/net/9p/client.c b/net/9p/client.c
index cb17075..c47a7ae 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -935,7 +935,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 	fid->rdir_fpos = 0;
 	fid->rdir_pos = 0;
 	fid->rdir_fcall = NULL;
-	fid->uid = current->fsuid;
+	fid->uid = current->cred->uid;
 	fid->clnt = clnt;
 	fid->aux = NULL;
 
diff --git a/net/socket.c b/net/socket.c
index 379b3a3..dc40a5e 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -484,8 +484,8 @@ static struct socket *sock_alloc(void)
 	sock = SOCKET_I(inode);
 
 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
+	inode->i_uid = current->cred->uid;
+	inode->i_gid = current->cred->gid;
 
 	get_cpu_var(sockets_in_use)++;
 	put_cpu_var(sockets_in_use);
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 1ea2755..362a0de 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -267,7 +267,7 @@ rpcauth_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
  * Look up a process' credentials in the authentication cache
  */
 struct rpc_cred *
-rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
+rpcauth_lookup_credcache(struct rpc_auth *auth, struct cred *acred,
 		int flags)
 {
 	LIST_HEAD(free);
@@ -336,23 +336,13 @@ out:
 struct rpc_cred *
 rpcauth_lookupcred(struct rpc_auth *auth, int flags)
 {
-	struct auth_cred acred = {
-		.uid = current->fsuid,
-		.gid = current->fsgid,
-		.group_info = current->group_info,
-	};
-	struct rpc_cred *ret;
-
 	dprintk("RPC:       looking up %s cred\n",
 		auth->au_ops->au_name);
-	get_group_info(acred.group_info);
-	ret = auth->au_ops->lookup_cred(auth, &acred, flags);
-	put_group_info(acred.group_info);
-	return ret;
+	return auth->au_ops->lookup_cred(auth, current->cred, flags);
 }
 
 void
-rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+rpcauth_init_cred(struct rpc_cred *cred, const struct cred *acred,
 		  struct rpc_auth *auth, const struct rpc_credops *ops)
 {
 	INIT_HLIST_NODE(&cred->cr_hash);
@@ -372,25 +362,18 @@ struct rpc_cred *
 rpcauth_bindcred(struct rpc_task *task)
 {
 	struct rpc_auth *auth = task->tk_client->cl_auth;
-	struct auth_cred acred = {
-		.uid = current->fsuid,
-		.gid = current->fsgid,
-		.group_info = current->group_info,
-	};
 	struct rpc_cred *ret;
 	int flags = 0;
 
 	dprintk("RPC: %5u looking up %s cred\n",
 		task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
-	get_group_info(acred.group_info);
 	if (task->tk_flags & RPC_TASK_ROOTCREDS)
 		flags |= RPCAUTH_LOOKUP_ROOTCREDS;
-	ret = auth->au_ops->lookup_cred(auth, &acred, flags);
+	ret = auth->au_ops->lookup_cred(auth, current->cred, flags);
 	if (!IS_ERR(ret))
 		task->tk_msg.rpc_cred = ret;
 	else
 		task->tk_status = PTR_ERR(ret);
-	put_group_info(acred.group_info);
 	return ret;
 }
 
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 53995af..bad2698 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -793,13 +793,13 @@ gss_destroy_cred(struct rpc_cred *cred)
  * Lookup RPCSEC_GSS cred for the current process
  */
 static struct rpc_cred *
-gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+gss_lookup_cred(struct rpc_auth *auth, struct cred *acred, int flags)
 {
 	return rpcauth_lookup_credcache(auth, acred, flags);
 }
 
 static struct rpc_cred *
-gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+gss_create_cred(struct rpc_auth *auth, struct cred *acred, int flags)
 {
 	struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
 	struct gss_cred	*cred = NULL;
@@ -840,7 +840,7 @@ gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred)
 }
 
 static int
-gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
+gss_match(struct cred *acred, struct rpc_cred *rc, int flags)
 {
 	struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
 
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 537d0e8..c2fcefa 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -34,7 +34,7 @@ nul_destroy(struct rpc_auth *auth)
  * Lookup NULL creds for current process
  */
 static struct rpc_cred *
-nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+nul_lookup_cred(struct rpc_auth *auth, struct cred *acred, int flags)
 {
 	return get_rpccred(&null_cred);
 }
@@ -51,7 +51,7 @@ nul_destroy_cred(struct rpc_cred *cred)
  * Match cred handle against current process
  */
 static int
-nul_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags)
+nul_match(struct cred *acred, struct rpc_cred *cred, int taskflags)
 {
 	return 1;
 }
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 5ed91e5..f5ab6d7 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -51,13 +51,13 @@ unx_destroy(struct rpc_auth *auth)
  * Lookup AUTH_UNIX creds for current process
  */
 static struct rpc_cred *
-unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+unx_lookup_cred(struct rpc_auth *auth, struct cred *acred, int flags)
 {
 	return rpcauth_lookup_credcache(auth, acred, flags);
 }
 
 static struct rpc_cred *
-unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+unx_create_cred(struct rpc_auth *auth, struct cred *acred, int flags)
 {
 	struct unx_cred	*cred;
 	int		i;
@@ -115,7 +115,7 @@ unx_destroy_cred(struct rpc_cred *cred)
  * request root creds (e.g. for NFS swapping).
  */
 static int
-unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
+unx_match(struct cred *acred, struct rpc_cred *rcred, int flags)
 {
 	struct unx_cred	*cred = container_of(rcred, struct unx_cred, uc_base);
 	int		i;
diff --git a/security/commoncap.c b/security/commoncap.c
index 7520361..a39eae7 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -162,8 +162,8 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
 		}
 	}
 
-	current->suid = current->euid = current->fsuid = bprm->e_uid;
-	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+	current->suid = current->euid = current->cred->uid = bprm->e_uid;
+	current->sgid = current->egid = current->cred->gid = bprm->e_gid;
 
 	/* For init, we want to retain the capabilities set
 	 * in the init_task struct. Thus we skip the usual
@@ -280,11 +280,11 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
 			 */
 
 			if (!issecure (SECURE_NO_SETUID_FIXUP)) {
-				if (old_fsuid == 0 && current->fsuid != 0) {
+				if (old_fsuid == 0 && current->cred->uid != 0) {
 					cap_t (current->cap_effective) &=
 					    ~CAP_FS_MASK;
 				}
-				if (old_fsuid != 0 && current->fsuid == 0) {
+				if (old_fsuid != 0 && current->cred->uid == 0) {
 					cap_t (current->cap_effective) |=
 					    (cap_t (current->cap_permitted) &
 					     CAP_FS_MASK);
diff --git a/security/dummy.c b/security/dummy.c
index 853ec22..62de89c 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -43,10 +43,12 @@ static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
 			*permitted |= (~0 & ~CAP_FS_MASK);
 			*effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
 		}
-		if (target->fsuid == 0) {
+		rcu_read_lock();
+		if (task_cred(target)->uid == 0) {
 			*permitted |= CAP_FS_MASK;
 			*effective |= CAP_FS_MASK;
 		}
+		rcu_read_unlock();
 	}
 	return 0;
 }
@@ -138,8 +140,11 @@ static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
 		}
 	}
 
-	current->suid = current->euid = current->fsuid = bprm->e_uid;
-	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+	current->suid = current->euid = bprm->e_uid;
+	current->sgid = current->egid = bprm->e_gid;
+
+	change_fsuid(bprm->cred, bprm->e_uid);
+	change_fsgid(bprm->cred, bprm->e_gid);
 
 	dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
 }
@@ -572,7 +577,7 @@ static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
 
 static void dummy_task_reparent_to_init (struct task_struct *p)
 {
-	p->euid = p->fsuid = 0;
+	p->euid = 0;
 	return;
 }
 
diff --git a/security/keys/key.c b/security/keys/key.c
index 654d23b..c11f408 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -817,7 +817,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 		perm |= KEY_USR_WRITE;
 
 	/* allocate a new key */
-	key = key_alloc(ktype, description, current->fsuid, current->fsgid,
+	key = key_alloc(ktype, description,
+			current->cred->uid, current->cred->gid,
 			current, perm, flags);
 	if (IS_ERR(key)) {
 		key_ref = ERR_CAST(key);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 8ec8432..39e7971 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -806,7 +806,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
 	down_write(&key->sem);
 
 	/* if we're not the sysadmin, we can only change a key that we own */
-	if (capable(CAP_SYS_ADMIN) || key->uid == current->fsuid) {
+	if (capable(CAP_SYS_ADMIN) || key->uid == current->cred->uid) {
 		key->perm = perm;
 		ret = 0;
 	}
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 3b41f9b..f0f0452 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -22,14 +22,19 @@ int key_task_permission(const key_ref_t key_ref,
 			struct task_struct *context,
 			key_perm_t perm)
 {
+	struct cred *cred;
 	struct key *key;
 	key_perm_t kperm;
 	int ret;
 
+	rcu_read_lock();
+	cred = get_task_cred(context);
+	rcu_read_unlock();
+
 	key = key_ref_to_ptr(key_ref);
 
 	/* use the second 8-bits of permissions for keys the caller owns */
-	if (key->uid == context->fsuid) {
+	if (key->uid == cred->uid) {
 		kperm = key->perm >> 16;
 		goto use_these_perms;
 	}
@@ -37,15 +42,12 @@ int key_task_permission(const key_ref_t key_ref,
 	/* use the third 8-bits of permissions for keys the caller has a group
 	 * membership in common with */
 	if (key->gid != -1 && key->perm & KEY_GRP_ALL) {
-		if (key->gid == context->fsgid) {
+		if (key->gid == cred->gid) {
 			kperm = key->perm >> 8;
 			goto use_these_perms;
 		}
 
-		task_lock(context);
-		ret = groups_search(context->group_info, key->gid);
-		task_unlock(context);
-
+		ret = groups_search(cred->group_info, key->gid);
 		if (ret) {
 			kperm = key->perm >> 8;
 			goto use_these_perms;
@@ -56,6 +58,8 @@ int key_task_permission(const key_ref_t key_ref,
 	kperm = key->perm;
 
 use_these_perms:
+	put_cred(cred);
+
 	/* use the top 8-bits of permissions for keys the caller possesses
 	 * - possessor permissions are additive with other permissions
 	 */
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index c886a2b..b8c1a42 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -357,13 +357,14 @@ int suid_keys(struct task_struct *tsk)
 /*****************************************************************************/
 /*
  * the filesystem user ID changed
+ * - can only be used for current task
  */
 void key_fsuid_changed(struct task_struct *tsk)
 {
 	/* update the ownership of the thread keyring */
 	if (tsk->thread_keyring) {
 		down_write(&tsk->thread_keyring->sem);
-		tsk->thread_keyring->uid = tsk->fsuid;
+		tsk->thread_keyring->uid = tsk->cred->uid;
 		up_write(&tsk->thread_keyring->sem);
 	}
 
@@ -372,13 +373,14 @@ void key_fsuid_changed(struct task_struct *tsk)
 /*****************************************************************************/
 /*
  * the filesystem group ID changed
+ * - can only be used for current task
  */
 void key_fsgid_changed(struct task_struct *tsk)
 {
 	/* update the ownership of the thread keyring */
 	if (tsk->thread_keyring) {
 		down_write(&tsk->thread_keyring->sem);
-		tsk->thread_keyring->gid = tsk->fsgid;
+		tsk->thread_keyring->gid = tsk->cred->gid;
 		up_write(&tsk->thread_keyring->sem);
 	}
 
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 5ecc505..4c2f0e2 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -76,8 +76,8 @@ static int call_sbin_request_key(struct key_construction *cons,
 	/* allocate a new session keyring */
 	sprintf(desc, "_req.%u", key->serial);
 
-	keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current,
-				KEY_ALLOC_QUOTA_OVERRUN, NULL);
+	keyring = keyring_alloc(desc, current->cred->uid, current->cred->gid,
+				current, KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error_alloc;
@@ -89,8 +89,8 @@ static int call_sbin_request_key(struct key_construction *cons,
 		goto error_link;
 
 	/* record the UID and GID */
-	sprintf(uid_str, "%d", current->fsuid);
-	sprintf(gid_str, "%d", current->fsgid);
+	sprintf(uid_str, "%d", current->cred->uid);
+	sprintf(gid_str, "%d", current->cred->gid);
 
 	/* we say which key is under construction */
 	sprintf(key_str, "%d", key->serial);
@@ -277,8 +277,8 @@ static int construct_alloc_key(struct key_type *type,
 	mutex_lock(&user->cons_lock);
 
 	key = key_alloc(type, description,
-			current->fsuid, current->fsgid, current, KEY_POS_ALL,
-			flags);
+			current->cred->uid, current->cred->gid, current,
+			KEY_POS_ALL, flags);
 	if (IS_ERR(key))
 		goto alloc_failed;
 
@@ -339,7 +339,7 @@ static struct key *construct_key_and_link(struct key_type *type,
 	struct key *key;
 	int ret;
 
-	user = key_user_lookup(current->fsuid);
+	user = key_user_lookup(current->cred->uid);
 	if (!user)
 		return ERR_PTR(-ENOMEM);
 
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index e42b525..82712bf 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -192,7 +192,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
 	sprintf(desc, "%x", target->serial);
 
 	authkey = key_alloc(&key_type_request_key_auth, desc,
-			    current->fsuid, current->fsgid, current,
+			    current->cred->uid, current->cred->gid, current,
 			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
 			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
 	if (IS_ERR(authkey)) {


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

* [PATCH 02/52] CRED: Give in_group_p() a cred pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
  2007-10-12 16:05 ` [PATCH 01/52] CRED: Introduce a COW credentials record David Howells
@ 2007-10-12 16:05 ` David Howells
  2007-10-12 16:05 ` [PATCH 03/52] CRED: Pass credentials down to ext3 block allocator David Howells
                   ` (51 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:05 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass a credential record pointer to in_group_p() so that it refers to the
credentials set of interest, rather than current credentials.

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

 fs/attr.c                   |   12 ++++++++----
 fs/configfs/inode.c         |    3 ++-
 fs/dquot.c                  |    2 +-
 fs/ext2/balloc.c            |    3 ++-
 fs/ext3/balloc.c            |    3 ++-
 fs/ext4/balloc.c            |    3 ++-
 fs/hugetlbfs/inode.c        |    2 +-
 fs/jffs2/fs.c               |    3 ++-
 fs/namei.c                  |    4 ++--
 fs/posix_acl.c              |    4 ++--
 fs/proc/proc_sysctl.c       |    2 +-
 fs/sysfs/inode.c            |    3 ++-
 fs/xfs/linux-2.6/xfs_iops.c |    3 ++-
 fs/xfs/xfs_inode.c          |    4 ++--
 fs/xfs/xfs_vnodeops.c       |    4 ++--
 include/linux/sched.h       |    4 ++--
 ipc/util.c                  |    3 ++-
 kernel/sys.c                |    5 ++---
 security/keys/keyctl.c      |    3 ++-
 19 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/fs/attr.c b/fs/attr.c
index 3e6b911..f0adb92 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -36,7 +36,8 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
 	/* Make sure caller can chgrp. */
 	if ((ia_valid & ATTR_GID) &&
 	    (current->cred->uid != inode->i_uid ||
-	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
+	     (!in_group_p(current->cred, attr->ia_gid) &&
+	      attr->ia_gid != inode->i_gid)) &&
 	    !capable(CAP_CHOWN))
 		goto error;
 
@@ -45,8 +46,10 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
 		if (!is_owner_or_cap(inode))
 			goto error;
 		/* Also check the setgid bit! */
-		if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
-				inode->i_gid) && !capable(CAP_FSETID))
+		if (!in_group_p(current->cred,
+				(ia_valid & ATTR_GID) ?
+				attr->ia_gid : inode->i_gid) &&
+		    !capable(CAP_FSETID))
 			attr->ia_mode &= ~S_ISGID;
 	}
 
@@ -90,7 +93,8 @@ int inode_setattr(struct inode * inode, struct iattr * attr)
 	if (ia_valid & ATTR_MODE) {
 		umode_t mode = attr->ia_mode;
 
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+		if (!in_group_p(current->cred, inode->i_gid) &&
+		    !capable(CAP_FSETID))
 			mode &= ~S_ISGID;
 		inode->i_mode = mode;
 	}
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index ddc003a..654011f 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -106,7 +106,8 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
 	if (ia_valid & ATTR_MODE) {
 		umode_t mode = iattr->ia_mode;
 
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+		if (!in_group_p(current->cred, inode->i_gid) &&
+		    !capable(CAP_FSETID))
 			mode &= ~S_ISGID;
 		sd_iattr->ia_mode = sd->s_mode = mode;
 	}
diff --git a/fs/dquot.c b/fs/dquot.c
index f1748c6..f98f4ff 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -834,7 +834,7 @@ static inline int need_print_warning(struct dquot *dquot)
 		case USRQUOTA:
 			return current->cred->uid == dquot->dq_id;
 		case GRPQUOTA:
-			return in_group_p(dquot->dq_id);
+			return in_group_p(current->cred, dquot->dq_id);
 	}
 	return 0;
 }
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 3517fce..ca88579 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -113,7 +113,8 @@ static int reserve_blocks(struct super_block *sb, int count)
 
 	if (free_blocks < root_blocks + count && !capable(CAP_SYS_RESOURCE) &&
 	    sbi->s_resuid != current->cred->uid &&
-	    (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+	    (sbi->s_resgid == 0 ||
+	     !in_group_p (current->cred, sbi->s_resgid))) {
 		/*
 		 * We are too close to reserve and we are not privileged.
 		 * Can we allocate anything at all?
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 6c4e82f..316ec8b 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1361,7 +1361,8 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
 		sbi->s_resuid != current->cred->uid &&
-		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+		(sbi->s_resgid == 0 ||
+		 !in_group_p (current->cred, sbi->s_resgid))) {
 		return 0;
 	}
 	return 1;
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 1628c1b..a6ced53 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1378,7 +1378,8 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
 	root_blocks = ext4_r_blocks_count(sbi->s_es);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
 		sbi->s_resuid != current->cred->uid &&
-		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+		(sbi->s_resgid == 0 ||
+		 !in_group_p (current->cred, sbi->s_resgid))) {
 		return 0;
 	}
 	return 1;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 354f545..e0a4795 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -781,7 +781,7 @@ static struct vfsmount *hugetlbfs_vfsmount;
 static int can_do_hugetlb_shm(void)
 {
 	return likely(capable(CAP_IPC_LOCK) ||
-			in_group_p(sysctl_hugetlb_shm_group) ||
+			in_group_p(current->cred, sysctl_hugetlb_shm_group) ||
 			can_do_mlock());
 }
 
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index a3ae187..eed08a2 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -100,7 +100,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
 
 	if (ivalid & ATTR_MODE)
 		if (iattr->ia_mode & S_ISGID &&
-		    !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID))
+		    !in_group_p(current->cred, je16_to_cpu(ri->gid)) &&
+		    !capable(CAP_FSETID))
 			ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID);
 		else
 			ri->mode = cpu_to_jemode(iattr->ia_mode);
diff --git a/fs/namei.c b/fs/namei.c
index 3e10fff..3db9a41 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -196,7 +196,7 @@ int generic_permission(struct inode *inode, int mask,
 				return error;
 		}
 
-		if (in_group_p(inode->i_gid))
+		if (in_group_p(current->cred, inode->i_gid))
 			mode >>= 3;
 	}
 
@@ -439,7 +439,7 @@ static int exec_permission_lite(struct inode *inode,
 
 	if (current->cred->uid == inode->i_uid)
 		mode >>= 6;
-	else if (in_group_p(inode->i_gid))
+	else if (in_group_p(current->cred, inode->i_gid))
 		mode >>= 3;
 
 	if (mode & MAY_EXEC)
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index b36c79f..a78335c 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -225,14 +225,14 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
                                         goto mask;
 				break;
                         case ACL_GROUP_OBJ:
-                                if (in_group_p(inode->i_gid)) {
+                                if (in_group_p(current->cred, inode->i_gid)) {
 					found = 1;
 					if ((pa->e_perm & want) == want)
 						goto mask;
                                 }
 				break;
                         case ACL_GROUP:
-                                if (in_group_p(pa->e_id)) {
+                                if (in_group_p(current->cred, pa->e_id)) {
 					found = 1;
 					if ((pa->e_perm & want) == want)
 						goto mask;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 680c429..feaf4f5 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -393,7 +393,7 @@ static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *
 
 	if (current->euid == 0)
 		mode >>= 6;
-	else if (in_group_p(0))
+	else if (in_group_p(current->cred, 0))
 		mode >>= 3;
 
 	if ((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 10d1b52..fc1934e 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -96,7 +96,8 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
 	if (ia_valid & ATTR_MODE) {
 		umode_t mode = iattr->ia_mode;
 
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+		if (!in_group_p(current->cred, inode->i_gid) &&
+		    !capable(CAP_FSETID))
 			mode &= ~S_ISGID;
 		sd_iattr->ia_mode = sd->s_mode = mode;
 	}
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 0b5fa12..4ffc42e 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -685,7 +685,8 @@ xfs_vn_setattr(
 	if (ia_valid & ATTR_MODE) {
 		vattr.va_mask |= XFS_AT_MODE;
 		vattr.va_mode = attr->ia_mode;
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+		if (!in_group_p(current->cred, inode->i_gid) &&
+		    !capable(CAP_FSETID))
 			inode->i_mode &= ~S_ISGID;
 	}
 
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index cdc4c28..4cd405f 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1175,7 +1175,7 @@ xfs_ialloc(
 	 */
 	if ((irix_sgid_inherit) &&
 	    (ip->i_d.di_mode & S_ISGID) &&
-	    (!in_group_p((gid_t)ip->i_d.di_gid))) {
+	    (!in_group_p(current->cred, (gid_t)ip->i_d.di_gid))) {
 		ip->i_d.di_mode &= ~S_ISGID;
 	}
 
@@ -3635,7 +3635,7 @@ xfs_iaccess(
 
 	if (current_fsuid(cr) != ip->i_d.di_uid) {
 		mode >>= 3;
-		if (!in_group_p((gid_t)ip->i_d.di_gid))
+		if (!in_group_p(current->cred, (gid_t)ip->i_d.di_gid))
 			mode >>= 3;
 	}
 
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 6034592..0109281 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -393,7 +393,7 @@ xfs_setattr(
 			if ((vap->va_mode & S_ISUID) && !file_owner)
 				m |= S_ISUID;
 			if ((vap->va_mode & S_ISGID) &&
-			    !in_group_p((gid_t)ip->i_d.di_gid))
+			    !in_group_p(current->cred, (gid_t)ip->i_d.di_gid))
 				m |= S_ISGID;
 #if 0
 			/* Linux allows this, Irix doesn't. */
@@ -439,7 +439,7 @@ xfs_setattr(
 		 */
 		if (restricted_chown &&
 		    (iuid != uid || (igid != gid &&
-				     !in_group_p((gid_t)gid))) &&
+				     !in_group_p(current->cred, (gid_t)gid))) &&
 		    !capable(CAP_CHOWN)) {
 			code = XFS_ERROR(EPERM);
 			goto error_return;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index fee8b1e..fb90406 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -835,7 +835,7 @@ struct group_info {
 extern struct group_info *groups_alloc(int gidsetsize);
 extern void groups_free(struct group_info *group_info);
 extern int set_current_groups(struct group_info *group_info);
-extern int groups_search(struct group_info *group_info, gid_t grp);
+extern int groups_search(const struct group_info *group_info, gid_t grp);
 /* access the groups "array" with this macro */
 #define GROUP_AT(gi, i) \
     ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK])
@@ -1493,7 +1493,7 @@ extern void FASTCALL(wake_up_new_task(struct task_struct * tsk,
 extern void sched_fork(struct task_struct *p, int clone_flags);
 extern void sched_dead(struct task_struct *p);
 
-extern int in_group_p(gid_t);
+extern int in_group_p(const struct cred *, gid_t);
 extern int in_egroup_p(gid_t);
 
 extern void proc_caches_init(void);
diff --git a/ipc/util.c b/ipc/util.c
index 44e5135..3daa63a 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -546,7 +546,8 @@ int ipcperms (struct kern_ipc_perm *ipcp, short flag)
 	granted_mode = ipcp->mode;
 	if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
 		granted_mode >>= 6;
-	else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
+	else if (in_group_p(current->cred, ipcp->cgid) ||
+		 in_group_p(current->cred, ipcp->gid))
 		granted_mode >>= 3;
 	/* is there some bit set in requested_mode but not in granted_mode? */
 	if ((requested_mode & ~granted_mode & 0007) && 
diff --git a/kernel/sys.c b/kernel/sys.c
index ff25530..5bfefd4 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1796,7 +1796,7 @@ static void groups_sort(struct group_info *group_info)
 }
 
 /* a simple bsearch */
-int groups_search(struct group_info *group_info, gid_t grp)
+int groups_search(const struct group_info *group_info, gid_t grp)
 {
 	unsigned int left, right;
 
@@ -1901,9 +1901,8 @@ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
 /*
  * Check whether we're fsgid/egid or in the supplemental group..
  */
-int in_group_p(gid_t grp)
+int in_group_p(const struct cred *cred, gid_t grp)
 {
-	struct cred *cred = current->cred;
 	int retval = 1;
 
 	if (grp != cred->gid)
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 39e7971..e0a024a 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -713,7 +713,8 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
 
 		/* only the sysadmin can set the key's GID to a group other
 		 * than one of those that the current process subscribes to */
-		if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
+		if (gid != (gid_t) -1 && gid != key->gid &&
+		    !in_group_p(current->cred, gid))
 			goto error_put;
 	}
 


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

* [PATCH 03/52] CRED: Pass credentials down to ext3 block allocator
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
  2007-10-12 16:05 ` [PATCH 01/52] CRED: Introduce a COW credentials record David Howells
  2007-10-12 16:05 ` [PATCH 02/52] CRED: Give in_group_p() a cred pointer David Howells
@ 2007-10-12 16:05 ` David Howells
  2007-10-12 16:05 ` [PATCH 04/52] CRED: Pass credentials down to ext3 inode allocator David Howells
                   ` (50 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:05 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials down to the ext3 block allocator.

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

 fs/ext3/acl.c            |   24 ++++--
 fs/ext3/acl.h            |    5 +
 fs/ext3/balloc.c         |   24 ++++--
 fs/ext3/dir.c            |    9 ++
 fs/ext3/ialloc.c         |    5 +
 fs/ext3/inode.c          |   35 ++++++---
 fs/ext3/namei.c          |  174 +++++++++++++++++++++++++++-------------------
 fs/ext3/super.c          |    6 +-
 fs/ext3/xattr.c          |   23 ++++--
 fs/ext3/xattr.h          |    6 +-
 fs/ext3/xattr_security.c |    7 +-
 fs/ext3/xattr_trusted.c  |    4 +
 fs/ext3/xattr_user.c     |    4 +
 include/linux/ext3_fs.h  |   22 ++++--
 14 files changed, 212 insertions(+), 136 deletions(-)

diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index d34e996..1db810a 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -221,7 +221,7 @@ ext3_get_acl(struct inode *inode, int type)
  */
 static int
 ext3_set_acl(handle_t *handle, struct inode *inode, int type,
-	     struct posix_acl *acl)
+	     struct posix_acl *acl, struct cred *cred)
 {
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	int name_index;
@@ -265,7 +265,7 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
 	}
 
 	error = ext3_xattr_set_handle(handle, inode, name_index, "",
-				      value, size, 0);
+				      value, size, 0, cred);
 
 	kfree(value);
 	if (!error) {
@@ -311,7 +311,8 @@ ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
  * inode->i_mutex: up (access to inode is still exclusive)
  */
 int
-ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
+ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir,
+	      struct cred *cred)
 {
 	struct posix_acl *acl = NULL;
 	int error = 0;
@@ -331,7 +332,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
 
 		if (S_ISDIR(inode->i_mode)) {
 			error = ext3_set_acl(handle, inode,
-					     ACL_TYPE_DEFAULT, acl);
+					     ACL_TYPE_DEFAULT, acl, cred);
 			if (error)
 				goto cleanup;
 		}
@@ -347,7 +348,8 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
 			if (error > 0) {
 				/* This is an extended ACL */
 				error = ext3_set_acl(handle, inode,
-						     ACL_TYPE_ACCESS, clone);
+						     ACL_TYPE_ACCESS, clone,
+						     cred);
 			}
 		}
 		posix_acl_release(clone);
@@ -372,7 +374,7 @@ cleanup:
  * inode->i_mutex: down
  */
 int
-ext3_acl_chmod(struct inode *inode)
+ext3_acl_chmod(struct inode *inode, struct cred *cred)
 {
 	struct posix_acl *acl, *clone;
         int error;
@@ -401,10 +403,10 @@ ext3_acl_chmod(struct inode *inode)
 			ext3_std_error(inode->i_sb, error);
 			goto out;
 		}
-		error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
+		error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone, cred);
 		ext3_journal_stop(handle);
 		if (error == -ENOSPC &&
-		    ext3_should_retry_alloc(inode->i_sb, &retries))
+		    ext3_should_retry_alloc(inode->i_sb, &retries, cred))
 			goto retry;
 	}
 out:
@@ -483,6 +485,7 @@ static int
 ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
 		   size_t size)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct posix_acl *acl;
 	int error, retries = 0;
@@ -508,9 +511,10 @@ retry:
 	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
-	error = ext3_set_acl(handle, inode, type, acl);
+	error = ext3_set_acl(handle, inode, type, acl, cred);
 	ext3_journal_stop(handle);
-	if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
+	if (error == -ENOSPC &&
+	    ext3_should_retry_alloc(inode->i_sb, &retries, cred))
 		goto retry;
 
 release_and_out:
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 0d1e627..f35ccac 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -59,8 +59,9 @@ static inline int ext3_acl_count(size_t size)
 
 /* acl.c */
 extern int ext3_permission (struct inode *, int, struct nameidata *);
-extern int ext3_acl_chmod (struct inode *);
-extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
+extern int ext3_acl_chmod (struct inode *, struct cred *);
+extern int ext3_init_acl (handle_t *, struct inode *, struct inode *,
+			  struct cred *);
 
 #else  /* CONFIG_EXT3_FS_POSIX_ACL */
 #include <linux/sched.h>
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 316ec8b..c1ff445 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1350,19 +1350,19 @@ out:
 /**
  * ext3_has_free_blocks()
  * @sbi:		in-core super block structure.
+ * @cred:		the credentials in force
  *
  * Check if filesystem has at least 1 free block available for allocation.
  */
-static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
+static int ext3_has_free_blocks(struct ext3_sb_info *sbi, struct cred *cred)
 {
 	ext3_fsblk_t free_blocks, root_blocks;
 
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current->cred->uid &&
-		(sbi->s_resgid == 0 ||
-		 !in_group_p (current->cred, sbi->s_resgid))) {
+		sbi->s_resuid != cred->uid &&
+		(sbi->s_resgid == 0 || !in_group_p(cred, sbi->s_resgid))) {
 		return 0;
 	}
 	return 1;
@@ -1372,6 +1372,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
  * ext3_should_retry_alloc()
  * @sb:			super block
  * @retries		number of attemps has been made
+ * @cred:		the credentials in force
  *
  * ext3_should_retry_alloc() is called when ENOSPC is returned, and if
  * it is profitable to retry the operation, this function will wait
@@ -1380,9 +1381,10 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
  *
  * if the total number of retries exceed three times, return FALSE.
  */
-int ext3_should_retry_alloc(struct super_block *sb, int *retries)
+int ext3_should_retry_alloc(struct super_block *sb, int *retries,
+			    struct cred *cred)
 {
-	if (!ext3_has_free_blocks(EXT3_SB(sb)) || (*retries)++ > 3)
+	if (!ext3_has_free_blocks(EXT3_SB(sb), cred) || (*retries)++ > 3)
 		return 0;
 
 	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
@@ -1397,6 +1399,7 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries)
  * @goal:		given target block(filesystem wide)
  * @count:		target number of blocks to allocate
  * @errp:		error code
+ * @cred:		the credentials in force
  *
  * ext3_new_blocks uses a goal block to assist allocation.  It tries to
  * allocate block(s) from the block group contains the goal block first. If that
@@ -1405,7 +1408,8 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries)
  *
  */
 ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
-			ext3_fsblk_t goal, unsigned long *count, int *errp)
+			ext3_fsblk_t goal, unsigned long *count, int *errp,
+			struct cred *cred)
 {
 	struct buffer_head *bitmap_bh = NULL;
 	struct buffer_head *gdp_bh;
@@ -1461,7 +1465,7 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
 	if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
 		my_rsv = &block_i->rsv_window_node;
 
-	if (!ext3_has_free_blocks(sbi)) {
+	if (!ext3_has_free_blocks(sbi, cred)) {
 		*errp = -ENOSPC;
 		goto out;
 	}
@@ -1668,11 +1672,11 @@ out:
 }
 
 ext3_fsblk_t ext3_new_block(handle_t *handle, struct inode *inode,
-			ext3_fsblk_t goal, int *errp)
+			ext3_fsblk_t goal, int *errp, struct cred *cred)
 {
 	unsigned long count = 1;
 
-	return ext3_new_blocks(handle, inode, goal, &count, errp);
+	return ext3_new_blocks(handle, inode, goal, &count, errp, cred);
 }
 
 /**
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index c00723a..d745f99 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -96,6 +96,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir,
 static int ext3_readdir(struct file * filp,
 			 void * dirent, filldir_t filldir)
 {
+	struct cred *cred = filp->f_cred;
 	int error = 0;
 	unsigned long offset;
 	int i, stored;
@@ -134,7 +135,7 @@ static int ext3_readdir(struct file * filp,
 
 		map_bh.b_state = 0;
 		err = ext3_get_blocks_handle(NULL, inode, blk, 1,
-						&map_bh, 0, 0);
+						&map_bh, 0, 0, cred);
 		if (err > 0) {
 			pgoff_t index = map_bh.b_blocknr >>
 					(PAGE_CACHE_SHIFT - inode->i_blkbits);
@@ -144,7 +145,7 @@ static int ext3_readdir(struct file * filp,
 					&filp->f_ra, filp,
 					index, 1);
 			filp->f_ra.prev_index = index;
-			bh = ext3_bread(NULL, inode, blk, 0, &err);
+			bh = ext3_bread(NULL, inode, blk, 0, &err, cred);
 		}
 
 		/*
@@ -432,6 +433,7 @@ static int call_filldir(struct file * filp, void * dirent,
 static int ext3_dx_readdir(struct file * filp,
 			 void * dirent, filldir_t filldir)
 {
+	struct cred *cred = filp->f_cred;
 	struct dir_private_info *info = filp->private_data;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct fname *fname;
@@ -480,7 +482,8 @@ static int ext3_dx_readdir(struct file * filp,
 			filp->f_version = inode->i_version;
 			ret = ext3_htree_fill_tree(filp, info->curr_hash,
 						   info->curr_minor_hash,
-						   &info->next_hash);
+						   &info->next_hash,
+						   cred);
 			if (ret < 0)
 				return ret;
 			if (ret == 0) {
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 195e9e8..596d8ca 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -421,7 +421,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
  * For other inodes, search forward from the parent directory's block
  * group to find a free inode.
  */
-struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
+struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode,
+			     struct cred *cred)
 {
 	struct super_block *sb;
 	struct buffer_head *bitmap_bh = NULL;
@@ -602,7 +603,7 @@ got:
 		goto fail_drop;
 	}
 
-	err = ext3_init_acl(handle, inode, dir);
+	err = ext3_init_acl(handle, inode, dir, cred);
 	if (err)
 		goto fail_free_drop;
 
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 6c74622..57a2e74 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -513,10 +513,12 @@ static int ext3_blks_to_allocate(Indirect *branch, int k, unsigned long blks,
  *	the indirect blocks(if needed) and the first direct block,
  *	@blks:	on return it will store the total number of allocated
  *		direct blocks
+ *	@cred:	the credentials in force
  */
 static int ext3_alloc_blocks(handle_t *handle, struct inode *inode,
 			ext3_fsblk_t goal, int indirect_blks, int blks,
-			ext3_fsblk_t new_blocks[4], int *err)
+			ext3_fsblk_t new_blocks[4], int *err,
+			struct cred *cred)
 {
 	int target, i;
 	unsigned long count = 0;
@@ -537,7 +539,8 @@ static int ext3_alloc_blocks(handle_t *handle, struct inode *inode,
 	while (1) {
 		count = target;
 		/* allocating blocks for indirect blocks and direct blocks */
-		current_block = ext3_new_blocks(handle,inode,goal,&count,err);
+		current_block = ext3_new_blocks(handle,inode,goal,&count,err,
+						cred);
 		if (*err)
 			goto failed_out;
 
@@ -572,6 +575,7 @@ failed_out:
  *	@blks: number of allocated direct blocks
  *	@offsets: offsets (in the blocks) to store the pointers to next.
  *	@branch: place to store the chain in.
+ *	@cred:	the credentials in force
  *
  *	This function allocates blocks, zeroes out all but the last one,
  *	links them into chain and (if we are synchronous) writes them to disk.
@@ -592,7 +596,7 @@ failed_out:
  */
 static int ext3_alloc_branch(handle_t *handle, struct inode *inode,
 			int indirect_blks, int *blks, ext3_fsblk_t goal,
-			int *offsets, Indirect *branch)
+			int *offsets, Indirect *branch, struct cred *cred)
 {
 	int blocksize = inode->i_sb->s_blocksize;
 	int i, n = 0;
@@ -603,7 +607,7 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode,
 	ext3_fsblk_t current_block;
 
 	num = ext3_alloc_blocks(handle, inode, goal, indirect_blks,
-				*blks, new_blocks, &err);
+				*blks, new_blocks, &err, cred);
 	if (err)
 		return err;
 
@@ -788,7 +792,7 @@ err_out:
 int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 		sector_t iblock, unsigned long maxblocks,
 		struct buffer_head *bh_result,
-		int create, int extend_disksize)
+		int create, int extend_disksize, struct cred *cred)
 {
 	int err = -EIO;
 	int offsets[4];
@@ -899,7 +903,7 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 	 * Block out ext3_truncate while we alter the tree
 	 */
 	err = ext3_alloc_branch(handle, inode, indirect_blks, &count, goal,
-				offsets + (partial - chain), partial);
+				offsets + (partial - chain), partial, cred);
 
 	/*
 	 * The ext3_splice_branch call will free and forget any buffers
@@ -946,6 +950,7 @@ out:
 static int ext3_get_block(struct inode *inode, sector_t iblock,
 			struct buffer_head *bh_result, int create)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle = ext3_journal_current_handle();
 	int ret = 0;
 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
@@ -984,7 +989,7 @@ static int ext3_get_block(struct inode *inode, sector_t iblock,
 get_block:
 	if (ret == 0) {
 		ret = ext3_get_blocks_handle(handle, inode, iblock,
-					max_blocks, bh_result, create, 0);
+					max_blocks, bh_result, create, 0, cred);
 		if (ret > 0) {
 			bh_result->b_size = (ret << inode->i_blkbits);
 			ret = 0;
@@ -997,7 +1002,8 @@ get_block:
  * `handle' can be NULL if create is zero
  */
 struct buffer_head *ext3_getblk(handle_t *handle, struct inode *inode,
-				long block, int create, int *errp)
+				long block, int create, int *errp,
+				struct cred *cred)
 {
 	struct buffer_head dummy;
 	int fatal = 0, err;
@@ -1008,7 +1014,7 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode *inode,
 	dummy.b_blocknr = -1000;
 	buffer_trace_init(&dummy.b_history);
 	err = ext3_get_blocks_handle(handle, inode, block, 1,
-					&dummy, create, 1);
+					&dummy, create, 1, cred);
 	/*
 	 * ext3_get_blocks_handle() returns number of blocks
 	 * mapped. 0 in case of a HOLE.
@@ -1064,11 +1070,12 @@ err:
 }
 
 struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode,
-			       int block, int create, int *err)
+			       int block, int create, int *err,
+			       struct cred *cred)
 {
 	struct buffer_head * bh;
 
-	bh = ext3_getblk(handle, inode, block, create, err);
+	bh = ext3_getblk(handle, inode, block, create, err, cred);
 	if (!bh)
 		return bh;
 	if (buffer_uptodate(bh))
@@ -1175,7 +1182,8 @@ retry:
 prepare_write_failed:
 	if (ret)
 		ext3_journal_stop(handle);
-	if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
+	if (ret == -ENOSPC &&
+	    ext3_should_retry_alloc(inode->i_sb, &retries, file->f_cred))
 		goto retry;
 out:
 	return ret;
@@ -2930,6 +2938,7 @@ int ext3_write_inode(struct inode *inode, int wait)
  */
 int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int error, rc = 0;
 	const unsigned int ia_valid = attr->ia_valid;
@@ -2992,7 +3001,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 		ext3_orphan_del(NULL, inode);
 
 	if (!rc && (ia_valid & ATTR_MODE))
-		rc = ext3_acl_chmod(inode);
+		rc = ext3_acl_chmod(inode, cred);
 
 err_out:
 	ext3_std_error(inode->i_sb, error);
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 6919a18..4a6adaa 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -51,13 +51,14 @@
 
 static struct buffer_head *ext3_append(handle_t *handle,
 					struct inode *inode,
-					u32 *block, int *err)
+					u32 *block, int *err,
+					struct cred *cred)
 {
 	struct buffer_head *bh;
 
 	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 
-	if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
+	if ((bh = ext3_bread(handle, inode, *block, 1, err, cred))) {
 		inode->i_size += inode->i_sb->s_blocksize;
 		EXT3_I(inode)->i_disksize = inode->i_size;
 		ext3_journal_get_write_access(handle,bh);
@@ -159,7 +160,8 @@ static struct dx_frame *dx_probe(struct dentry *dentry,
 				 struct inode *dir,
 				 struct dx_hash_info *hinfo,
 				 struct dx_frame *frame,
-				 int *err);
+				 int *err,
+				 struct cred *cred);
 static void dx_release (struct dx_frame *frames);
 static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
 			struct dx_hash_info *hinfo, struct dx_map_entry map[]);
@@ -171,11 +173,13 @@ static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
 static int ext3_htree_next_block(struct inode *dir, __u32 hash,
 				 struct dx_frame *frame,
 				 struct dx_frame *frames,
-				 __u32 *start_hash);
+				 __u32 *start_hash,
+				 struct cred *cred);
 static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-		       struct ext3_dir_entry_2 **res_dir, int *err);
+		       struct ext3_dir_entry_2 **res_dir, int *err,
+		       struct cred *cred);
 static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
-			     struct inode *inode);
+			     struct inode *inode, struct cred *cred);
 
 /*
  * Future: use high four bits of block for coalesce-on-delete flags
@@ -329,7 +333,8 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
  */
 static struct dx_frame *
 dx_probe(struct dentry *dentry, struct inode *dir,
-	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
+	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err,
+	 struct cred *cred)
 {
 	unsigned count, indirect;
 	struct dx_entry *at, *entries, *p, *q, *m;
@@ -341,7 +346,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 	frame->bh = NULL;
 	if (dentry)
 		dir = dentry->d_parent->d_inode;
-	if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
+	if (!(bh = ext3_bread (NULL,dir, 0, 0, err, cred)))
 		goto fail;
 	root = (struct dx_root *) bh->b_data;
 	if (root->info.hash_version != DX_HASH_TEA &&
@@ -436,7 +441,8 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 		frame->entries = entries;
 		frame->at = at;
 		if (!indirect--) return frame;
-		if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
+		if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err,
+				       cred)))
 			goto fail2;
 		at = entries = ((struct dx_node *) bh->b_data)->entries;
 		if (dx_get_limit(entries) != dx_node_limit (dir)) {
@@ -492,7 +498,8 @@ static void dx_release (struct dx_frame *frames)
 static int ext3_htree_next_block(struct inode *dir, __u32 hash,
 				 struct dx_frame *frame,
 				 struct dx_frame *frames,
-				 __u32 *start_hash)
+				 __u32 *start_hash,
+				 struct cred *cred)
 {
 	struct dx_frame *p;
 	struct buffer_head *bh;
@@ -536,7 +543,7 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash,
 	 */
 	while (num_frames--) {
 		if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
-				      0, &err)))
+				      0, &err, cred)))
 			return err; /* Failure */
 		p++;
 		brelse (p->bh);
@@ -563,14 +570,15 @@ static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *
 static int htree_dirblock_to_tree(struct file *dir_file,
 				  struct inode *dir, int block,
 				  struct dx_hash_info *hinfo,
-				  __u32 start_hash, __u32 start_minor_hash)
+				  __u32 start_hash, __u32 start_minor_hash,
+				  struct cred *cred)
 {
 	struct buffer_head *bh;
 	struct ext3_dir_entry_2 *de, *top;
 	int err, count = 0;
 
 	dxtrace(printk("In htree dirblock_to_tree: block %d\n", block));
-	if (!(bh = ext3_bread (NULL, dir, block, 0, &err)))
+	if (!(bh = ext3_bread (NULL, dir, block, 0, &err, cred)))
 		return err;
 
 	de = (struct ext3_dir_entry_2 *) bh->b_data;
@@ -615,7 +623,8 @@ static int htree_dirblock_to_tree(struct file *dir_file,
  * or a negative error code.
  */
 int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-			 __u32 start_minor_hash, __u32 *next_hash)
+			 __u32 start_minor_hash, __u32 *next_hash,
+			 struct cred *cred)
 {
 	struct dx_hash_info hinfo;
 	struct ext3_dir_entry_2 *de;
@@ -633,13 +642,15 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 		hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
 		hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
 		count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo,
-					       start_hash, start_minor_hash);
+					       start_hash, start_minor_hash,
+					       cred);
 		*next_hash = ~0;
 		return count;
 	}
 	hinfo.hash = start_hash;
 	hinfo.minor_hash = 0;
-	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
+	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames,
+			 &err, cred);
 	if (!frame)
 		return err;
 
@@ -661,7 +672,8 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 	while (1) {
 		block = dx_get_block(frame->at);
 		ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo,
-					     start_hash, start_minor_hash);
+					     start_hash, start_minor_hash,
+					     cred);
 		if (ret < 0) {
 			err = ret;
 			goto errout;
@@ -669,7 +681,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 		count += ret;
 		hashval = ~0;
 		ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS,
-					    frame, frames, &hashval);
+					    frame, frames, &hashval, cred);
 		*next_hash = hashval;
 		if (ret < 0) {
 			err = ret;
@@ -847,7 +859,8 @@ static inline int search_dirblock(struct buffer_head * bh,
  * to brelse() it when appropriate.
  */
 static struct buffer_head * ext3_find_entry (struct dentry *dentry,
-					struct ext3_dir_entry_2 ** res_dir)
+					struct ext3_dir_entry_2 ** res_dir,
+					struct cred *cred)
 {
 	struct super_block * sb;
 	struct buffer_head * bh_use[NAMEI_RA_SIZE];
@@ -873,7 +886,7 @@ static struct buffer_head * ext3_find_entry (struct dentry *dentry,
 		return NULL;
 #ifdef CONFIG_EXT3_INDEX
 	if (is_dx(dir)) {
-		bh = ext3_dx_find_entry(dentry, res_dir, &err);
+		bh = ext3_dx_find_entry(dentry, res_dir, &err, cred);
 		/*
 		 * On success, or if the error was file not found,
 		 * return.  Otherwise, fall back to doing a search the
@@ -909,7 +922,7 @@ restart:
 					break;
 				}
 				num++;
-				bh = ext3_getblk(NULL, dir, b++, 0, &err);
+				bh = ext3_getblk(NULL, dir, b++, 0, &err, cred);
 				bh_use[ra_max] = bh;
 				if (bh)
 					ll_rw_block(READ_META, 1, &bh);
@@ -961,7 +974,8 @@ cleanup_and_exit:
 
 #ifdef CONFIG_EXT3_INDEX
 static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-		       struct ext3_dir_entry_2 **res_dir, int *err)
+		       struct ext3_dir_entry_2 **res_dir, int *err,
+		       struct cred *cred)
 {
 	struct super_block * sb;
 	struct dx_hash_info	hinfo;
@@ -978,7 +992,8 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
 	sb = dir->i_sb;
 	/* NFS may look up ".." - look at dx_root directory block */
 	if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
-		if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
+		if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err,
+				       cred)))
 			return NULL;
 	} else {
 		frame = frames;
@@ -989,7 +1004,7 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
 	hash = hinfo.hash;
 	do {
 		block = dx_get_block(frame->at);
-		if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
+		if (!(bh = ext3_bread (NULL,dir, block, 0, err, cred)))
 			goto errout;
 		de = (struct ext3_dir_entry_2 *) bh->b_data;
 		top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize -
@@ -1011,7 +1026,7 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
 		brelse (bh);
 		/* Check to see if we should continue to search */
 		retval = ext3_htree_next_block(dir, hash, frame,
-					       frames, NULL);
+					       frames, NULL, cred);
 		if (retval < 0) {
 			ext3_warning(sb, __FUNCTION__,
 			     "error reading index page in directory #%lu",
@@ -1031,6 +1046,7 @@ errout:
 
 static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	struct inode * inode;
 	struct ext3_dir_entry_2 * de;
 	struct buffer_head * bh;
@@ -1038,7 +1054,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
 	if (dentry->d_name.len > EXT3_NAME_LEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	bh = ext3_find_entry(dentry, &de);
+	bh = ext3_find_entry(dentry, &de, cred);
 	inode = NULL;
 	if (bh) {
 		unsigned long ino = le32_to_cpu(de->inode);
@@ -1058,6 +1074,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
 
 struct dentry *ext3_get_parent(struct dentry *child)
 {
+	struct cred *cred = current->cred;
 	unsigned long ino;
 	struct dentry *parent;
 	struct inode *inode;
@@ -1069,7 +1086,7 @@ struct dentry *ext3_get_parent(struct dentry *child)
 	dotdot.d_name.len = 2;
 	dotdot.d_parent = child; /* confusing, isn't it! */
 
-	bh = ext3_find_entry(&dotdot, &de);
+	bh = ext3_find_entry(&dotdot, &de, cred);
 	inode = NULL;
 	if (!bh)
 		return ERR_PTR(-ENOENT);
@@ -1168,7 +1185,8 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
  */
 static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 			struct buffer_head **bh,struct dx_frame *frame,
-			struct dx_hash_info *hinfo, int *error)
+			struct dx_hash_info *hinfo, int *error,
+			struct cred *cred)
 {
 	unsigned blocksize = dir->i_sb->s_blocksize;
 	unsigned count, continued;
@@ -1181,7 +1199,7 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 	struct ext3_dir_entry_2 *de = NULL, *de2;
 	int	err = 0;
 
-	bh2 = ext3_append (handle, dir, &newblock, &err);
+	bh2 = ext3_append (handle, dir, &newblock, &err, cred);
 	if (!(bh2)) {
 		brelse(*bh);
 		*bh = NULL;
@@ -1361,7 +1379,8 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
  * directory, and adds the dentry to the indexed directory.
  */
 static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
-			    struct inode *inode, struct buffer_head *bh)
+			    struct inode *inode, struct buffer_head *bh,
+			    struct cred *cred)
 {
 	struct inode	*dir = dentry->d_parent->d_inode;
 	const char	*name = dentry->d_name.name;
@@ -1389,7 +1408,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
 	}
 	root = (struct dx_root *) bh->b_data;
 
-	bh2 = ext3_append (handle, dir, &block, &retval);
+	bh2 = ext3_append (handle, dir, &block, &retval, cred);
 	if (!(bh2)) {
 		brelse(bh);
 		return retval;
@@ -1427,7 +1446,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
 	frame->at = entries;
 	frame->bh = bh;
 	bh = bh2;
-	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
+	de = do_split(handle,dir, &bh, frame, &hinfo, &retval, cred);
 	dx_release (frames);
 	if (!(de))
 		return retval;
@@ -1447,7 +1466,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
  * the entry, as someone else might have used it while you slept.
  */
 static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
-	struct inode *inode)
+	struct inode *inode, struct cred *cred)
 {
 	struct inode *dir = dentry->d_parent->d_inode;
 	unsigned long offset;
@@ -1467,7 +1486,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
 		return -EINVAL;
 #ifdef CONFIG_EXT3_INDEX
 	if (is_dx(dir)) {
-		retval = ext3_dx_add_entry(handle, dentry, inode);
+		retval = ext3_dx_add_entry(handle, dentry, inode, cred);
 		if (!retval || (retval != ERR_BAD_DX_DIR))
 			return retval;
 		EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL;
@@ -1477,7 +1496,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
 #endif
 	blocks = dir->i_size >> sb->s_blocksize_bits;
 	for (block = 0, offset = 0; block < blocks; block++) {
-		bh = ext3_bread(handle, dir, block, 0, &retval);
+		bh = ext3_bread(handle, dir, block, 0, &retval, cred);
 		if(!bh)
 			return retval;
 		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
@@ -1487,11 +1506,11 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
 #ifdef CONFIG_EXT3_INDEX
 		if (blocks == 1 && !dx_fallback &&
 		    EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
-			return make_indexed_dir(handle, dentry, inode, bh);
+			return make_indexed_dir(handle, dentry, inode, bh, cred);
 #endif
 		brelse(bh);
 	}
-	bh = ext3_append(handle, dir, &block, &retval);
+	bh = ext3_append(handle, dir, &block, &retval, cred);
 	if (!bh)
 		return retval;
 	de = (struct ext3_dir_entry_2 *) bh->b_data;
@@ -1505,7 +1524,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
  * Returns 0 for success, or a negative error value
  */
 static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
-			     struct inode *inode)
+			     struct inode *inode, struct cred *cred)
 {
 	struct dx_frame frames[2], *frame;
 	struct dx_entry *entries, *at;
@@ -1516,13 +1535,14 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
 	struct ext3_dir_entry_2 *de;
 	int err;
 
-	frame = dx_probe(dentry, NULL, &hinfo, frames, &err);
+	frame = dx_probe(dentry, NULL, &hinfo, frames, &err, cred);
 	if (!frame)
 		return err;
 	entries = frame->entries;
 	at = frame->at;
 
-	if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
+	if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err,
+			      cred)))
 		goto cleanup;
 
 	BUFFER_TRACE(bh, "get_write_access");
@@ -1555,7 +1575,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			err = -ENOSPC;
 			goto cleanup;
 		}
-		bh2 = ext3_append (handle, dir, &newblock, &err);
+		bh2 = ext3_append (handle, dir, &newblock, &err, cred);
 		if (!(bh2))
 			goto cleanup;
 		node2 = (struct dx_node *)(bh2->b_data);
@@ -1620,7 +1640,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
 		}
 		ext3_journal_dirty_metadata(handle, frames[0].bh);
 	}
-	de = do_split(handle, dir, &bh, frame, &hinfo, &err);
+	de = do_split(handle, dir, &bh, frame, &hinfo, &err, cred);
 	if (!de)
 		goto cleanup;
 	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
@@ -1678,9 +1698,9 @@ static int ext3_delete_entry (handle_t *handle,
 }
 
 static int ext3_add_nondir(handle_t *handle,
-		struct dentry *dentry, struct inode *inode)
+		struct dentry *dentry, struct inode *inode, struct cred *cred)
 {
-	int err = ext3_add_entry(handle, dentry, inode);
+	int err = ext3_add_entry(handle, dentry, inode, cred);
 	if (!err) {
 		ext3_mark_inode_dirty(handle, inode);
 		d_instantiate(dentry, inode);
@@ -1702,6 +1722,7 @@ static int ext3_add_nondir(handle_t *handle,
 static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
 		struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	int err, retries = 0;
@@ -1716,16 +1737,16 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext3_new_inode (handle, dir, mode);
+	inode = ext3_new_inode (handle, dir, mode, cred);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		inode->i_op = &ext3_file_inode_operations;
 		inode->i_fop = &ext3_file_operations;
 		ext3_set_aops(inode);
-		err = ext3_add_nondir(handle, dentry, inode);
+		err = ext3_add_nondir(handle, dentry, inode, cred);
 	}
 	ext3_journal_stop(handle);
-	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
@@ -1733,6 +1754,7 @@ retry:
 static int ext3_mknod (struct inode * dir, struct dentry *dentry,
 			int mode, dev_t rdev)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode *inode;
 	int err, retries = 0;
@@ -1750,23 +1772,25 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext3_new_inode (handle, dir, mode);
+	inode = ext3_new_inode (handle, dir, mode, cred);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, inode->i_mode, rdev);
 #ifdef CONFIG_EXT3_FS_XATTR
 		inode->i_op = &ext3_special_inode_operations;
 #endif
-		err = ext3_add_nondir(handle, dentry, inode);
+		err = ext3_add_nondir(handle, dentry, inode, cred);
 	}
 	ext3_journal_stop(handle);
-	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries,
+						      cred))
 		goto retry;
 	return err;
 }
 
 static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	struct buffer_head * dir_block;
@@ -1786,7 +1810,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
+	inode = ext3_new_inode (handle, dir, S_IFDIR | mode, cred);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_stop;
@@ -1794,7 +1818,7 @@ retry:
 	inode->i_op = &ext3_dir_inode_operations;
 	inode->i_fop = &ext3_dir_operations;
 	inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-	dir_block = ext3_bread (handle, inode, 0, 1, &err);
+	dir_block = ext3_bread (handle, inode, 0, 1, &err, cred);
 	if (!dir_block) {
 		drop_nlink(inode); /* is this nlink == 0? */
 		ext3_mark_inode_dirty(handle, inode);
@@ -1821,7 +1845,7 @@ retry:
 	ext3_journal_dirty_metadata(handle, dir_block);
 	brelse (dir_block);
 	ext3_mark_inode_dirty(handle, inode);
-	err = ext3_add_entry (handle, dentry, inode);
+	err = ext3_add_entry (handle, dentry, inode, cred);
 	if (err) {
 		inode->i_nlink = 0;
 		ext3_mark_inode_dirty(handle, inode);
@@ -1834,7 +1858,7 @@ retry:
 	d_instantiate(dentry, inode);
 out_stop:
 	ext3_journal_stop(handle);
-	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
@@ -1842,7 +1866,7 @@ out_stop:
 /*
  * routine to check that the specified directory is empty (for rmdir)
  */
-static int empty_dir (struct inode * inode)
+static int empty_dir (struct inode * inode, struct cred *cred)
 {
 	unsigned long offset;
 	struct buffer_head * bh;
@@ -1852,7 +1876,7 @@ static int empty_dir (struct inode * inode)
 
 	sb = inode->i_sb;
 	if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) ||
-	    !(bh = ext3_bread (NULL, inode, 0, 0, &err))) {
+	    !(bh = ext3_bread (NULL, inode, 0, 0, &err, cred))) {
 		if (err)
 			ext3_error(inode->i_sb, __FUNCTION__,
 				   "error %d reading directory #%lu offset 0",
@@ -1885,7 +1909,8 @@ static int empty_dir (struct inode * inode)
 			err = 0;
 			brelse (bh);
 			bh = ext3_bread (NULL, inode,
-				offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err);
+				offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err,
+				cred);
 			if (!bh) {
 				if (err)
 					ext3_error(sb, __FUNCTION__,
@@ -2059,6 +2084,7 @@ out_brelse:
 
 static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
@@ -2073,7 +2099,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
 		return PTR_ERR(handle);
 
 	retval = -ENOENT;
-	bh = ext3_find_entry (dentry, &de);
+	bh = ext3_find_entry (dentry, &de, cred);
 	if (!bh)
 		goto end_rmdir;
 
@@ -2087,7 +2113,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
 		goto end_rmdir;
 
 	retval = -ENOTEMPTY;
-	if (!empty_dir (inode))
+	if (!empty_dir (inode, cred))
 		goto end_rmdir;
 
 	retval = ext3_delete_entry(handle, dir, de, bh);
@@ -2118,6 +2144,7 @@ end_rmdir:
 
 static int ext3_unlink(struct inode * dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
@@ -2135,7 +2162,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
 		handle->h_sync = 1;
 
 	retval = -ENOENT;
-	bh = ext3_find_entry (dentry, &de);
+	bh = ext3_find_entry (dentry, &de, cred);
 	if (!bh)
 		goto end_unlink;
 
@@ -2173,6 +2200,7 @@ end_unlink:
 static int ext3_symlink (struct inode * dir,
 		struct dentry *dentry, const char * symname)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	int l, err, retries = 0;
@@ -2191,7 +2219,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
+	inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO, cred);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_stop;
@@ -2218,10 +2246,11 @@ retry:
 		inode->i_size = l-1;
 	}
 	EXT3_I(inode)->i_disksize = inode->i_size;
-	err = ext3_add_nondir(handle, dentry, inode);
+	err = ext3_add_nondir(handle, dentry, inode, cred);
 out_stop:
 	ext3_journal_stop(handle);
-	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC &&
+	    ext3_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
@@ -2229,6 +2258,7 @@ out_stop:
 static int ext3_link (struct dentry * old_dentry,
 		struct inode * dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode *inode = old_dentry->d_inode;
 	int err, retries = 0;
@@ -2255,9 +2285,10 @@ retry:
 	inc_nlink(inode);
 	atomic_inc(&inode->i_count);
 
-	err = ext3_add_nondir(handle, dentry, inode);
+	err = ext3_add_nondir(handle, dentry, inode, cred);
 	ext3_journal_stop(handle);
-	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC &&
+	    ext3_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
@@ -2273,6 +2304,7 @@ retry:
 static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 			   struct inode * new_dir,struct dentry *new_dentry)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * old_inode, * new_inode;
 	struct buffer_head * old_bh, * new_bh, * dir_bh;
@@ -2294,7 +2326,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
 		handle->h_sync = 1;
 
-	old_bh = ext3_find_entry (old_dentry, &old_de);
+	old_bh = ext3_find_entry (old_dentry, &old_de, cred);
 	/*
 	 *  Check for inode number is _not_ due to possible IO errors.
 	 *  We might rmdir the source, keep it as pwd of some process
@@ -2307,7 +2339,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 		goto end_rename;
 
 	new_inode = new_dentry->d_inode;
-	new_bh = ext3_find_entry (new_dentry, &new_de);
+	new_bh = ext3_find_entry (new_dentry, &new_de, cred);
 	if (new_bh) {
 		if (!new_inode) {
 			brelse (new_bh);
@@ -2317,11 +2349,11 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 	if (S_ISDIR(old_inode->i_mode)) {
 		if (new_inode) {
 			retval = -ENOTEMPTY;
-			if (!empty_dir (new_inode))
+			if (!empty_dir (new_inode, cred))
 				goto end_rename;
 		}
 		retval = -EIO;
-		dir_bh = ext3_bread (handle, old_inode, 0, 0, &retval);
+		dir_bh = ext3_bread (handle, old_inode, 0, 0, &retval, cred);
 		if (!dir_bh)
 			goto end_rename;
 		if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
@@ -2332,7 +2364,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 			goto end_rename;
 	}
 	if (!new_bh) {
-		retval = ext3_add_entry (handle, new_dentry, old_inode);
+		retval = ext3_add_entry (handle, new_dentry, old_inode, cred);
 		if (retval)
 			goto end_rename;
 	} else {
@@ -2371,7 +2403,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 		struct buffer_head *old_bh2;
 		struct ext3_dir_entry_2 *old_de2;
 
-		old_bh2 = ext3_find_entry(old_dentry, &old_de2);
+		old_bh2 = ext3_find_entry(old_dentry, &old_de2, cred);
 		if (old_bh2) {
 			retval = ext3_delete_entry(handle, old_dir,
 						   old_de2, old_bh2);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index add683b..14a558b 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -2671,6 +2671,7 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
 static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
 			       size_t len, loff_t off)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = sb_dqopt(sb)->files[type];
 	sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
 	int err = 0;
@@ -2688,7 +2689,7 @@ static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
 	while (toread > 0) {
 		tocopy = sb->s_blocksize - offset < toread ?
 				sb->s_blocksize - offset : toread;
-		bh = ext3_bread(NULL, inode, blk, 0, &err);
+		bh = ext3_bread(NULL, inode, blk, 0, &err, cred);
 		if (err)
 			return err;
 		if (!bh)	/* A hole? */
@@ -2709,6 +2710,7 @@ static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
 static ssize_t ext3_quota_write(struct super_block *sb, int type,
 				const char *data, size_t len, loff_t off)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = sb_dqopt(sb)->files[type];
 	sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
 	int err = 0;
@@ -2729,7 +2731,7 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
 	while (towrite > 0) {
 		tocopy = sb->s_blocksize - offset < towrite ?
 				sb->s_blocksize - offset : towrite;
-		bh = ext3_bread(handle, inode, blk, 1, &err);
+		bh = ext3_bread(handle, inode, blk, 1, &err, cred);
 		if (!bh)
 			goto out;
 		if (journal_quota) {
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index f58cbb2..3b34cea 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -676,7 +676,8 @@ cleanup:
 static int
 ext3_xattr_block_set(handle_t *handle, struct inode *inode,
 		     struct ext3_xattr_info *i,
-		     struct ext3_xattr_block_find *bs)
+		     struct ext3_xattr_block_find *bs,
+		     struct cred *cred)
 {
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *new_bh = NULL;
@@ -805,7 +806,7 @@ inserted:
 				(ext3_fsblk_t)EXT3_I(inode)->i_block_group *
 				EXT3_BLOCKS_PER_GROUP(sb);
 			ext3_fsblk_t block = ext3_new_block(handle, inode,
-							goal, &error);
+							goal, &error, cred);
 			if (error)
 				goto cleanup;
 			ea_idebug(inode, "creating block %d", block);
@@ -938,7 +939,7 @@ ext3_xattr_ibody_set(handle_t *handle, struct inode *inode,
 int
 ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
 		      const char *name, const void *value, size_t value_len,
-		      int flags)
+		      int flags, struct cred *cred)
 {
 	struct ext3_xattr_info i = {
 		.name_index = name_index,
@@ -996,14 +997,17 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
 		if (!is.s.not_found)
 			error = ext3_xattr_ibody_set(handle, inode, &i, &is);
 		else if (!bs.s.not_found)
-			error = ext3_xattr_block_set(handle, inode, &i, &bs);
+			error = ext3_xattr_block_set(handle, inode, &i, &bs,
+						     cred);
 	} else {
 		error = ext3_xattr_ibody_set(handle, inode, &i, &is);
 		if (!error && !bs.s.not_found) {
 			i.value = NULL;
-			error = ext3_xattr_block_set(handle, inode, &i, &bs);
+			error = ext3_xattr_block_set(handle, inode, &i, &bs,
+						     cred);
 		} else if (error == -ENOSPC) {
-			error = ext3_xattr_block_set(handle, inode, &i, &bs);
+			error = ext3_xattr_block_set(handle, inode, &i, &bs,
+						     cred);
 			if (error)
 				goto cleanup;
 			if (!is.s.not_found) {
@@ -1043,7 +1047,8 @@ cleanup:
  */
 int
 ext3_xattr_set(struct inode *inode, int name_index, const char *name,
-	       const void *value, size_t value_len, int flags)
+	       const void *value, size_t value_len, int flags,
+	       struct cred *cred)
 {
 	handle_t *handle;
 	int error, retries = 0;
@@ -1056,10 +1061,10 @@ retry:
 		int error2;
 
 		error = ext3_xattr_set_handle(handle, inode, name_index, name,
-					      value, value_len, flags);
+					      value, value_len, flags, cred);
 		error2 = ext3_journal_stop(handle);
 		if (error == -ENOSPC &&
-		    ext3_should_retry_alloc(inode->i_sb, &retries))
+		    ext3_should_retry_alloc(inode->i_sb, &retries, cred))
 			goto retry;
 		if (error == 0)
 			error = error2;
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 6b1ae1c..761772a 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -68,8 +68,10 @@ extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
 
 extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
 extern int ext3_xattr_list(struct inode *, char *, size_t);
-extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
-extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
+extern int ext3_xattr_set(struct inode *, int, const char *, const void *,
+			  size_t, int, struct cred *);
+extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *,
+				 const void *, size_t, int, struct cred *);
 
 extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
 extern void ext3_xattr_put_super(struct super_block *);
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index 821efaf..76ccead 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -41,15 +41,18 @@ static int
 ext3_xattr_security_set(struct inode *inode, const char *name,
 		       const void *value, size_t size, int flags)
 {
+	struct cred *cred = current->cred;
+
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY, name,
-			      value, size, flags);
+			      value, size, flags, cred);
 }
 
 int
 ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
 {
+	struct cred *cred = current->cred;
 	int err;
 	size_t len;
 	void *value;
@@ -62,7 +65,7 @@ ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
 		return err;
 	}
 	err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY,
-				    name, value, len, 0);
+				    name, value, len, 0, cred);
 	kfree(name);
 	kfree(value);
 	return err;
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index 0327497..eead225 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -47,10 +47,12 @@ static int
 ext3_xattr_trusted_set(struct inode *inode, const char *name,
 		       const void *value, size_t size, int flags)
 {
+	struct cred *cred = current->cred;
+
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
-			      value, size, flags);
+			      value, size, flags, cred);
 }
 
 struct xattr_handler ext3_xattr_trusted_handler = {
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index 1abd8f9..1aa87ae 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -47,12 +47,14 @@ static int
 ext3_xattr_user_set(struct inode *inode, const char *name,
 		    const void *value, size_t size, int flags)
 {
+	struct cred *cred = current->cred;
+
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
 	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
-			      value, size, flags);
+			      value, size, flags, cred);
 }
 
 struct xattr_handler ext3_xattr_user_handler = {
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index a5ccfea..23db760 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -761,9 +761,10 @@ ext3_group_first_block_no(struct super_block *sb, unsigned long group_no)
 extern int ext3_bg_has_super(struct super_block *sb, int group);
 extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
 extern ext3_fsblk_t ext3_new_block (handle_t *handle, struct inode *inode,
-			ext3_fsblk_t goal, int *errp);
+			ext3_fsblk_t goal, int *errp, struct cred *cred);
 extern ext3_fsblk_t ext3_new_blocks (handle_t *handle, struct inode *inode,
-			ext3_fsblk_t goal, unsigned long *count, int *errp);
+			ext3_fsblk_t goal, unsigned long *count, int *errp,
+			struct cred *cred);
 extern void ext3_free_blocks (handle_t *handle, struct inode *inode,
 			ext3_fsblk_t block, unsigned long count);
 extern void ext3_free_blocks_sb (handle_t *handle, struct super_block *sb,
@@ -774,7 +775,8 @@ extern void ext3_check_blocks_bitmap (struct super_block *);
 extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
 						    unsigned int block_group,
 						    struct buffer_head ** bh);
-extern int ext3_should_retry_alloc(struct super_block *sb, int *retries);
+extern int ext3_should_retry_alloc(struct super_block *sb, int *retries,
+				   struct cred *cred);
 extern void ext3_init_block_alloc_info(struct inode *);
 extern void ext3_rsv_window_add(struct super_block *sb, struct ext3_reserve_window_node *rsv);
 
@@ -795,7 +797,8 @@ extern int ext3fs_dirhash(const char *name, int len, struct
 			  dx_hash_info *hinfo);
 
 /* ialloc.c */
-extern struct inode * ext3_new_inode (handle_t *, struct inode *, int);
+extern struct inode * ext3_new_inode (handle_t *, struct inode *, int,
+				      struct cred *);
 extern void ext3_free_inode (handle_t *, struct inode *);
 extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
 extern unsigned long ext3_count_free_inodes (struct super_block *);
@@ -807,11 +810,13 @@ extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
 /* inode.c */
 int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
 		struct buffer_head *bh, ext3_fsblk_t blocknr);
-struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
-struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
+struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *,
+				  struct cred *);
+struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *,
+				 struct cred *);
 int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 	sector_t iblock, unsigned long maxblocks, struct buffer_head *bh_result,
-	int create, int extend_disksize);
+	int create, int extend_disksize, struct cred *cred);
 
 extern struct inode *ext3_iget (struct super_block *, unsigned long);
 extern int  ext3_write_inode (struct inode *, int);
@@ -836,7 +841,8 @@ extern long ext3_compat_ioctl (struct file *, unsigned int, unsigned long);
 extern int ext3_orphan_add(handle_t *, struct inode *);
 extern int ext3_orphan_del(handle_t *, struct inode *);
 extern int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-				__u32 start_minor_hash, __u32 *next_hash);
+				__u32 start_minor_hash, __u32 *next_hash,
+				struct cred *cred);
 
 /* resize.c */
 extern int ext3_group_add(struct super_block *sb,


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

* [PATCH 04/52] CRED: Pass credentials down to ext3 inode allocator
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (2 preceding siblings ...)
  2007-10-12 16:05 ` [PATCH 03/52] CRED: Pass credentials down to ext3 block allocator David Howells
@ 2007-10-12 16:05 ` David Howells
  2007-10-12 16:05 ` [PATCH 05/52] CRED: Prepare TMPFS for cred passing David Howells
                   ` (49 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:05 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials down to the ext3 inode allocator.

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

 fs/ext3/ialloc.c         |    6 +++---
 fs/ext3/xattr.h          |    4 ++--
 fs/ext3/xattr_security.c |    4 ++--
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 596d8ca..7335461 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -547,7 +547,7 @@ got:
 		percpu_counter_inc(&sbi->s_dirs_counter);
 	sb->s_dirt = 1;
 
-	inode->i_uid = current->cred->uid;
+	inode->i_uid = cred->uid;
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -555,7 +555,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->cred->gid;
+		inode->i_gid = cred->gid;
 	inode->i_mode = mode;
 
 	inode->i_ino = ino;
@@ -607,7 +607,7 @@ got:
 	if (err)
 		goto fail_free_drop;
 
-	err = ext3_init_security(handle,inode, dir);
+	err = ext3_init_security(handle,inode, dir, cred);
 	if (err)
 		goto fail_free_drop;
 
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 761772a..8d00a18 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -137,10 +137,10 @@ exit_ext3_xattr(void)
 
 #ifdef CONFIG_EXT3_FS_SECURITY
 extern int ext3_init_security(handle_t *handle, struct inode *inode,
-				struct inode *dir);
+				struct inode *dir, struct cred *cred);
 #else
 static inline int ext3_init_security(handle_t *handle, struct inode *inode,
-				struct inode *dir)
+				struct inode *dir, struct cred *cred)
 {
 	return 0;
 }
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index 76ccead..9a949e3 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -50,9 +50,9 @@ ext3_xattr_security_set(struct inode *inode, const char *name,
 }
 
 int
-ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
+ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
+		   struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	int err;
 	size_t len;
 	void *value;


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

* [PATCH 05/52] CRED: Prepare TMPFS for cred passing
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (3 preceding siblings ...)
  2007-10-12 16:05 ` [PATCH 04/52] CRED: Pass credentials down to ext3 inode allocator David Howells
@ 2007-10-12 16:05 ` David Howells
  2007-10-12 16:05 ` [PATCH 06/52] CRED: Prepare RAMFS " David Howells
                   ` (48 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:05 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Prepare TMPFS for cred passing.

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

 mm/shmem.c |   22 +++++++++++++---------
 1 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index e1fa1c3..49a4b40 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1375,7 +1375,7 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
 }
 
 static struct inode *
-shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+shmem_get_inode(struct super_block *sb, int mode, dev_t dev, struct cred *cred)
 {
 	struct inode *inode;
 	struct shmem_inode_info *info;
@@ -1394,8 +1394,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 	inode = new_inode(sb);
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->cred->uid;
-		inode->i_gid = current->cred->gid;
+		inode->i_uid = cred->uid;
+		inode->i_gid = cred->gid;
 		inode->i_blocks = 0;
 		inode->i_mapping->a_ops = &shmem_aops;
 		inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
@@ -1708,7 +1708,8 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 static int
 shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
-	struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev);
+	struct cred *cred = current->cred;
+	struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev, cred);
 	int error = -ENOSPC;
 
 	if (inode) {
@@ -1849,6 +1850,7 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct
 
 static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
+	struct cred *cred = current->cred;
 	int error;
 	int len;
 	struct inode *inode;
@@ -1860,7 +1862,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 	if (len > PAGE_CACHE_SIZE)
 		return -ENAMETOOLONG;
 
-	inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
+	inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0, cred);
 	if (!inode)
 		return -ENOSPC;
 
@@ -2209,11 +2211,12 @@ static void shmem_put_super(struct super_block *sb)
 static int shmem_fill_super(struct super_block *sb,
 			    void *data, int silent)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode;
 	struct dentry *root;
 	int mode   = S_IRWXUGO | S_ISVTX;
-	uid_t uid = current->cred->uid;
-	gid_t gid = current->cred->gid;
+	uid_t uid = cred->uid;
+	gid_t gid = cred->gid;
 	int err = -ENOMEM;
 	struct shmem_sb_info *sbinfo;
 	unsigned long blocks = 0;
@@ -2267,7 +2270,7 @@ static int shmem_fill_super(struct super_block *sb,
 	sb->s_flags |= MS_POSIXACL;
 #endif
 
-	inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
+	inode = shmem_get_inode(sb, S_IFDIR | mode, 0, cred);
 	if (!inode)
 		goto failed;
 	inode->i_uid = uid;
@@ -2480,6 +2483,7 @@ module_init(init_tmpfs)
  */
 struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 {
+	struct cred *cred = current->cred;
 	int error;
 	struct file *file;
 	struct inode *inode;
@@ -2510,7 +2514,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 		goto put_dentry;
 
 	error = -ENOSPC;
-	inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
+	inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, cred);
 	if (!inode)
 		goto close_file;
 


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

* [PATCH 06/52] CRED: Prepare RAMFS for cred passing
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (4 preceding siblings ...)
  2007-10-12 16:05 ` [PATCH 05/52] CRED: Prepare TMPFS for cred passing David Howells
@ 2007-10-12 16:05 ` David Howells
  2007-10-12 16:05 ` [PATCH 07/52] CRED: Pass credentials down to ext2 block allocator David Howells
                   ` (47 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:05 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Prepare RAMFS for cred passing.

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

 fs/ramfs/inode.c      |   16 ++++++++++------
 include/linux/ramfs.h |    3 ++-
 mm/tiny-shmem.c       |    3 ++-
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index fe3642a..29100e2 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -49,14 +49,15 @@ static struct backing_dev_info ramfs_backing_dev_info = {
 			  BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
 };
 
-struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
+struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev,
+			      struct cred *cred)
 {
 	struct inode * inode = new_inode(sb);
 
 	if (inode) {
 		inode->i_mode = mode;
-		inode->i_uid = current->cred->uid;
-		inode->i_gid = current->cred->gid;
+		inode->i_uid = cred->uid;
+		inode->i_gid = cred->gid;
 		inode->i_blocks = 0;
 		inode->i_mapping->a_ops = &ramfs_aops;
 		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
@@ -92,7 +93,8 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
 static int
 ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
-	struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev);
+	struct cred *cred = current->cred;
+	struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev, cred);
 	int error = -ENOSPC;
 
 	if (inode) {
@@ -124,10 +126,11 @@ static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, stru
 
 static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode;
 	int error = -ENOSPC;
 
-	inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
+	inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0, cred);
 	if (inode) {
 		int l = strlen(symname)+1;
 		error = page_symlink(inode, symname, l);
@@ -162,6 +165,7 @@ static const struct super_operations ramfs_ops = {
 
 static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
 {
+	struct cred *cred = current->cred;
 	struct inode * inode;
 	struct dentry * root;
 
@@ -171,7 +175,7 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
 	sb->s_magic = RAMFS_MAGIC;
 	sb->s_op = &ramfs_ops;
 	sb->s_time_gran = 1;
-	inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0);
+	inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0, cred);
 	if (!inode)
 		return -ENOMEM;
 
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index b160fb1..124b0c3 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -1,7 +1,8 @@
 #ifndef _LINUX_RAMFS_H
 #define _LINUX_RAMFS_H
 
-struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev);
+struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev,
+			      struct cred *cred);
 extern int ramfs_get_sb(struct file_system_type *fs_type,
 	 int flags, const char *dev_name, void *data, struct vfsmount *mnt);
 
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
index 8803471..3d4d602 100644
--- a/mm/tiny-shmem.c
+++ b/mm/tiny-shmem.c
@@ -48,6 +48,7 @@ module_init(init_tmpfs)
  */
 struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 {
+	struct cred *cred = current->cred;
 	int error;
 	struct file *file;
 	struct inode *inode;
@@ -72,7 +73,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 		goto put_dentry;
 
 	error = -ENOSPC;
-	inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
+	inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, cred);
 	if (!inode)
 		goto close_file;
 


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

* [PATCH 07/52] CRED: Pass credentials down to ext2 block allocator
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (5 preceding siblings ...)
  2007-10-12 16:05 ` [PATCH 06/52] CRED: Prepare RAMFS " David Howells
@ 2007-10-12 16:05 ` David Howells
  2007-10-12 16:06 ` [PATCH 08/52] CRED: Pass credentials down to ext2 inode allocator David Howells
                   ` (46 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:05 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials down to the ext2 block allocator.

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

 fs/ext2/balloc.c |   11 ++++++-----
 fs/ext2/ext2.h   |    2 +-
 fs/ext2/inode.c  |   18 +++++++++++-------
 3 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index ca88579..6ec7e47 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -98,7 +98,7 @@ error_out:
  * Set sb->s_dirt here because the superblock was "logically" altered.  We
  * need to recalculate its free blocks count and flush it out.
  */
-static int reserve_blocks(struct super_block *sb, int count)
+static int reserve_blocks(struct super_block *sb, int count, struct cred *cred)
 {
 	struct ext2_sb_info *sbi = EXT2_SB(sb);
 	struct ext2_super_block *es = sbi->s_es;
@@ -112,9 +112,9 @@ static int reserve_blocks(struct super_block *sb, int count)
 		count = free_blocks;
 
 	if (free_blocks < root_blocks + count && !capable(CAP_SYS_RESOURCE) &&
-	    sbi->s_resuid != current->cred->uid &&
+	    sbi->s_resuid != cred->uid &&
 	    (sbi->s_resgid == 0 ||
-	     !in_group_p (current->cred, sbi->s_resgid))) {
+	     !in_group_p (cred, sbi->s_resgid))) {
 		/*
 		 * We are too close to reserve and we are not privileged.
 		 * Can we allocate anything at all?
@@ -325,7 +325,8 @@ got_it:
  * This function also updates quota and i_blocks field.
  */
 int ext2_new_block(struct inode *inode, unsigned long goal,
-			u32 *prealloc_count, u32 *prealloc_block, int *err)
+			u32 *prealloc_count, u32 *prealloc_block, int *err,
+			struct cred *cred)
 {
 	struct buffer_head *bitmap_bh = NULL;
 	struct buffer_head *gdp_bh;	/* bh2 */
@@ -357,7 +358,7 @@ int ext2_new_block(struct inode *inode, unsigned long goal,
 		prealloc_goal--;
 
 	dq_alloc = prealloc_goal + 1;
-	es_alloc = reserve_blocks(sb, dq_alloc);
+	es_alloc = reserve_blocks(sb, dq_alloc, cred);
 	if (!es_alloc) {
 		*err = -ENOSPC;
 		goto out_dquot;
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 85ca3de..47d68aa 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -92,7 +92,7 @@ static inline struct ext2_inode_info *EXT2_I(struct inode *inode)
 extern int ext2_bg_has_super(struct super_block *sb, int group);
 extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
 extern int ext2_new_block (struct inode *, unsigned long,
-			   __u32 *, __u32 *, int *);
+			   __u32 *, __u32 *, int *, struct cred *);
 extern void ext2_free_blocks (struct inode *, unsigned long,
 			      unsigned long);
 extern unsigned long ext2_count_free_blocks (struct super_block *);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index fa5e115..a5a6bb4 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -107,7 +107,8 @@ void ext2_discard_prealloc (struct inode * inode)
 #endif
 }
 
-static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err)
+static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err,
+			     struct cred *cred)
 {
 #ifdef EXT2FS_DEBUG
 	static unsigned long alloc_hits, alloc_attempts;
@@ -134,9 +135,10 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err)
 		if (S_ISREG(inode->i_mode))
 			result = ext2_new_block (inode, goal, 
 				 &ei->i_prealloc_count,
-				 &ei->i_prealloc_block, err);
+				 &ei->i_prealloc_block, err, cred);
 		else
-			result = ext2_new_block(inode, goal, NULL, NULL, err);
+			result = ext2_new_block(inode, goal, NULL, NULL, err,
+						cred);
 	}
 #else
 	result = ext2_new_block (inode, goal, 0, 0, err);
@@ -419,19 +421,20 @@ static int ext2_alloc_branch(struct inode *inode,
 			     int num,
 			     unsigned long goal,
 			     int *offsets,
-			     Indirect *branch)
+			     Indirect *branch,
+			     struct cred *cred)
 {
 	int blocksize = inode->i_sb->s_blocksize;
 	int n = 0;
 	int err;
 	int i;
-	int parent = ext2_alloc_block(inode, goal, &err);
+	int parent = ext2_alloc_block(inode, goal, &err, cred);
 
 	branch[0].key = cpu_to_le32(parent);
 	if (parent) for (n = 1; n < num; n++) {
 		struct buffer_head *bh;
 		/* Allocate the next block */
-		int nr = ext2_alloc_block(inode, parent, &err);
+		int nr = ext2_alloc_block(inode, parent, &err, cred);
 		if (!nr)
 			break;
 		branch[n].key = cpu_to_le32(nr);
@@ -546,6 +549,7 @@ changed:
 
 int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
 {
+	struct cred *cred = current->cred;
 	int err = -EIO;
 	int offsets[4];
 	Indirect chain[4];
@@ -597,7 +601,7 @@ out:
 
 	left = (chain + depth) - partial;
 	err = ext2_alloc_branch(inode, left, goal,
-					offsets+(partial-chain), partial);
+					offsets+(partial-chain), partial, cred);
 	if (err)
 		goto cleanup;
 


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

* [PATCH 08/52] CRED: Pass credentials down to ext2 inode allocator
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (6 preceding siblings ...)
  2007-10-12 16:05 ` [PATCH 07/52] CRED: Pass credentials down to ext2 block allocator David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 09/52] CRED: Pass credentials down to ext4 block allocator David Howells
                   ` (45 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials down to the ext2 inode allocator.

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

 fs/ext2/ext2.h   |    2 +-
 fs/ext2/ialloc.c |    6 +++---
 fs/ext2/namei.c  |   12 ++++++++----
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 47d68aa..e6d3c3d 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -116,7 +116,7 @@ extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page
 extern int ext2_sync_file (struct file *, struct dentry *, int);
 
 /* ialloc.c */
-extern struct inode * ext2_new_inode (struct inode *, int);
+extern struct inode * ext2_new_inode (struct inode *, int, struct cred *);
 extern void ext2_free_inode (struct inode *);
 extern unsigned long ext2_count_free_inodes (struct super_block *);
 extern void ext2_check_inodes_bitmap (struct super_block *);
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 03b9287..8775a8e 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -445,7 +445,7 @@ found:
 	return group;
 }
 
-struct inode *ext2_new_inode(struct inode *dir, int mode)
+struct inode *ext2_new_inode(struct inode *dir, int mode, struct cred *cred)
 {
 	struct super_block *sb;
 	struct buffer_head *bitmap_bh = NULL;
@@ -562,7 +562,7 @@ got:
 
 	sb->s_dirt = 1;
 	mark_buffer_dirty(bh2);
-	inode->i_uid = current->cred->uid;
+	inode->i_uid = cred->uid;
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -570,7 +570,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->cred->gid;
+		inode->i_gid = cred->gid;
 	inode->i_mode = mode;
 
 	inode->i_ino = ino;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 80c97fd..821a2c3 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -105,7 +105,8 @@ struct dentry *ext2_get_parent(struct dentry *child)
  */
 static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
 {
-	struct inode * inode = ext2_new_inode (dir, mode);
+	struct cred *cred = current->cred;
+	struct inode * inode = ext2_new_inode (dir, mode, cred);
 	int err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		inode->i_op = &ext2_file_inode_operations;
@@ -127,13 +128,14 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st
 
 static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev)
 {
+	struct cred *cred = current->cred;
 	struct inode * inode;
 	int err;
 
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
 
-	inode = ext2_new_inode (dir, mode);
+	inode = ext2_new_inode (dir, mode, cred);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, inode->i_mode, rdev);
@@ -149,6 +151,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_
 static int ext2_symlink (struct inode * dir, struct dentry * dentry,
 	const char * symname)
 {
+	struct cred *cred = current->cred;
 	struct super_block * sb = dir->i_sb;
 	int err = -ENAMETOOLONG;
 	unsigned l = strlen(symname)+1;
@@ -157,7 +160,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,
 	if (l > sb->s_blocksize)
 		goto out;
 
-	inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
+	inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, cred);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out;
@@ -207,6 +210,7 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
 
 static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
+	struct cred *cred = current->cred;
 	struct inode * inode;
 	int err = -EMLINK;
 
@@ -215,7 +219,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 
 	inode_inc_link_count(dir);
 
-	inode = ext2_new_inode (dir, S_IFDIR | mode);
+	inode = ext2_new_inode (dir, S_IFDIR | mode, cred);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_dir;


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

* [PATCH 09/52] CRED: Pass credentials down to ext4 block allocator
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (7 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 08/52] CRED: Pass credentials down to ext2 inode allocator David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 10/52] CRED: Pass credentials down to ext4 inode allocator David Howells
                   ` (44 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials down to the ext4 block allocator.

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

 fs/ext4/balloc.c                |   23 ++--
 fs/ext4/dir.c                   |   15 ++-
 fs/ext4/extents.c               |  129 +++++++++++++----------
 fs/ext4/ialloc.c                |    7 +
 fs/ext4/inode.c                 |  118 +++++++++++++--------
 fs/ext4/ioctl.c                 |    4 +
 fs/ext4/namei.c                 |  221 +++++++++++++++++++++++----------------
 fs/ext4/super.c                 |    8 +
 fs/ext4/xattr.c                 |   25 ++--
 fs/ext4/xattr.h                 |    7 +
 fs/ext4/xattr_trusted.c         |    4 +
 fs/ext4/xattr_user.c            |    4 +
 include/linux/ext4_fs.h         |   36 ++++--
 include/linux/ext4_fs_extents.h |    2 
 include/linux/ext4_jbd2.h       |    3 -
 15 files changed, 359 insertions(+), 247 deletions(-)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index a6ced53..e95557c 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1367,19 +1367,20 @@ out:
 /**
  * ext4_has_free_blocks()
  * @sbi:		in-core super block structure.
+ * @cred:		credentials currently in force
  *
  * Check if filesystem has at least 1 free block available for allocation.
  */
-static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
+static int ext4_has_free_blocks(struct ext4_sb_info *sbi, struct cred *cred)
 {
 	ext4_fsblk_t free_blocks, root_blocks;
 
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = ext4_r_blocks_count(sbi->s_es);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current->cred->uid &&
+		sbi->s_resuid != cred->uid &&
 		(sbi->s_resgid == 0 ||
-		 !in_group_p (current->cred, sbi->s_resgid))) {
+		 !in_group_p (cred, sbi->s_resgid))) {
 		return 0;
 	}
 	return 1;
@@ -1389,6 +1390,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
  * ext4_should_retry_alloc()
  * @sb:			super block
  * @retries		number of attemps has been made
+ * @cred:		credentials currently in force
  *
  * ext4_should_retry_alloc() is called when ENOSPC is returned, and if
  * it is profitable to retry the operation, this function will wait
@@ -1397,9 +1399,10 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
  *
  * if the total number of retries exceed three times, return FALSE.
  */
-int ext4_should_retry_alloc(struct super_block *sb, int *retries)
+int ext4_should_retry_alloc(struct super_block *sb, int *retries,
+			    struct cred *cred)
 {
-	if (!ext4_has_free_blocks(EXT4_SB(sb)) || (*retries)++ > 3)
+	if (!ext4_has_free_blocks(EXT4_SB(sb), cred) || (*retries)++ > 3)
 		return 0;
 
 	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
@@ -1414,6 +1417,7 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
  * @goal:		given target block(filesystem wide)
  * @count:		target number of blocks to allocate
  * @errp:		error code
+ * @cred:		credentials currently in force
  *
  * ext4_new_blocks uses a goal block to assist allocation.  It tries to
  * allocate block(s) from the block group contains the goal block first. If that
@@ -1422,7 +1426,8 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
  *
  */
 ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
-			ext4_fsblk_t goal, unsigned long *count, int *errp)
+			ext4_fsblk_t goal, unsigned long *count, int *errp,
+			struct cred *cred)
 {
 	struct buffer_head *bitmap_bh = NULL;
 	struct buffer_head *gdp_bh;
@@ -1478,7 +1483,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
 	if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
 		my_rsv = &block_i->rsv_window_node;
 
-	if (!ext4_has_free_blocks(sbi)) {
+	if (!ext4_has_free_blocks(sbi, cred)) {
 		*errp = -ENOSPC;
 		goto out;
 	}
@@ -1682,11 +1687,11 @@ out:
 }
 
 ext4_fsblk_t ext4_new_block(handle_t *handle, struct inode *inode,
-			ext4_fsblk_t goal, int *errp)
+			ext4_fsblk_t goal, int *errp, struct cred *cred)
 {
 	unsigned long count = 1;
 
-	return ext4_new_blocks(handle, inode, goal, &count, errp);
+	return ext4_new_blocks(handle, inode, goal, &count, errp, cred);
 }
 
 /**
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 3ab01c0..3ccd926 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -34,7 +34,7 @@ static unsigned char ext4_filetype_table[] = {
 
 static int ext4_readdir(struct file *, void *, filldir_t);
 static int ext4_dx_readdir(struct file * filp,
-			   void * dirent, filldir_t filldir);
+			   void * dirent, filldir_t filldir, struct cred *cred);
 static int ext4_release_dir (struct inode * inode,
 				struct file * filp);
 
@@ -96,6 +96,7 @@ int ext4_check_dir_entry (const char * function, struct inode * dir,
 static int ext4_readdir(struct file * filp,
 			 void * dirent, filldir_t filldir)
 {
+	struct cred *cred = filp->f_cred;
 	int error = 0;
 	unsigned long offset;
 	int i, stored;
@@ -112,7 +113,7 @@ static int ext4_readdir(struct file * filp,
 				    EXT4_FEATURE_COMPAT_DIR_INDEX) &&
 	    ((EXT4_I(inode)->i_flags & EXT4_INDEX_FL) ||
 	     ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
-		err = ext4_dx_readdir(filp, dirent, filldir);
+		err = ext4_dx_readdir(filp, dirent, filldir, cred);
 		if (err != ERR_BAD_DX_DIR) {
 			ret = err;
 			goto out;
@@ -133,7 +134,8 @@ static int ext4_readdir(struct file * filp,
 		struct buffer_head *bh = NULL;
 
 		map_bh.b_state = 0;
-		err = ext4_get_blocks_wrap(NULL, inode, blk, 1, &map_bh, 0, 0);
+		err = ext4_get_blocks_wrap(NULL, inode, blk, 1, &map_bh, 0, 0,
+					   cred);
 		if (err > 0) {
 			pgoff_t index = map_bh.b_blocknr >>
 					(PAGE_CACHE_SHIFT - inode->i_blkbits);
@@ -143,7 +145,7 @@ static int ext4_readdir(struct file * filp,
 					&filp->f_ra, filp,
 					index, 1);
 			filp->f_ra.prev_index = index;
-			bh = ext4_bread(NULL, inode, blk, 0, &err);
+			bh = ext4_bread(NULL, inode, blk, 0, &err, cred);
 		}
 
 		/*
@@ -430,7 +432,8 @@ static int call_filldir(struct file * filp, void * dirent,
 }
 
 static int ext4_dx_readdir(struct file * filp,
-			 void * dirent, filldir_t filldir)
+			 void * dirent, filldir_t filldir,
+			 struct cred *cred)
 {
 	struct dir_private_info *info = filp->private_data;
 	struct inode *inode = filp->f_path.dentry->d_inode;
@@ -480,7 +483,7 @@ static int ext4_dx_readdir(struct file * filp,
 			filp->f_version = inode->i_version;
 			ret = ext4_htree_fill_tree(filp, info->curr_hash,
 						   info->curr_minor_hash,
-						   &info->next_hash);
+						   &info->next_hash, cred);
 			if (ret < 0)
 				return ret;
 			if (ret == 0) {
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 78beb09..472be1a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -129,7 +129,8 @@ static int ext4_ext_get_access(handle_t *handle, struct inode *inode,
  *  - EIO
  */
 static int ext4_ext_dirty(handle_t *handle, struct inode *inode,
-				struct ext4_ext_path *path)
+				struct ext4_ext_path *path,
+				struct cred *cred)
 {
 	int err;
 	if (path->p_bh) {
@@ -137,7 +138,7 @@ static int ext4_ext_dirty(handle_t *handle, struct inode *inode,
 		err = ext4_journal_dirty_metadata(handle, path->p_bh);
 	} else {
 		/* path points to leaf/index in inode body */
-		err = ext4_mark_inode_dirty(handle, inode);
+		err = ext4_mark_inode_dirty(handle, inode, cred);
 	}
 	return err;
 }
@@ -177,12 +178,13 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
 static ext4_fsblk_t
 ext4_ext_new_block(handle_t *handle, struct inode *inode,
 			struct ext4_ext_path *path,
-			struct ext4_extent *ex, int *err)
+			struct ext4_extent *ex, int *err,
+			struct cred *cred)
 {
 	ext4_fsblk_t goal, newblock;
 
 	goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block));
-	newblock = ext4_new_block(handle, inode, goal, err);
+	newblock = ext4_new_block(handle, inode, goal, err, cred);
 	return newblock;
 }
 
@@ -479,7 +481,7 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block)
 
 }
 
-int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
+int ext4_ext_tree_init(handle_t *handle, struct inode *inode, struct cred *cred)
 {
 	struct ext4_extent_header *eh;
 
@@ -488,7 +490,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
 	eh->eh_entries = 0;
 	eh->eh_magic = EXT4_EXT_MAGIC;
 	eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode));
-	ext4_mark_inode_dirty(handle, inode);
+	ext4_mark_inode_dirty(handle, inode, cred);
 	ext4_ext_invalidate_cache(inode);
 	return 0;
 }
@@ -568,7 +570,8 @@ err:
  */
 static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
 				struct ext4_ext_path *curp,
-				int logical, ext4_fsblk_t ptr)
+				int logical, ext4_fsblk_t ptr,
+				struct cred *cred)
 {
 	struct ext4_extent_idx *ix;
 	int len, err;
@@ -611,7 +614,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
 			     > le16_to_cpu(curp->p_hdr->eh_max));
 	BUG_ON(ix > EXT_LAST_INDEX(curp->p_hdr));
 
-	err = ext4_ext_dirty(handle, inode, curp);
+	err = ext4_ext_dirty(handle, inode, curp, cred);
 	ext4_std_error(inode->i_sb, err);
 
 	return err;
@@ -629,7 +632,8 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
  */
 static int ext4_ext_split(handle_t *handle, struct inode *inode,
 				struct ext4_ext_path *path,
-				struct ext4_extent *newext, int at)
+				struct ext4_extent *newext, int at,
+				struct cred *cred)
 {
 	struct buffer_head *bh = NULL;
 	int depth = ext_depth(inode);
@@ -679,7 +683,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
 	/* allocate all needed blocks */
 	ext_debug("allocate %d blocks for indexes/leaf\n", depth - at);
 	for (a = 0; a < depth - at; a++) {
-		newblock = ext4_ext_new_block(handle, inode, path, newext, &err);
+		newblock = ext4_ext_new_block(handle, inode, path, newext, &err,
+					      cred);
 		if (newblock == 0)
 			goto cleanup;
 		ablocks[a] = newblock;
@@ -746,7 +751,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
 			goto cleanup;
 		path[depth].p_hdr->eh_entries =
 		     cpu_to_le16(le16_to_cpu(path[depth].p_hdr->eh_entries)-m);
-		err = ext4_ext_dirty(handle, inode, path + depth);
+		err = ext4_ext_dirty(handle, inode, path + depth, cred);
 		if (err)
 			goto cleanup;
 
@@ -827,7 +832,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
 			if (err)
 				goto cleanup;
 			path[i].p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path[i].p_hdr->eh_entries)-m);
-			err = ext4_ext_dirty(handle, inode, path + i);
+			err = ext4_ext_dirty(handle, inode, path + i, cred);
 			if (err)
 				goto cleanup;
 		}
@@ -837,7 +842,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
 
 	/* insert new index */
 	err = ext4_ext_insert_index(handle, inode, path + at,
-				    le32_to_cpu(border), newblock);
+				    le32_to_cpu(border), newblock, cred);
 
 cleanup:
 	if (bh) {
@@ -869,7 +874,8 @@ cleanup:
  */
 static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 					struct ext4_ext_path *path,
-					struct ext4_extent *newext)
+					struct ext4_extent *newext,
+					struct cred *cred)
 {
 	struct ext4_ext_path *curp = path;
 	struct ext4_extent_header *neh;
@@ -878,7 +884,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 	ext4_fsblk_t newblock;
 	int err = 0;
 
-	newblock = ext4_ext_new_block(handle, inode, path, newext, &err);
+	newblock = ext4_ext_new_block(handle, inode, path, newext, &err, cred);
 	if (newblock == 0)
 		return err;
 
@@ -940,7 +946,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 		  le32_to_cpu(fidx->ei_block), idx_pblock(fidx));
 
 	neh->eh_depth = cpu_to_le16(path->p_depth + 1);
-	err = ext4_ext_dirty(handle, inode, curp);
+	err = ext4_ext_dirty(handle, inode, curp, cred);
 out:
 	brelse(bh);
 
@@ -954,7 +960,8 @@ out:
  */
 static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
 					struct ext4_ext_path *path,
-					struct ext4_extent *newext)
+					struct ext4_extent *newext,
+					struct cred *cred)
 {
 	struct ext4_ext_path *curp;
 	int depth, i, err = 0;
@@ -974,7 +981,7 @@ repeat:
 	if (EXT_HAS_FREE_INDEX(curp)) {
 		/* if we found index with free entry, then use that
 		 * entry: create all needed subtree and add new leaf */
-		err = ext4_ext_split(handle, inode, path, newext, i);
+		err = ext4_ext_split(handle, inode, path, newext, i, cred);
 
 		/* refill path */
 		ext4_ext_drop_refs(path);
@@ -985,7 +992,7 @@ repeat:
 			err = PTR_ERR(path);
 	} else {
 		/* tree is full, time to grow in depth */
-		err = ext4_ext_grow_indepth(handle, inode, path, newext);
+		err = ext4_ext_grow_indepth(handle, inode, path, newext, cred);
 		if (err)
 			goto out;
 
@@ -1086,7 +1093,7 @@ static unsigned ext4_ext_next_leaf_block(struct inode *inode,
  * TODO: do we need to correct tree in all cases?
  */
 int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
-				struct ext4_ext_path *path)
+				struct ext4_ext_path *path, struct cred *cred)
 {
 	struct ext4_extent_header *eh;
 	int depth = ext_depth(inode);
@@ -1118,7 +1125,7 @@ int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
 	if (err)
 		return err;
 	path[k].p_idx->ei_block = border;
-	err = ext4_ext_dirty(handle, inode, path + k);
+	err = ext4_ext_dirty(handle, inode, path + k, cred);
 	if (err)
 		return err;
 
@@ -1130,7 +1137,7 @@ int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
 		if (err)
 			break;
 		path[k].p_idx->ei_block = border;
-		err = ext4_ext_dirty(handle, inode, path + k);
+		err = ext4_ext_dirty(handle, inode, path + k, cred);
 		if (err)
 			break;
 	}
@@ -1284,7 +1291,8 @@ out:
  */
 int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 				struct ext4_ext_path *path,
-				struct ext4_extent *newext)
+				struct ext4_extent *newext,
+				struct cred *cred)
 {
 	struct ext4_extent_header * eh;
 	struct ext4_extent *ex, *fex;
@@ -1356,7 +1364,7 @@ repeat:
 	 * There is no free space in the found leaf.
 	 * We're gonna add a new leaf in the tree.
 	 */
-	err = ext4_ext_create_new_leaf(handle, inode, path, newext);
+	err = ext4_ext_create_new_leaf(handle, inode, path, newext, cred);
 	if (err)
 		goto cleanup;
 	depth = ext_depth(inode);
@@ -1420,11 +1428,11 @@ merge:
 	/* try to merge extents to the left */
 
 	/* time to correct all indexes above */
-	err = ext4_ext_correct_indexes(handle, inode, path);
+	err = ext4_ext_correct_indexes(handle, inode, path, cred);
 	if (err)
 		goto cleanup;
 
-	err = ext4_ext_dirty(handle, inode, path + depth);
+	err = ext4_ext_dirty(handle, inode, path + depth, cred);
 
 cleanup:
 	if (npath) {
@@ -1638,7 +1646,7 @@ ext4_ext_in_cache(struct inode *inode, unsigned long block,
  * last index in the block only.
  */
 int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
-			struct ext4_ext_path *path)
+			struct ext4_ext_path *path, struct cred *cred)
 {
 	struct buffer_head *bh;
 	int err;
@@ -1652,7 +1660,7 @@ int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
 	if (err)
 		return err;
 	path->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1);
-	err = ext4_ext_dirty(handle, inode, path);
+	err = ext4_ext_dirty(handle, inode, path, cred);
 	if (err)
 		return err;
 	ext_debug("index is empty, remove it, free block %llu\n", leaf);
@@ -1762,7 +1770,8 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
 
 static int
 ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
-		struct ext4_ext_path *path, unsigned long start)
+		struct ext4_ext_path *path, unsigned long start,
+		struct cred *cred)
 {
 	int err = 0, correct_index = 0;
 	int depth = ext_depth(inode), credits;
@@ -1861,7 +1870,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 		if (uninitialized && num)
 			ext4_ext_mark_uninitialized(ex);
 
-		err = ext4_ext_dirty(handle, inode, path + depth);
+		err = ext4_ext_dirty(handle, inode, path + depth, cred);
 		if (err)
 			goto out;
 
@@ -1873,12 +1882,12 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 	}
 
 	if (correct_index && eh->eh_entries)
-		err = ext4_ext_correct_indexes(handle, inode, path);
+		err = ext4_ext_correct_indexes(handle, inode, path, cred);
 
 	/* if this leaf is free, then we should
 	 * remove it from index block above */
 	if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
-		err = ext4_ext_rm_idx(handle, inode, path + depth);
+		err = ext4_ext_rm_idx(handle, inode, path + depth, cred);
 
 out:
 	return err;
@@ -1905,7 +1914,8 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path)
 	return 1;
 }
 
-int ext4_ext_remove_space(struct inode *inode, unsigned long start)
+int ext4_ext_remove_space(struct inode *inode, unsigned long start,
+			  struct cred *cred)
 {
 	struct super_block *sb = inode->i_sb;
 	int depth = ext_depth(inode);
@@ -1941,7 +1951,8 @@ int ext4_ext_remove_space(struct inode *inode, unsigned long start)
 	while (i >= 0 && err == 0) {
 		if (i == depth) {
 			/* this is leaf block */
-			err = ext4_ext_rm_leaf(handle, inode, path, start);
+			err = ext4_ext_rm_leaf(handle, inode, path, start,
+					       cred);
 			/* root level has p_bh == NULL, brelse() eats this */
 			brelse(path[i].p_bh);
 			path[i].p_bh = NULL;
@@ -2003,7 +2014,8 @@ int ext4_ext_remove_space(struct inode *inode, unsigned long start)
 				/* index is empty, remove it;
 				 * handle must be already prepared by the
 				 * truncatei_leaf() */
-				err = ext4_ext_rm_idx(handle, inode, path + i);
+				err = ext4_ext_rm_idx(handle, inode, path + i,
+						      cred);
 			}
 			/* root level has p_bh == NULL, brelse() eats this */
 			brelse(path[i].p_bh);
@@ -2024,7 +2036,7 @@ int ext4_ext_remove_space(struct inode *inode, unsigned long start)
 			ext_inode_hdr(inode)->eh_depth = 0;
 			ext_inode_hdr(inode)->eh_max =
 				cpu_to_le16(ext4_ext_space_root(inode));
-			err = ext4_ext_dirty(handle, inode, path);
+			err = ext4_ext_dirty(handle, inode, path, cred);
 		}
 	}
 out:
@@ -2098,7 +2110,8 @@ void ext4_ext_release(struct super_block *sb)
 int ext4_ext_convert_to_initialized(handle_t *handle, struct inode *inode,
 					struct ext4_ext_path *path,
 					ext4_fsblk_t iblock,
-					unsigned long max_blocks)
+					unsigned long max_blocks,
+					struct cred *cred)
 {
 	struct ext4_extent *ex, newex;
 	struct ext4_extent *ex1 = NULL;
@@ -2141,7 +2154,7 @@ int ext4_ext_convert_to_initialized(handle_t *handle, struct inode *inode,
 		ext4_ext_store_pblock(ex3, newblock + max_blocks);
 		ex3->ee_len = cpu_to_le16(allocated - max_blocks);
 		ext4_ext_mark_uninitialized(ex3);
-		err = ext4_ext_insert_extent(handle, inode, path, ex3);
+		err = ext4_ext_insert_extent(handle, inode, path, ex3, cred);
 		if (err)
 			goto out;
 		/*
@@ -2198,7 +2211,8 @@ int ext4_ext_convert_to_initialized(handle_t *handle, struct inode *inode,
 		 */
 		ret = ext4_ext_try_to_merge(inode, path, ex2 - 1);
 		if (ret) {
-			err = ext4_ext_correct_indexes(handle, inode, path);
+			err = ext4_ext_correct_indexes(handle, inode, path,
+						       cred);
 			if (err)
 				goto out;
 			depth = ext_depth(inode);
@@ -2213,16 +2227,17 @@ int ext4_ext_convert_to_initialized(handle_t *handle, struct inode *inode,
 	if (!ex3) {
 		ret = ext4_ext_try_to_merge(inode, path, ex2);
 		if (ret) {
-			err = ext4_ext_correct_indexes(handle, inode, path);
+			err = ext4_ext_correct_indexes(handle, inode, path,
+						       cred);
 			if (err)
 				goto out;
 		}
 	}
 	/* Mark modified extent as dirty */
-	err = ext4_ext_dirty(handle, inode, path + depth);
+	err = ext4_ext_dirty(handle, inode, path + depth, cred);
 	goto out;
 insert:
-	err = ext4_ext_insert_extent(handle, inode, path, &newex);
+	err = ext4_ext_insert_extent(handle, inode, path, &newex, cred);
 out:
 	return err ? err : allocated;
 }
@@ -2230,7 +2245,8 @@ out:
 int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
 			ext4_fsblk_t iblock,
 			unsigned long max_blocks, struct buffer_head *bh_result,
-			int create, int extend_disksize)
+			int create, int extend_disksize,
+			struct cred *cred)
 {
 	struct ext4_ext_path *path = NULL;
 	struct ext4_extent_header *eh;
@@ -2321,7 +2337,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
 
 			ret = ext4_ext_convert_to_initialized(handle, inode,
 								path, iblock,
-								max_blocks);
+								max_blocks,
+								cred);
 			if (ret <= 0)
 				goto out2;
 			else
@@ -2373,7 +2390,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
 		allocated = le16_to_cpu(newex.ee_len);
 	else
 		allocated = max_blocks;
-	newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err);
+	newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err, cred);
 	if (!newblock)
 		goto out2;
 	ext_debug("allocate new block: goal %llu, found %llu/%lu\n",
@@ -2384,7 +2401,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
 	newex.ee_len = cpu_to_le16(allocated);
 	if (create == EXT4_CREATE_UNINITIALIZED_EXT)  /* Mark uninitialized */
 		ext4_ext_mark_uninitialized(&newex);
-	err = ext4_ext_insert_extent(handle, inode, path, &newex);
+	err = ext4_ext_insert_extent(handle, inode, path, &newex, cred);
 	if (err) {
 		/* free data blocks we just allocated */
 		ext4_free_blocks(handle, inode, ext_pblock(&newex),
@@ -2421,7 +2438,8 @@ out2:
 	return err ? err : allocated;
 }
 
-void ext4_ext_truncate(struct inode * inode, struct page *page)
+void ext4_ext_truncate(struct inode * inode, struct page *page,
+		       struct cred *cred)
 {
 	struct address_space *mapping = inode->i_mapping;
 	struct super_block *sb = inode->i_sb;
@@ -2460,11 +2478,11 @@ void ext4_ext_truncate(struct inode * inode, struct page *page)
 
 	/* we have to know where to truncate from in crash case */
 	EXT4_I(inode)->i_disksize = inode->i_size;
-	ext4_mark_inode_dirty(handle, inode);
+	ext4_mark_inode_dirty(handle, inode, cred);
 
 	last_block = (inode->i_size + sb->s_blocksize - 1)
 			>> EXT4_BLOCK_SIZE_BITS(sb);
-	err = ext4_ext_remove_space(inode, last_block);
+	err = ext4_ext_remove_space(inode, last_block, cred);
 
 	/* In a multi-transaction truncate, we only make the final
 	 * transaction synchronous.
@@ -2517,6 +2535,7 @@ int ext4_ext_writepage_trans_blocks(struct inode *inode, int num)
  */
 long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	ext4_fsblk_t block, max_blocks;
 	ext4_fsblk_t nblocks = 0;
@@ -2558,7 +2577,8 @@ retry:
 
 		ret = ext4_ext_get_blocks(handle, inode, block,
 					  max_blocks, &map_bh,
-					  EXT4_CREATE_UNINITIALIZED_EXT, 0);
+					  EXT4_CREATE_UNINITIALIZED_EXT, 0,
+					  cred);
 		WARN_ON(!ret);
 		if (!ret) {
 			ext4_error(inode->i_sb, "ext4_fallocate",
@@ -2566,7 +2586,7 @@ retry:
 				   ", block=%llu, max_blocks=%llu",
 				   inode->i_ino, block, max_blocks);
 			ret = -EIO;
-			ext4_mark_inode_dirty(handle, inode);
+			ext4_mark_inode_dirty(handle, inode, cred);
 			ret2 = ext4_journal_stop(handle);
 			break;
 		}
@@ -2574,7 +2594,7 @@ retry:
 			/* check wrap through sign-bit/zero here */
 			if ((block + ret) < 0 || (block + ret) < block) {
 				ret = -EIO;
-				ext4_mark_inode_dirty(handle, inode);
+				ext4_mark_inode_dirty(handle, inode, cred);
 				ret2 = ext4_journal_stop(handle);
 				break;
 			}
@@ -2593,13 +2613,14 @@ retry:
 				inode->i_ctime = now;
 		}
 
-		ext4_mark_inode_dirty(handle, inode);
+		ext4_mark_inode_dirty(handle, inode, cred);
 		ret2 = ext4_journal_stop(handle);
 		if (ret2)
 			break;
 	}
 
-	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+	if (ret == -ENOSPC &&
+	    ext4_should_retry_alloc(inode->i_sb, &retries, cred))
 		goto retry;
 
 	/*
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 488cc2b..937610d 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -424,7 +424,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
  * For other inodes, search forward from the parent directory's block
  * group to find a free inode.
  */
-struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
+struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode,
+			     struct cred *cred)
 {
 	struct super_block *sb;
 	struct buffer_head *bitmap_bh = NULL;
@@ -613,14 +614,14 @@ got:
 	if (err)
 		goto fail_free_drop;
 
-	err = ext4_mark_inode_dirty(handle, inode);
+	err = ext4_mark_inode_dirty(handle, inode, cred);
 	if (err) {
 		ext4_std_error(sb, err);
 		goto fail_free_drop;
 	}
 	if (test_opt(sb, EXTENTS)) {
 		EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL;
-		ext4_ext_tree_init(handle, inode);
+		ext4_ext_tree_init(handle, inode, cred);
 		if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
 			err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
 			if (err) goto fail;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c4fb1eb..f09cb71 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -179,6 +179,7 @@ static int ext4_journal_test_restart(handle_t *handle, struct inode *inode)
  */
 void ext4_delete_inode (struct inode * inode)
 {
+	struct cred *cred = &init_cred;
 	handle_t *handle;
 
 	truncate_inode_pages(&inode->i_data, 0);
@@ -220,7 +221,7 @@ void ext4_delete_inode (struct inode * inode)
 	 * having errors), but we can't free the inode if the mark_dirty
 	 * fails.
 	 */
-	if (ext4_mark_inode_dirty(handle, inode))
+	if (ext4_mark_inode_dirty(handle, inode, cred))
 		/* If that failed, just do the required in-core inode clear. */
 		clear_inode(inode);
 	else
@@ -511,10 +512,11 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned long blks,
  *	the indirect blocks(if needed) and the first direct block,
  *	@blks:	on return it will store the total number of allocated
  *		direct blocks
+ *	@cred:	the credentials currently in force
  */
 static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
 			ext4_fsblk_t goal, int indirect_blks, int blks,
-			ext4_fsblk_t new_blocks[4], int *err)
+			ext4_fsblk_t new_blocks[4], int *err, struct cred *cred)
 {
 	int target, i;
 	unsigned long count = 0;
@@ -535,7 +537,8 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
 	while (1) {
 		count = target;
 		/* allocating blocks for indirect blocks and direct blocks */
-		current_block = ext4_new_blocks(handle,inode,goal,&count,err);
+		current_block = ext4_new_blocks(handle, inode, goal, &count,
+						err, cred);
 		if (*err)
 			goto failed_out;
 
@@ -590,7 +593,7 @@ failed_out:
  */
 static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
 			int indirect_blks, int *blks, ext4_fsblk_t goal,
-			int *offsets, Indirect *branch)
+			int *offsets, Indirect *branch, struct cred *cred)
 {
 	int blocksize = inode->i_sb->s_blocksize;
 	int i, n = 0;
@@ -601,7 +604,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
 	ext4_fsblk_t current_block;
 
 	num = ext4_alloc_blocks(handle, inode, goal, indirect_blks,
-				*blks, new_blocks, &err);
+				*blks, new_blocks, &err, cred);
 	if (err)
 		return err;
 
@@ -674,13 +677,15 @@ failed:
  * @where: location of missing link
  * @num:   number of indirect blocks we are adding
  * @blks:  number of direct blocks we are adding
+ * @cred:  the credentials in force
  *
  * This function fills the missing link and does all housekeeping needed in
  * inode (->i_blocks, etc.). In case of success we end up with the full
  * chain to new block and return 0.
  */
 static int ext4_splice_branch(handle_t *handle, struct inode *inode,
-			long block, Indirect *where, int num, int blks)
+			long block, Indirect *where, int num, int blks,
+			struct cred *cred)
 {
 	int i;
 	int err = 0;
@@ -727,7 +732,7 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
 	/* We are done with atomic stuff, now do the rest of housekeeping */
 
 	inode->i_ctime = ext4_current_time(inode);
-	ext4_mark_inode_dirty(handle, inode);
+	ext4_mark_inode_dirty(handle, inode, cred);
 
 	/* had we spliced it onto indirect block? */
 	if (where->bh) {
@@ -786,7 +791,7 @@ err_out:
 int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
 		sector_t iblock, unsigned long maxblocks,
 		struct buffer_head *bh_result,
-		int create, int extend_disksize)
+		int create, int extend_disksize, struct cred *cred)
 {
 	int err = -EIO;
 	int offsets[4];
@@ -898,7 +903,7 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
 	 * Block out ext4_truncate while we alter the tree
 	 */
 	err = ext4_alloc_branch(handle, inode, indirect_blks, &count, goal,
-				offsets + (partial - chain), partial);
+				offsets + (partial - chain), partial, cred);
 
 	/*
 	 * The ext4_splice_branch call will free and forget any buffers
@@ -909,7 +914,7 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
 	 */
 	if (!err)
 		err = ext4_splice_branch(handle, inode, iblock,
-					partial, indirect_blks, count);
+					partial, indirect_blks, count, cred);
 	/*
 	 * i_disksize growing is protected by truncate_mutex.  Don't forget to
 	 * protect it if you're about to implement concurrent
@@ -945,6 +950,7 @@ out:
 static int ext4_get_block(struct inode *inode, sector_t iblock,
 			struct buffer_head *bh_result, int create)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle = ext4_journal_current_handle();
 	int ret = 0;
 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
@@ -983,7 +989,7 @@ static int ext4_get_block(struct inode *inode, sector_t iblock,
 get_block:
 	if (ret == 0) {
 		ret = ext4_get_blocks_wrap(handle, inode, iblock,
-					max_blocks, bh_result, create, 0);
+					max_blocks, bh_result, create, 0, cred);
 		if (ret > 0) {
 			bh_result->b_size = (ret << inode->i_blkbits);
 			ret = 0;
@@ -996,7 +1002,8 @@ get_block:
  * `handle' can be NULL if create is zero
  */
 struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
-				long block, int create, int *errp)
+				long block, int create, int *errp,
+				struct cred *cred)
 {
 	struct buffer_head dummy;
 	int fatal = 0, err;
@@ -1007,7 +1014,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
 	dummy.b_blocknr = -1000;
 	buffer_trace_init(&dummy.b_history);
 	err = ext4_get_blocks_wrap(handle, inode, block, 1,
-					&dummy, create, 1);
+					&dummy, create, 1, cred);
 	/*
 	 * ext4_get_blocks_handle() returns number of blocks
 	 * mapped. 0 in case of a HOLE.
@@ -1063,11 +1070,12 @@ err:
 }
 
 struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
-			       int block, int create, int *err)
+			       int block, int create, int *err,
+			       struct cred *cred)
 {
 	struct buffer_head * bh;
 
-	bh = ext4_getblk(handle, inode, block, create, err);
+	bh = ext4_getblk(handle, inode, block, create, err, cred);
 	if (!bh)
 		return bh;
 	if (buffer_uptodate(bh))
@@ -1149,6 +1157,7 @@ static int do_journal_get_write_access(handle_t *handle,
 static int ext4_prepare_write(struct file *file, struct page *page,
 			      unsigned from, unsigned to)
 {
+	struct cred *cred = file->f_cred;
 	struct inode *inode = page->mapping->host;
 	int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
 	handle_t *handle;
@@ -1174,7 +1183,8 @@ retry:
 prepare_write_failed:
 	if (ret)
 		ext4_journal_stop(handle);
-	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+	if (ret == -ENOSPC &&
+	    ext4_should_retry_alloc(inode->i_sb, &retries, cred))
 		goto retry;
 out:
 	return ret;
@@ -1260,6 +1270,7 @@ static int ext4_writeback_commit_write(struct file *file, struct page *page,
 static int ext4_journalled_commit_write(struct file *file,
 			struct page *page, unsigned from, unsigned to)
 {
+	struct cred *cred = file->f_cred;
 	handle_t *handle = ext4_journal_current_handle();
 	struct inode *inode = page->mapping->host;
 	int ret = 0, ret2;
@@ -1280,7 +1291,7 @@ static int ext4_journalled_commit_write(struct file *file,
 	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
 	if (inode->i_size > EXT4_I(inode)->i_disksize) {
 		EXT4_I(inode)->i_disksize = inode->i_size;
-		ret2 = ext4_mark_inode_dirty(handle, inode);
+		ret2 = ext4_mark_inode_dirty(handle, inode, cred);
 		if (!ret)
 			ret = ret2;
 	}
@@ -1619,6 +1630,7 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
 			unsigned long nr_segs)
 {
 	struct file *file = iocb->ki_filp;
+	struct cred *cred = file->f_cred;
 	struct inode *inode = file->f_mapping->host;
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	handle_t *handle = NULL;
@@ -1670,7 +1682,7 @@ out_stop:
 				 * ext4_mark_inode_dirty() to userspace.  So
 				 * ignore it.
 				 */
-				ext4_mark_inode_dirty(handle, inode);
+				ext4_mark_inode_dirty(handle, inode, cred);
 			}
 		}
 		err = ext4_journal_stop(handle);
@@ -1955,7 +1967,8 @@ no_top:
  */
 static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
 		struct buffer_head *bh, ext4_fsblk_t block_to_free,
-		unsigned long count, __le32 *first, __le32 *last)
+		unsigned long count, __le32 *first, __le32 *last,
+		struct cred *cred)
 {
 	__le32 *p;
 	if (try_to_extend_transaction(handle, inode)) {
@@ -1963,7 +1976,7 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
 			BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
 			ext4_journal_dirty_metadata(handle, bh);
 		}
-		ext4_mark_inode_dirty(handle, inode);
+		ext4_mark_inode_dirty(handle, inode, cred);
 		ext4_journal_test_restart(handle, inode);
 		if (bh) {
 			BUFFER_TRACE(bh, "retaking write access");
@@ -2000,6 +2013,7 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
  * @this_bh:	indirect buffer_head which contains *@first and *@last
  * @first:	array of block numbers
  * @last:	points immediately past the end of array
+ * @cred:	credentials to use
  *
  * We are freeing all blocks refered from that array (numbers are stored as
  * little-endian 32-bit) and updating @inode->i_blocks appropriately.
@@ -2014,7 +2028,8 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
  */
 static void ext4_free_data(handle_t *handle, struct inode *inode,
 			   struct buffer_head *this_bh,
-			   __le32 *first, __le32 *last)
+			   __le32 *first, __le32 *last,
+			   struct cred *cred)
 {
 	ext4_fsblk_t block_to_free = 0;    /* Starting block # of a run */
 	unsigned long count = 0;	    /* Number of blocks in the run */
@@ -2048,7 +2063,8 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
 			} else {
 				ext4_clear_blocks(handle, inode, this_bh,
 						  block_to_free,
-						  count, block_to_free_p, p);
+						  count, block_to_free_p, p,
+						  cred);
 				block_to_free = nr;
 				block_to_free_p = p;
 				count = 1;
@@ -2058,7 +2074,7 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
 
 	if (count > 0)
 		ext4_clear_blocks(handle, inode, this_bh, block_to_free,
-				  count, block_to_free_p, p);
+				  count, block_to_free_p, p, cred);
 
 	if (this_bh) {
 		BUFFER_TRACE(this_bh, "call ext4_journal_dirty_metadata");
@@ -2081,7 +2097,8 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
  */
 static void ext4_free_branches(handle_t *handle, struct inode *inode,
 			       struct buffer_head *parent_bh,
-			       __le32 *first, __le32 *last, int depth)
+			       __le32 *first, __le32 *last, int depth,
+			       struct cred *cred)
 {
 	ext4_fsblk_t nr;
 	__le32 *p;
@@ -2117,7 +2134,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
 			ext4_free_branches(handle, inode, bh,
 					   (__le32*)bh->b_data,
 					   (__le32*)bh->b_data + addr_per_block,
-					   depth);
+					   depth, cred);
 
 			/*
 			 * We've probably journalled the indirect block several
@@ -2159,7 +2176,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
 			if (is_handle_aborted(handle))
 				return;
 			if (try_to_extend_transaction(handle, inode)) {
-				ext4_mark_inode_dirty(handle, inode);
+				ext4_mark_inode_dirty(handle, inode, cred);
 				ext4_journal_test_restart(handle, inode);
 			}
 
@@ -2184,7 +2201,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
 	} else {
 		/* We have reached the bottom of the tree. */
 		BUFFER_TRACE(parent_bh, "free data blocks");
-		ext4_free_data(handle, inode, parent_bh, first, last);
+		ext4_free_data(handle, inode, parent_bh, first, last, cred);
 	}
 }
 
@@ -2218,6 +2235,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
  */
 void ext4_truncate(struct inode *inode)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	__le32 *i_data = ei->i_data;
@@ -2255,7 +2273,7 @@ void ext4_truncate(struct inode *inode)
 	}
 
 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
-		return ext4_ext_truncate(inode, page);
+		return ext4_ext_truncate(inode, page, cred);
 
 	handle = start_transaction(inode);
 	if (IS_ERR(handle)) {
@@ -2307,7 +2325,7 @@ void ext4_truncate(struct inode *inode)
 
 	if (n == 1) {		/* direct blocks */
 		ext4_free_data(handle, inode, NULL, i_data+offsets[0],
-			       i_data + EXT4_NDIR_BLOCKS);
+			       i_data + EXT4_NDIR_BLOCKS, cred);
 		goto do_indirects;
 	}
 
@@ -2317,7 +2335,8 @@ void ext4_truncate(struct inode *inode)
 		if (partial == chain) {
 			/* Shared branch grows from the inode */
 			ext4_free_branches(handle, inode, NULL,
-					   &nr, &nr+1, (chain+n-1) - partial);
+					   &nr, &nr+1, (chain+n-1) - partial,
+					   cred);
 			*partial->p = 0;
 			/*
 			 * We mark the inode dirty prior to restart,
@@ -2328,14 +2347,15 @@ void ext4_truncate(struct inode *inode)
 			BUFFER_TRACE(partial->bh, "get_write_access");
 			ext4_free_branches(handle, inode, partial->bh,
 					partial->p,
-					partial->p+1, (chain+n-1) - partial);
+					partial->p+1, (chain+n-1) - partial,
+					cred);
 		}
 	}
 	/* Clear the ends of indirect blocks on the shared branch */
 	while (partial > chain) {
 		ext4_free_branches(handle, inode, partial->bh, partial->p + 1,
 				   (__le32*)partial->bh->b_data+addr_per_block,
-				   (chain+n-1) - partial);
+				   (chain+n-1) - partial, cred);
 		BUFFER_TRACE(partial->bh, "call brelse");
 		brelse (partial->bh);
 		partial--;
@@ -2346,19 +2366,22 @@ do_indirects:
 	default:
 		nr = i_data[EXT4_IND_BLOCK];
 		if (nr) {
-			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
+			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1,
+					   cred);
 			i_data[EXT4_IND_BLOCK] = 0;
 		}
 	case EXT4_IND_BLOCK:
 		nr = i_data[EXT4_DIND_BLOCK];
 		if (nr) {
-			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
+			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2,
+					   cred);
 			i_data[EXT4_DIND_BLOCK] = 0;
 		}
 	case EXT4_DIND_BLOCK:
 		nr = i_data[EXT4_TIND_BLOCK];
 		if (nr) {
-			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
+			ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3,
+					   cred);
 			i_data[EXT4_TIND_BLOCK] = 0;
 		}
 	case EXT4_TIND_BLOCK:
@@ -2369,7 +2392,7 @@ do_indirects:
 
 	mutex_unlock(&ei->truncate_mutex);
 	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-	ext4_mark_inode_dirty(handle, inode);
+	ext4_mark_inode_dirty(handle, inode, cred);
 
 	/*
 	 * In a multi-transaction truncate, we only make the final transaction
@@ -2946,6 +2969,7 @@ int ext4_write_inode(struct inode *inode, int wait)
  */
 int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int error, rc = 0;
 	const unsigned int ia_valid = attr->ia_valid;
@@ -2977,7 +3001,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 			inode->i_uid = attr->ia_uid;
 		if (attr->ia_valid & ATTR_GID)
 			inode->i_gid = attr->ia_gid;
-		error = ext4_mark_inode_dirty(handle, inode);
+		error = ext4_mark_inode_dirty(handle, inode, cred);
 		ext4_journal_stop(handle);
 	}
 
@@ -2993,7 +3017,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 
 		error = ext4_orphan_add(handle, inode);
 		EXT4_I(inode)->i_disksize = attr->ia_size;
-		rc = ext4_mark_inode_dirty(handle, inode);
+		rc = ext4_mark_inode_dirty(handle, inode, cred);
 		if (!error)
 			error = rc;
 		ext4_journal_stop(handle);
@@ -3116,7 +3140,8 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
  * Returns 0 on success or negative error number on failure.
  */
 int ext4_expand_extra_isize(struct inode *inode, unsigned int new_extra_isize,
-			struct ext4_iloc iloc, handle_t *handle)
+			struct ext4_iloc iloc, handle_t *handle,
+			struct cred *cred)
 {
 	struct ext4_inode *raw_inode;
 	struct ext4_xattr_ibody_header *header;
@@ -3141,7 +3166,7 @@ int ext4_expand_extra_isize(struct inode *inode, unsigned int new_extra_isize,
 
 	/* try to expand with EAs present */
 	return ext4_expand_extra_isize_ea(inode, new_extra_isize,
-					  raw_inode, handle);
+					  raw_inode, handle, cred);
 }
 
 /*
@@ -3165,7 +3190,8 @@ int ext4_expand_extra_isize(struct inode *inode, unsigned int new_extra_isize,
  * to do a write_super() to free up some memory.  It has the desired
  * effect.
  */
-int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
+int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode,
+			  struct cred *cred)
 {
 	struct ext4_iloc iloc;
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
@@ -3187,7 +3213,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
 			     EXT4_DATA_TRANS_BLOCKS(inode->i_sb))) == 0) {
 			ret = ext4_expand_extra_isize(inode,
 						      sbi->s_want_extra_isize,
-						      iloc, handle);
+						      iloc, handle, cred);
 			if (ret) {
 				EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
 				if (mnt_count != sbi->s_es->s_mnt_count) {
@@ -3221,6 +3247,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
  */
 void ext4_dirty_inode(struct inode *inode)
 {
+	struct cred *cred = current->cred;
 	handle_t *current_handle = ext4_journal_current_handle();
 	handle_t *handle;
 
@@ -3235,7 +3262,7 @@ void ext4_dirty_inode(struct inode *inode)
 	} else {
 		jbd_debug(5, "marking dirty.  outer handle=%p\n",
 				current_handle);
-		ext4_mark_inode_dirty(handle, inode);
+		ext4_mark_inode_dirty(handle, inode, cred);
 	}
 	ext4_journal_stop(handle);
 out:
@@ -3271,7 +3298,8 @@ static int ext4_pin_inode(handle_t *handle, struct inode *inode)
 }
 #endif
 
-int ext4_change_inode_journal_flag(struct inode *inode, int val)
+int ext4_change_inode_journal_flag(struct inode *inode, int val,
+				   struct cred *cred)
 {
 	journal_t *journal;
 	handle_t *handle;
@@ -3316,7 +3344,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
-	err = ext4_mark_inode_dirty(handle, inode);
+	err = ext4_mark_inode_dirty(handle, inode, cred);
 	handle->h_sync = 1;
 	ext4_journal_stop(handle);
 	ext4_std_error(inode->i_sb, err);
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index c04c7cc..4110510 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -21,6 +21,7 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		unsigned long arg)
 {
 	struct ext4_inode_info *ei = EXT4_I(inode);
+	struct cred *cred = filp->f_cred;
 	unsigned int flags;
 	unsigned short rsv_window_size;
 
@@ -108,7 +109,8 @@ flags_err:
 		}
 
 		if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
-			err = ext4_change_inode_journal_flag(inode, jflag);
+			err = ext4_change_inode_journal_flag(inode, jflag,
+							     cred);
 		mutex_unlock(&inode->i_mutex);
 		return err;
 	}
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 301f41f..be28f73 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -51,13 +51,14 @@
 
 static struct buffer_head *ext4_append(handle_t *handle,
 					struct inode *inode,
-					u32 *block, int *err)
+					u32 *block, int *err,
+					struct cred *cred)
 {
 	struct buffer_head *bh;
 
 	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 
-	if ((bh = ext4_bread(handle, inode, *block, 1, err))) {
+	if ((bh = ext4_bread(handle, inode, *block, 1, err, cred))) {
 		inode->i_size += inode->i_sb->s_blocksize;
 		EXT4_I(inode)->i_disksize = inode->i_size;
 		ext4_journal_get_write_access(handle,bh);
@@ -159,7 +160,8 @@ static struct dx_frame *dx_probe(struct dentry *dentry,
 				 struct inode *dir,
 				 struct dx_hash_info *hinfo,
 				 struct dx_frame *frame,
-				 int *err);
+				 int *err,
+				 struct cred *cred);
 static void dx_release (struct dx_frame *frames);
 static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
 			struct dx_hash_info *hinfo, struct dx_map_entry map[]);
@@ -171,11 +173,13 @@ static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
 static int ext4_htree_next_block(struct inode *dir, __u32 hash,
 				 struct dx_frame *frame,
 				 struct dx_frame *frames,
-				 __u32 *start_hash);
+				 __u32 *start_hash,
+				 struct cred *cred);
 static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
-		       struct ext4_dir_entry_2 **res_dir, int *err);
+		       struct ext4_dir_entry_2 **res_dir, int *err,
+		       struct cred *cred);
 static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
-			     struct inode *inode);
+			     struct inode *inode, struct cred *cred);
 
 /*
  * Future: use high four bits of block for coalesce-on-delete flags
@@ -329,7 +333,8 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
  */
 static struct dx_frame *
 dx_probe(struct dentry *dentry, struct inode *dir,
-	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
+	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err,
+	 struct cred *cred)
 {
 	unsigned count, indirect;
 	struct dx_entry *at, *entries, *p, *q, *m;
@@ -341,7 +346,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 	frame->bh = NULL;
 	if (dentry)
 		dir = dentry->d_parent->d_inode;
-	if (!(bh = ext4_bread (NULL,dir, 0, 0, err)))
+	if (!(bh = ext4_bread (NULL,dir, 0, 0, err, cred)))
 		goto fail;
 	root = (struct dx_root *) bh->b_data;
 	if (root->info.hash_version != DX_HASH_TEA &&
@@ -436,7 +441,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 		frame->entries = entries;
 		frame->at = at;
 		if (!indirect--) return frame;
-		if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
+		if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err, cred)))
 			goto fail2;
 		at = entries = ((struct dx_node *) bh->b_data)->entries;
 		if (dx_get_limit(entries) != dx_node_limit (dir)) {
@@ -492,7 +497,8 @@ static void dx_release (struct dx_frame *frames)
 static int ext4_htree_next_block(struct inode *dir, __u32 hash,
 				 struct dx_frame *frame,
 				 struct dx_frame *frames,
-				 __u32 *start_hash)
+				 __u32 *start_hash,
+				 struct cred *cred)
 {
 	struct dx_frame *p;
 	struct buffer_head *bh;
@@ -536,7 +542,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
 	 */
 	while (num_frames--) {
 		if (!(bh = ext4_bread(NULL, dir, dx_get_block(p->at),
-				      0, &err)))
+				      0, &err, cred)))
 			return err; /* Failure */
 		p++;
 		brelse (p->bh);
@@ -563,14 +569,15 @@ static inline struct ext4_dir_entry_2 *ext4_next_entry(struct ext4_dir_entry_2 *
 static int htree_dirblock_to_tree(struct file *dir_file,
 				  struct inode *dir, int block,
 				  struct dx_hash_info *hinfo,
-				  __u32 start_hash, __u32 start_minor_hash)
+				  __u32 start_hash, __u32 start_minor_hash,
+				  struct cred *cred)
 {
 	struct buffer_head *bh;
 	struct ext4_dir_entry_2 *de, *top;
 	int err, count = 0;
 
 	dxtrace(printk("In htree dirblock_to_tree: block %d\n", block));
-	if (!(bh = ext4_bread (NULL, dir, block, 0, &err)))
+	if (!(bh = ext4_bread (NULL, dir, block, 0, &err, cred)))
 		return err;
 
 	de = (struct ext4_dir_entry_2 *) bh->b_data;
@@ -615,7 +622,8 @@ static int htree_dirblock_to_tree(struct file *dir_file,
  * or a negative error code.
  */
 int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-			 __u32 start_minor_hash, __u32 *next_hash)
+			 __u32 start_minor_hash, __u32 *next_hash,
+			 struct cred *cred)
 {
 	struct dx_hash_info hinfo;
 	struct ext4_dir_entry_2 *de;
@@ -633,13 +641,15 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 		hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
 		hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
 		count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo,
-					       start_hash, start_minor_hash);
+					       start_hash, start_minor_hash,
+					       cred);
 		*next_hash = ~0;
 		return count;
 	}
 	hinfo.hash = start_hash;
 	hinfo.minor_hash = 0;
-	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
+	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames,
+			 &err, cred);
 	if (!frame)
 		return err;
 
@@ -661,7 +671,8 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 	while (1) {
 		block = dx_get_block(frame->at);
 		ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo,
-					     start_hash, start_minor_hash);
+					     start_hash, start_minor_hash,
+					     cred);
 		if (ret < 0) {
 			err = ret;
 			goto errout;
@@ -669,7 +680,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 		count += ret;
 		hashval = ~0;
 		ret = ext4_htree_next_block(dir, HASH_NB_ALWAYS,
-					    frame, frames, &hashval);
+					    frame, frames, &hashval, cred);
 		*next_hash = hashval;
 		if (ret < 0) {
 			err = ret;
@@ -845,7 +856,8 @@ static inline int search_dirblock(struct buffer_head * bh,
  * to brelse() it when appropriate.
  */
 static struct buffer_head * ext4_find_entry (struct dentry *dentry,
-					struct ext4_dir_entry_2 ** res_dir)
+					struct ext4_dir_entry_2 ** res_dir,
+					struct cred *cred)
 {
 	struct super_block * sb;
 	struct buffer_head * bh_use[NAMEI_RA_SIZE];
@@ -871,7 +883,7 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry,
 		return NULL;
 #ifdef CONFIG_EXT4_INDEX
 	if (is_dx(dir)) {
-		bh = ext4_dx_find_entry(dentry, res_dir, &err);
+		bh = ext4_dx_find_entry(dentry, res_dir, &err, cred);
 		/*
 		 * On success, or if the error was file not found,
 		 * return.  Otherwise, fall back to doing a search the
@@ -907,7 +919,7 @@ restart:
 					break;
 				}
 				num++;
-				bh = ext4_getblk(NULL, dir, b++, 0, &err);
+				bh = ext4_getblk(NULL, dir, b++, 0, &err, cred);
 				bh_use[ra_max] = bh;
 				if (bh)
 					ll_rw_block(READ_META, 1, &bh);
@@ -959,7 +971,8 @@ cleanup_and_exit:
 
 #ifdef CONFIG_EXT4_INDEX
 static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
-		       struct ext4_dir_entry_2 **res_dir, int *err)
+		       struct ext4_dir_entry_2 **res_dir, int *err,
+		       struct cred *cred)
 {
 	struct super_block * sb;
 	struct dx_hash_info	hinfo;
@@ -976,7 +989,8 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
 	sb = dir->i_sb;
 	/* NFS may look up ".." - look at dx_root directory block */
 	if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
-		if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
+		if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err,
+				       cred)))
 			return NULL;
 	} else {
 		frame = frames;
@@ -987,7 +1001,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
 	hash = hinfo.hash;
 	do {
 		block = dx_get_block(frame->at);
-		if (!(bh = ext4_bread (NULL,dir, block, 0, err)))
+		if (!(bh = ext4_bread (NULL,dir, block, 0, err, cred)))
 			goto errout;
 		de = (struct ext4_dir_entry_2 *) bh->b_data;
 		top = (struct ext4_dir_entry_2 *) ((char *) de + sb->s_blocksize -
@@ -1009,7 +1023,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
 		brelse (bh);
 		/* Check to see if we should continue to search */
 		retval = ext4_htree_next_block(dir, hash, frame,
-					       frames, NULL);
+					       frames, NULL, cred);
 		if (retval < 0) {
 			ext4_warning(sb, __FUNCTION__,
 			     "error reading index page in directory #%lu",
@@ -1029,6 +1043,7 @@ errout:
 
 static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	struct inode * inode;
 	struct ext4_dir_entry_2 * de;
 	struct buffer_head * bh;
@@ -1036,7 +1051,7 @@ static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, str
 	if (dentry->d_name.len > EXT4_NAME_LEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	bh = ext4_find_entry(dentry, &de);
+	bh = ext4_find_entry(dentry, &de, cred);
 	inode = NULL;
 	if (bh) {
 		unsigned long ino = le32_to_cpu(de->inode);
@@ -1056,6 +1071,7 @@ static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, str
 
 struct dentry *ext4_get_parent(struct dentry *child)
 {
+	struct cred *cred = current->cred;
 	unsigned long ino;
 	struct dentry *parent;
 	struct inode *inode;
@@ -1067,7 +1083,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
 	dotdot.d_name.len = 2;
 	dotdot.d_parent = child; /* confusing, isn't it! */
 
-	bh = ext4_find_entry(&dotdot, &de);
+	bh = ext4_find_entry(&dotdot, &de, cred);
 	inode = NULL;
 	if (!bh)
 		return ERR_PTR(-ENOENT);
@@ -1166,7 +1182,8 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size)
  */
 static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 			struct buffer_head **bh,struct dx_frame *frame,
-			struct dx_hash_info *hinfo, int *error)
+			struct dx_hash_info *hinfo, int *error,
+			struct cred *cred)
 {
 	unsigned blocksize = dir->i_sb->s_blocksize;
 	unsigned count, continued;
@@ -1179,7 +1196,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 	struct ext4_dir_entry_2 *de = NULL, *de2;
 	int	err = 0;
 
-	bh2 = ext4_append (handle, dir, &newblock, &err);
+	bh2 = ext4_append (handle, dir, &newblock, &err, cred);
 	if (!(bh2)) {
 		brelse(*bh);
 		*bh = NULL;
@@ -1271,7 +1288,7 @@ errout:
  */
 static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
 			     struct inode *inode, struct ext4_dir_entry_2 *de,
-			     struct buffer_head * bh)
+			     struct buffer_head * bh, struct cred *cred)
 {
 	struct inode	*dir = dentry->d_parent->d_inode;
 	const char	*name = dentry->d_name.name;
@@ -1344,7 +1361,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
 	dir->i_mtime = dir->i_ctime = ext4_current_time(dir);
 	ext4_update_dx_flag(dir);
 	dir->i_version++;
-	ext4_mark_inode_dirty(handle, dir);
+	ext4_mark_inode_dirty(handle, dir, cred);
 	BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
 	err = ext4_journal_dirty_metadata(handle, bh);
 	if (err)
@@ -1359,7 +1376,8 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
  * directory, and adds the dentry to the indexed directory.
  */
 static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
-			    struct inode *inode, struct buffer_head *bh)
+			    struct inode *inode, struct buffer_head *bh,
+			    struct cred *cred)
 {
 	struct inode	*dir = dentry->d_parent->d_inode;
 	const char	*name = dentry->d_name.name;
@@ -1387,7 +1405,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
 	}
 	root = (struct dx_root *) bh->b_data;
 
-	bh2 = ext4_append (handle, dir, &block, &retval);
+	bh2 = ext4_append (handle, dir, &block, &retval, cred);
 	if (!(bh2)) {
 		brelse(bh);
 		return retval;
@@ -1425,12 +1443,12 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
 	frame->at = entries;
 	frame->bh = bh;
 	bh = bh2;
-	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
+	de = do_split(handle,dir, &bh, frame, &hinfo, &retval, cred);
 	dx_release (frames);
 	if (!(de))
 		return retval;
 
-	return add_dirent_to_buf(handle, dentry, inode, de, bh);
+	return add_dirent_to_buf(handle, dentry, inode, de, bh, cred);
 }
 #endif
 
@@ -1445,7 +1463,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
  * the entry, as someone else might have used it while you slept.
  */
 static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
-	struct inode *inode)
+	struct inode *inode, struct cred *cred)
 {
 	struct inode *dir = dentry->d_parent->d_inode;
 	unsigned long offset;
@@ -1465,37 +1483,39 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
 		return -EINVAL;
 #ifdef CONFIG_EXT4_INDEX
 	if (is_dx(dir)) {
-		retval = ext4_dx_add_entry(handle, dentry, inode);
+		retval = ext4_dx_add_entry(handle, dentry, inode, cred);
 		if (!retval || (retval != ERR_BAD_DX_DIR))
 			return retval;
 		EXT4_I(dir)->i_flags &= ~EXT4_INDEX_FL;
 		dx_fallback++;
-		ext4_mark_inode_dirty(handle, dir);
+		ext4_mark_inode_dirty(handle, dir, cred);
 	}
 #endif
 	blocks = dir->i_size >> sb->s_blocksize_bits;
 	for (block = 0, offset = 0; block < blocks; block++) {
-		bh = ext4_bread(handle, dir, block, 0, &retval);
+		bh = ext4_bread(handle, dir, block, 0, &retval, cred);
 		if(!bh)
 			return retval;
-		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
+		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh,
+					   cred);
 		if (retval != -ENOSPC)
 			return retval;
 
 #ifdef CONFIG_EXT4_INDEX
 		if (blocks == 1 && !dx_fallback &&
 		    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
-			return make_indexed_dir(handle, dentry, inode, bh);
+			return make_indexed_dir(handle, dentry, inode, bh,
+						cred);
 #endif
 		brelse(bh);
 	}
-	bh = ext4_append(handle, dir, &block, &retval);
+	bh = ext4_append(handle, dir, &block, &retval, cred);
 	if (!bh)
 		return retval;
 	de = (struct ext4_dir_entry_2 *) bh->b_data;
 	de->inode = 0;
 	de->rec_len = cpu_to_le16(blocksize);
-	return add_dirent_to_buf(handle, dentry, inode, de, bh);
+	return add_dirent_to_buf(handle, dentry, inode, de, bh, cred);
 }
 
 #ifdef CONFIG_EXT4_INDEX
@@ -1503,7 +1523,7 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry,
  * Returns 0 for success, or a negative error value
  */
 static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
-			     struct inode *inode)
+			     struct inode *inode, struct cred *cred)
 {
 	struct dx_frame frames[2], *frame;
 	struct dx_entry *entries, *at;
@@ -1514,13 +1534,14 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 	struct ext4_dir_entry_2 *de;
 	int err;
 
-	frame = dx_probe(dentry, NULL, &hinfo, frames, &err);
+	frame = dx_probe(dentry, NULL, &hinfo, frames, &err, cred);
 	if (!frame)
 		return err;
 	entries = frame->entries;
 	at = frame->at;
 
-	if (!(bh = ext4_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
+	if (!(bh = ext4_bread(handle,dir, dx_get_block(frame->at), 0, &err,
+			      cred)))
 		goto cleanup;
 
 	BUFFER_TRACE(bh, "get_write_access");
@@ -1528,7 +1549,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 	if (err)
 		goto journal_error;
 
-	err = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
+	err = add_dirent_to_buf(handle, dentry, inode, NULL, bh, cred);
 	if (err != -ENOSPC) {
 		bh = NULL;
 		goto cleanup;
@@ -1553,7 +1574,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			err = -ENOSPC;
 			goto cleanup;
 		}
-		bh2 = ext4_append (handle, dir, &newblock, &err);
+		bh2 = ext4_append (handle, dir, &newblock, &err, cred);
 		if (!(bh2))
 			goto cleanup;
 		node2 = (struct dx_node *)(bh2->b_data);
@@ -1618,10 +1639,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 		}
 		ext4_journal_dirty_metadata(handle, frames[0].bh);
 	}
-	de = do_split(handle, dir, &bh, frame, &hinfo, &err);
+	de = do_split(handle, dir, &bh, frame, &hinfo, &err, cred);
 	if (!de)
 		goto cleanup;
-	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
+	err = add_dirent_to_buf(handle, dentry, inode, de, bh, cred);
 	bh = NULL;
 	goto cleanup;
 
@@ -1705,11 +1726,11 @@ static void ext4_dec_count(handle_t *handle, struct inode *inode)
 
 
 static int ext4_add_nondir(handle_t *handle,
-		struct dentry *dentry, struct inode *inode)
+		struct dentry *dentry, struct inode *inode, struct cred *cred)
 {
-	int err = ext4_add_entry(handle, dentry, inode);
+	int err = ext4_add_entry(handle, dentry, inode, cred);
 	if (!err) {
-		ext4_mark_inode_dirty(handle, inode);
+		ext4_mark_inode_dirty(handle, inode, cred);
 		d_instantiate(dentry, inode);
 		return 0;
 	}
@@ -1729,6 +1750,7 @@ static int ext4_add_nondir(handle_t *handle,
 static int ext4_create (struct inode * dir, struct dentry * dentry, int mode,
 		struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	int err, retries = 0;
@@ -1743,16 +1765,17 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext4_new_inode (handle, dir, mode);
+	inode = ext4_new_inode (handle, dir, mode, cred);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		inode->i_op = &ext4_file_inode_operations;
 		inode->i_fop = &ext4_file_operations;
 		ext4_set_aops(inode);
-		err = ext4_add_nondir(handle, dentry, inode);
+		err = ext4_add_nondir(handle, dentry, inode, cred);
 	}
 	ext4_journal_stop(handle);
-	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC &&
+	    ext4_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
@@ -1760,6 +1783,7 @@ retry:
 static int ext4_mknod (struct inode * dir, struct dentry *dentry,
 			int mode, dev_t rdev)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode *inode;
 	int err, retries = 0;
@@ -1777,23 +1801,25 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext4_new_inode (handle, dir, mode);
+	inode = ext4_new_inode (handle, dir, mode, cred);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, inode->i_mode, rdev);
 #ifdef CONFIG_EXT4DEV_FS_XATTR
 		inode->i_op = &ext4_special_inode_operations;
 #endif
-		err = ext4_add_nondir(handle, dentry, inode);
+		err = ext4_add_nondir(handle, dentry, inode, cred);
 	}
 	ext4_journal_stop(handle);
-	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC &&
+	    ext4_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
 
 static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	struct buffer_head * dir_block;
@@ -1813,7 +1839,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext4_new_inode (handle, dir, S_IFDIR | mode);
+	inode = ext4_new_inode (handle, dir, S_IFDIR | mode, cred);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_stop;
@@ -1821,10 +1847,10 @@ retry:
 	inode->i_op = &ext4_dir_inode_operations;
 	inode->i_fop = &ext4_dir_operations;
 	inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-	dir_block = ext4_bread (handle, inode, 0, 1, &err);
+	dir_block = ext4_bread (handle, inode, 0, 1, &err, cred);
 	if (!dir_block) {
 		ext4_dec_count(handle, inode); /* is this nlink == 0? */
-		ext4_mark_inode_dirty(handle, inode);
+		ext4_mark_inode_dirty(handle, inode, cred);
 		iput (inode);
 		goto out_stop;
 	}
@@ -1847,21 +1873,22 @@ retry:
 	BUFFER_TRACE(dir_block, "call ext4_journal_dirty_metadata");
 	ext4_journal_dirty_metadata(handle, dir_block);
 	brelse (dir_block);
-	ext4_mark_inode_dirty(handle, inode);
-	err = ext4_add_entry (handle, dentry, inode);
+	ext4_mark_inode_dirty(handle, inode, cred);
+	err = ext4_add_entry (handle, dentry, inode, cred);
 	if (err) {
 		inode->i_nlink = 0;
-		ext4_mark_inode_dirty(handle, inode);
+		ext4_mark_inode_dirty(handle, inode, cred);
 		iput (inode);
 		goto out_stop;
 	}
 	ext4_inc_count(handle, dir);
 	ext4_update_dx_flag(dir);
-	ext4_mark_inode_dirty(handle, dir);
+	ext4_mark_inode_dirty(handle, dir, cred);
 	d_instantiate(dentry, inode);
 out_stop:
 	ext4_journal_stop(handle);
-	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC &&
+	    ext4_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
@@ -1869,7 +1896,7 @@ out_stop:
 /*
  * routine to check that the specified directory is empty (for rmdir)
  */
-static int empty_dir (struct inode * inode)
+static int empty_dir (struct inode * inode, struct cred *cred)
 {
 	unsigned long offset;
 	struct buffer_head * bh;
@@ -1879,7 +1906,7 @@ static int empty_dir (struct inode * inode)
 
 	sb = inode->i_sb;
 	if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
-	    !(bh = ext4_bread (NULL, inode, 0, 0, &err))) {
+	    !(bh = ext4_bread (NULL, inode, 0, 0, &err, cred))) {
 		if (err)
 			ext4_error(inode->i_sb, __FUNCTION__,
 				   "error %d reading directory #%lu offset 0",
@@ -1912,7 +1939,8 @@ static int empty_dir (struct inode * inode)
 			err = 0;
 			brelse (bh);
 			bh = ext4_bread (NULL, inode,
-				offset >> EXT4_BLOCK_SIZE_BITS(sb), 0, &err);
+				offset >> EXT4_BLOCK_SIZE_BITS(sb), 0, &err,
+				cred);
 			if (!bh) {
 				if (err)
 					ext4_error(sb, __FUNCTION__,
@@ -2086,6 +2114,7 @@ out_brelse:
 
 static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
@@ -2100,7 +2129,7 @@ static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
 		return PTR_ERR(handle);
 
 	retval = -ENOENT;
-	bh = ext4_find_entry (dentry, &de);
+	bh = ext4_find_entry (dentry, &de, cred);
 	if (!bh)
 		goto end_rmdir;
 
@@ -2114,7 +2143,7 @@ static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
 		goto end_rmdir;
 
 	retval = -ENOTEMPTY;
-	if (!empty_dir (inode))
+	if (!empty_dir (inode, cred))
 		goto end_rmdir;
 
 	retval = ext4_delete_entry(handle, dir, de, bh);
@@ -2132,10 +2161,10 @@ static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
 	inode->i_size = 0;
 	ext4_orphan_add(handle, inode);
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = ext4_current_time(inode);
-	ext4_mark_inode_dirty(handle, inode);
+	ext4_mark_inode_dirty(handle, inode, cred);
 	ext4_dec_count(handle, dir);
 	ext4_update_dx_flag(dir);
-	ext4_mark_inode_dirty(handle, dir);
+	ext4_mark_inode_dirty(handle, dir, cred);
 
 end_rmdir:
 	ext4_journal_stop(handle);
@@ -2145,6 +2174,7 @@ end_rmdir:
 
 static int ext4_unlink(struct inode * dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
@@ -2162,7 +2192,7 @@ static int ext4_unlink(struct inode * dir, struct dentry *dentry)
 		handle->h_sync = 1;
 
 	retval = -ENOENT;
-	bh = ext4_find_entry (dentry, &de);
+	bh = ext4_find_entry (dentry, &de, cred);
 	if (!bh)
 		goto end_unlink;
 
@@ -2183,12 +2213,12 @@ static int ext4_unlink(struct inode * dir, struct dentry *dentry)
 		goto end_unlink;
 	dir->i_ctime = dir->i_mtime = ext4_current_time(dir);
 	ext4_update_dx_flag(dir);
-	ext4_mark_inode_dirty(handle, dir);
+	ext4_mark_inode_dirty(handle, dir, cred);
 	ext4_dec_count(handle, inode);
 	if (!inode->i_nlink)
 		ext4_orphan_add(handle, inode);
 	inode->i_ctime = ext4_current_time(inode);
-	ext4_mark_inode_dirty(handle, inode);
+	ext4_mark_inode_dirty(handle, inode, cred);
 	retval = 0;
 
 end_unlink:
@@ -2200,6 +2230,7 @@ end_unlink:
 static int ext4_symlink (struct inode * dir,
 		struct dentry *dentry, const char * symname)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	int l, err, retries = 0;
@@ -2218,7 +2249,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext4_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
+	inode = ext4_new_inode (handle, dir, S_IFLNK|S_IRWXUGO, cred);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_stop;
@@ -2235,7 +2266,7 @@ retry:
 				mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
 		if (err) {
 			ext4_dec_count(handle, inode);
-			ext4_mark_inode_dirty(handle, inode);
+			ext4_mark_inode_dirty(handle, inode, cred);
 			iput (inode);
 			goto out_stop;
 		}
@@ -2245,10 +2276,11 @@ retry:
 		inode->i_size = l-1;
 	}
 	EXT4_I(inode)->i_disksize = inode->i_size;
-	err = ext4_add_nondir(handle, dentry, inode);
+	err = ext4_add_nondir(handle, dentry, inode, cred);
 out_stop:
 	ext4_journal_stop(handle);
-	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC &&
+	    ext4_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
@@ -2256,6 +2288,7 @@ out_stop:
 static int ext4_link (struct dentry * old_dentry,
 		struct inode * dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode *inode = old_dentry->d_inode;
 	int err, retries = 0;
@@ -2283,9 +2316,10 @@ retry:
 	ext4_inc_count(handle, inode);
 	atomic_inc(&inode->i_count);
 
-	err = ext4_add_nondir(handle, dentry, inode);
+	err = ext4_add_nondir(handle, dentry, inode, cred);
 	ext4_journal_stop(handle);
-	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
+	if (err == -ENOSPC &&
+	    ext4_should_retry_alloc(dir->i_sb, &retries, cred))
 		goto retry;
 	return err;
 }
@@ -2301,6 +2335,7 @@ retry:
 static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
 			   struct inode * new_dir,struct dentry *new_dentry)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * old_inode, * new_inode;
 	struct buffer_head * old_bh, * new_bh, * dir_bh;
@@ -2322,7 +2357,7 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
 	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
 		handle->h_sync = 1;
 
-	old_bh = ext4_find_entry (old_dentry, &old_de);
+	old_bh = ext4_find_entry (old_dentry, &old_de, cred);
 	/*
 	 *  Check for inode number is _not_ due to possible IO errors.
 	 *  We might rmdir the source, keep it as pwd of some process
@@ -2335,7 +2370,7 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
 		goto end_rename;
 
 	new_inode = new_dentry->d_inode;
-	new_bh = ext4_find_entry (new_dentry, &new_de);
+	new_bh = ext4_find_entry (new_dentry, &new_de, cred);
 	if (new_bh) {
 		if (!new_inode) {
 			brelse (new_bh);
@@ -2345,11 +2380,11 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
 	if (S_ISDIR(old_inode->i_mode)) {
 		if (new_inode) {
 			retval = -ENOTEMPTY;
-			if (!empty_dir (new_inode))
+			if (!empty_dir (new_inode, cred))
 				goto end_rename;
 		}
 		retval = -EIO;
-		dir_bh = ext4_bread (handle, old_inode, 0, 0, &retval);
+		dir_bh = ext4_bread (handle, old_inode, 0, 0, &retval, cred);
 		if (!dir_bh)
 			goto end_rename;
 		if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
@@ -2360,7 +2395,7 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
 			goto end_rename;
 	}
 	if (!new_bh) {
-		retval = ext4_add_entry (handle, new_dentry, old_inode);
+		retval = ext4_add_entry (handle, new_dentry, old_inode, cred);
 		if (retval)
 			goto end_rename;
 	} else {
@@ -2382,7 +2417,7 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
 	 * rename.
 	 */
 	old_inode->i_ctime = ext4_current_time(old_inode);
-	ext4_mark_inode_dirty(handle, old_inode);
+	ext4_mark_inode_dirty(handle, old_inode, cred);
 
 	/*
 	 * ok, that's it
@@ -2399,7 +2434,7 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
 		struct buffer_head *old_bh2;
 		struct ext4_dir_entry_2 *old_de2;
 
-		old_bh2 = ext4_find_entry(old_dentry, &old_de2);
+		old_bh2 = ext4_find_entry(old_dentry, &old_de2, cred);
 		if (old_bh2) {
 			retval = ext4_delete_entry(handle, old_dir,
 						   old_de2, old_bh2);
@@ -2432,12 +2467,12 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
 		} else {
 			ext4_inc_count(handle, new_dir);
 			ext4_update_dx_flag(new_dir);
-			ext4_mark_inode_dirty(handle, new_dir);
+			ext4_mark_inode_dirty(handle, new_dir, cred);
 		}
 	}
-	ext4_mark_inode_dirty(handle, old_dir);
+	ext4_mark_inode_dirty(handle, old_dir, cred);
 	if (new_inode) {
-		ext4_mark_inode_dirty(handle, new_inode);
+		ext4_mark_inode_dirty(handle, new_inode, cred);
 		if (!new_inode->i_nlink)
 			ext4_orphan_add(handle, new_inode);
 	}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 05434a1..f8d5bc7 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2791,6 +2791,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
 static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
 			       size_t len, loff_t off)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = sb_dqopt(sb)->files[type];
 	sector_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
 	int err = 0;
@@ -2808,7 +2809,7 @@ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
 	while (toread > 0) {
 		tocopy = sb->s_blocksize - offset < toread ?
 				sb->s_blocksize - offset : toread;
-		bh = ext4_bread(NULL, inode, blk, 0, &err);
+		bh = ext4_bread(NULL, inode, blk, 0, &err, cred);
 		if (err)
 			return err;
 		if (!bh)	/* A hole? */
@@ -2829,6 +2830,7 @@ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
 static ssize_t ext4_quota_write(struct super_block *sb, int type,
 				const char *data, size_t len, loff_t off)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = sb_dqopt(sb)->files[type];
 	sector_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
 	int err = 0;
@@ -2849,7 +2851,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
 	while (towrite > 0) {
 		tocopy = sb->s_blocksize - offset < towrite ?
 				sb->s_blocksize - offset : towrite;
-		bh = ext4_bread(handle, inode, blk, 1, &err);
+		bh = ext4_bread(handle, inode, blk, 1, &err, cred);
 		if (!bh)
 			goto out;
 		if (journal_quota) {
@@ -2887,7 +2889,7 @@ out:
 	}
 	inode->i_version++;
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	ext4_mark_inode_dirty(handle, inode);
+	ext4_mark_inode_dirty(handle, inode, cred);
 	mutex_unlock(&inode->i_mutex);
 	return len - towrite;
 }
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index b10d68f..0c43a31 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -686,7 +686,8 @@ cleanup:
 static int
 ext4_xattr_block_set(handle_t *handle, struct inode *inode,
 		     struct ext4_xattr_info *i,
-		     struct ext4_xattr_block_find *bs)
+		     struct ext4_xattr_block_find *bs,
+		     struct cred *cred)
 {
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *new_bh = NULL;
@@ -814,7 +815,7 @@ inserted:
 				(ext4_fsblk_t)EXT4_I(inode)->i_block_group *
 				EXT4_BLOCKS_PER_GROUP(sb);
 			ext4_fsblk_t block = ext4_new_block(handle, inode,
-							goal, &error);
+							goal, &error, cred);
 			if (error)
 				goto cleanup;
 			ea_idebug(inode, "creating block %d", block);
@@ -947,7 +948,7 @@ ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
 int
 ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
 		      const char *name, const void *value, size_t value_len,
-		      int flags)
+		      int flags, struct cred *cred)
 {
 	struct ext4_xattr_info i = {
 		.name_index = name_index,
@@ -1005,14 +1006,14 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
 		if (!is.s.not_found)
 			error = ext4_xattr_ibody_set(handle, inode, &i, &is);
 		else if (!bs.s.not_found)
-			error = ext4_xattr_block_set(handle, inode, &i, &bs);
+			error = ext4_xattr_block_set(handle, inode, &i, &bs, cred);
 	} else {
 		error = ext4_xattr_ibody_set(handle, inode, &i, &is);
 		if (!error && !bs.s.not_found) {
 			i.value = NULL;
-			error = ext4_xattr_block_set(handle, inode, &i, &bs);
+			error = ext4_xattr_block_set(handle, inode, &i, &bs, cred);
 		} else if (error == -ENOSPC) {
-			error = ext4_xattr_block_set(handle, inode, &i, &bs);
+			error = ext4_xattr_block_set(handle, inode, &i, &bs, cred);
 			if (error)
 				goto cleanup;
 			if (!is.s.not_found) {
@@ -1054,7 +1055,8 @@ cleanup:
  */
 int
 ext4_xattr_set(struct inode *inode, int name_index, const char *name,
-	       const void *value, size_t value_len, int flags)
+	       const void *value, size_t value_len, int flags,
+	       struct cred *cred)
 {
 	handle_t *handle;
 	int error, retries = 0;
@@ -1067,10 +1069,10 @@ retry:
 		int error2;
 
 		error = ext4_xattr_set_handle(handle, inode, name_index, name,
-					      value, value_len, flags);
+					      value, value_len, flags, cred);
 		error2 = ext4_journal_stop(handle);
 		if (error == -ENOSPC &&
-		    ext4_should_retry_alloc(inode->i_sb, &retries))
+		    ext4_should_retry_alloc(inode->i_sb, &retries, cred))
 			goto retry;
 		if (error == 0)
 			error = error2;
@@ -1109,7 +1111,8 @@ static void ext4_xattr_shift_entries(struct ext4_xattr_entry *entry,
  * Returns 0 on success or negative error number on failure.
  */
 int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
-			       struct ext4_inode *raw_inode, handle_t *handle)
+			       struct ext4_inode *raw_inode, handle_t *handle,
+			       struct cred *cred)
 {
 	struct ext4_xattr_ibody_header *header;
 	struct ext4_xattr_entry *entry, *last, *first;
@@ -1299,7 +1302,7 @@ retry:
 			goto cleanup;
 
 		/* Add entry which was removed from the inode into the block */
-		error = ext4_xattr_block_set(handle, inode, &i, bs);
+		error = ext4_xattr_block_set(handle, inode, &i, bs, cred);
 		if (error)
 			goto cleanup;
 		kfree(b_entry_name);
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index d7f5d6a..f737d16 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -75,14 +75,15 @@ extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
 
 extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t);
 extern int ext4_xattr_list(struct inode *, char *, size_t);
-extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
-extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
+extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int, struct cred *);
+extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int, struct cred *);
 
 extern void ext4_xattr_delete_inode(handle_t *, struct inode *);
 extern void ext4_xattr_put_super(struct super_block *);
 
 extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
-			    struct ext4_inode *raw_inode, handle_t *handle);
+			    struct ext4_inode *raw_inode, handle_t *handle,
+			    struct cred *cred);
 
 extern int init_ext4_xattr(void);
 extern void exit_ext4_xattr(void);
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
index e0f05ac..283e4c3 100644
--- a/fs/ext4/xattr_trusted.c
+++ b/fs/ext4/xattr_trusted.c
@@ -47,10 +47,12 @@ static int
 ext4_xattr_trusted_set(struct inode *inode, const char *name,
 		       const void *value, size_t size, int flags)
 {
+	struct cred *cred = current->cred;
+
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED, name,
-			      value, size, flags);
+			      value, size, flags, cred);
 }
 
 struct xattr_handler ext4_xattr_trusted_handler = {
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
index 7ed3d8e..d3dd4de 100644
--- a/fs/ext4/xattr_user.c
+++ b/fs/ext4/xattr_user.c
@@ -47,12 +47,14 @@ static int
 ext4_xattr_user_set(struct inode *inode, const char *name,
 		    const void *value, size_t size, int flags)
 {
+	struct cred *cred = current->cred;
+
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
 	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER, name,
-			      value, size, flags);
+			      value, size, flags, cred);
 }
 
 struct xattr_handler ext4_xattr_user_handler = {
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index 12354d5..7fd3ae8 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -892,9 +892,10 @@ extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb,
 extern int ext4_bg_has_super(struct super_block *sb, int group);
 extern unsigned long ext4_bg_num_gdb(struct super_block *sb, int group);
 extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode,
-			ext4_fsblk_t goal, int *errp);
+			ext4_fsblk_t goal, int *errp, struct cred *cred);
 extern ext4_fsblk_t ext4_new_blocks (handle_t *handle, struct inode *inode,
-			ext4_fsblk_t goal, unsigned long *count, int *errp);
+			ext4_fsblk_t goal, unsigned long *count, int *errp,
+			struct cred *cred);
 extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
 			ext4_fsblk_t block, unsigned long count);
 extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb,
@@ -905,7 +906,8 @@ extern void ext4_check_blocks_bitmap (struct super_block *);
 extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
 						    unsigned int block_group,
 						    struct buffer_head ** bh);
-extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
+extern int ext4_should_retry_alloc(struct super_block *sb, int *retries,
+				   struct cred *cred);
 extern void ext4_init_block_alloc_info(struct inode *);
 extern void ext4_rsv_window_add(struct super_block *sb, struct ext4_reserve_window_node *rsv);
 
@@ -926,7 +928,8 @@ extern int ext4fs_dirhash(const char *name, int len, struct
 			  dx_hash_info *hinfo);
 
 /* ialloc.c */
-extern struct inode * ext4_new_inode (handle_t *, struct inode *, int);
+extern struct inode * ext4_new_inode (handle_t *, struct inode *, int,
+				      struct cred *);
 extern void ext4_free_inode (handle_t *, struct inode *);
 extern struct inode * ext4_orphan_get (struct super_block *, unsigned long);
 extern unsigned long ext4_count_free_inodes (struct super_block *);
@@ -938,11 +941,13 @@ extern unsigned long ext4_count_free (struct buffer_head *, unsigned);
 /* inode.c */
 int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
 		struct buffer_head *bh, ext4_fsblk_t blocknr);
-struct buffer_head * ext4_getblk (handle_t *, struct inode *, long, int, int *);
-struct buffer_head * ext4_bread (handle_t *, struct inode *, int, int, int *);
+struct buffer_head * ext4_getblk (handle_t *, struct inode *, long, int, int *,
+				  struct cred *);
+struct buffer_head * ext4_bread (handle_t *, struct inode *, int, int, int *,
+				 struct cred *);
 int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
 	sector_t iblock, unsigned long maxblocks, struct buffer_head *bh_result,
-	int create, int extend_disksize);
+	int create, int extend_disksize, struct cred *cred);
 
 extern struct inode *ext4_iget(struct super_block *, unsigned long);
 extern int  ext4_write_inode (struct inode *, int);
@@ -951,7 +956,7 @@ extern void ext4_delete_inode (struct inode *);
 extern int  ext4_sync_inode (handle_t *, struct inode *);
 extern void ext4_discard_reservation (struct inode *);
 extern void ext4_dirty_inode(struct inode *);
-extern int ext4_change_inode_journal_flag(struct inode *, int);
+extern int ext4_change_inode_journal_flag(struct inode *, int, struct cred *);
 extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
 extern void ext4_truncate (struct inode *);
 extern void ext4_set_inode_flags(struct inode *);
@@ -970,7 +975,8 @@ extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long);
 extern int ext4_orphan_add(handle_t *, struct inode *);
 extern int ext4_orphan_del(handle_t *, struct inode *);
 extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-				__u32 start_minor_hash, __u32 *next_hash);
+				__u32 start_minor_hash, __u32 *next_hash,
+				struct cred *cred);
 
 /* resize.c */
 extern int ext4_group_add(struct super_block *sb,
@@ -1068,13 +1074,13 @@ extern const struct inode_operations ext4_symlink_inode_operations;
 extern const struct inode_operations ext4_fast_symlink_inode_operations;
 
 /* extents.c */
-extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
+extern int ext4_ext_tree_init(handle_t *handle, struct inode *, struct cred *);
 extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
 extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
 			ext4_fsblk_t iblock,
 			unsigned long max_blocks, struct buffer_head *bh_result,
-			int create, int extend_disksize);
-extern void ext4_ext_truncate(struct inode *, struct page *);
+			int create, int extend_disksize, struct cred *cred);
+extern void ext4_ext_truncate(struct inode *, struct page *, struct cred *);
 extern void ext4_ext_init(struct super_block *);
 extern void ext4_ext_release(struct super_block *);
 extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
@@ -1082,13 +1088,13 @@ extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
 static inline int
 ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
 			unsigned long max_blocks, struct buffer_head *bh,
-			int create, int extend_disksize)
+			int create, int extend_disksize, struct cred *cred)
 {
 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
 		return ext4_ext_get_blocks(handle, inode, block, max_blocks,
-					bh, create, extend_disksize);
+					bh, create, extend_disksize, cred);
 	return ext4_get_blocks_handle(handle, inode, block, max_blocks, bh,
-					create, extend_disksize);
+					create, extend_disksize, cred);
 }
 
 
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
index 81406f3..8f38419 100644
--- a/include/linux/ext4_fs_extents.h
+++ b/include/linux/ext4_fs_extents.h
@@ -232,7 +232,7 @@ extern int ext4_ext_try_to_merge(struct inode *inode,
 				 struct ext4_ext_path *path,
 				 struct ext4_extent *);
 extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
-extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
+extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *, struct cred *);
 extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *);
 extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *);
 
diff --git a/include/linux/ext4_jbd2.h b/include/linux/ext4_jbd2.h
index d716e63..3ec5e5b 100644
--- a/include/linux/ext4_jbd2.h
+++ b/include/linux/ext4_jbd2.h
@@ -105,7 +105,8 @@ ext4_mark_iloc_dirty(handle_t *handle,
 int ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
 			struct ext4_iloc *iloc);
 
-int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode);
+int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode,
+			  struct cred *cred);
 
 /*
  * Wrapper functions with which ext4 calls into JBD.  The intent here is


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

* [PATCH 10/52] CRED: Pass credentials down to ext4 inode allocator
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (8 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 09/52] CRED: Pass credentials down to ext4 block allocator David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 11/52] CRED: Give the get_block() callback a credentials pointer David Howells
                   ` (43 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials down to the ext4 inode allocator.

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

 fs/ext4/ialloc.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 937610d..d5626be 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -550,7 +550,7 @@ got:
 		percpu_counter_inc(&sbi->s_dirs_counter);
 	sb->s_dirt = 1;
 
-	inode->i_uid = current->cred->uid;
+	inode->i_uid = cred->uid;
 	if (test_opt (sb, GRPID))
 		inode->i_gid = dir->i_gid;
 	else if (dir->i_mode & S_ISGID) {
@@ -558,7 +558,7 @@ got:
 		if (S_ISDIR(mode))
 			mode |= S_ISGID;
 	} else
-		inode->i_gid = current->cred->gid;
+		inode->i_gid = cred->gid;
 	inode->i_mode = mode;
 
 	inode->i_ino = ino;


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

* [PATCH 11/52] CRED: Give the get_block() callback a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (9 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 10/52] CRED: Pass credentials down to ext4 inode allocator David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 12/52] CRED: Make mpage read functions take " David Howells
                   ` (42 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the get_block() callback a credentials pointer.

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

 fs/block_dev.c     |    6 ++++--
 fs/buffer.c        |   18 ++++++++++++------
 fs/direct-io.c     |    3 ++-
 fs/ext3/inode.c    |    7 ++++---
 fs/fat/inode.c     |    3 ++-
 fs/mpage.c         |    6 ++++--
 include/linux/fs.h |    3 ++-
 7 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 6339a30..1a51716 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -112,7 +112,8 @@ EXPORT_SYMBOL(sb_min_blocksize);
 
 static int
 blkdev_get_block(struct inode *inode, sector_t iblock,
-		struct buffer_head *bh, int create)
+		struct buffer_head *bh, int create,
+		struct cred *cred)
 {
 	if (iblock >= max_block(I_BDEV(inode))) {
 		if (create)
@@ -134,7 +135,8 @@ blkdev_get_block(struct inode *inode, sector_t iblock,
 
 static int
 blkdev_get_blocks(struct inode *inode, sector_t iblock,
-		struct buffer_head *bh, int create)
+		struct buffer_head *bh, int create,
+		struct cred *cred)
 {
 	sector_t end_block = max_block(I_BDEV(inode));
 	unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
diff --git a/fs/buffer.c b/fs/buffer.c
index 75b51df..c5b2ebc 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1599,6 +1599,7 @@ EXPORT_SYMBOL(unmap_underlying_metadata);
 static int __block_write_full_page(struct inode *inode, struct page *page,
 			get_block_t *get_block, struct writeback_control *wbc)
 {
+	struct cred *cred = current->cred;
 	int err;
 	sector_t block;
 	sector_t last_block;
@@ -1647,7 +1648,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
 			set_buffer_uptodate(bh);
 		} else if (!buffer_mapped(bh) && buffer_dirty(bh)) {
 			WARN_ON(bh->b_size != blocksize);
-			err = get_block(inode, block, bh, 1);
+			err = get_block(inode, block, bh, 1, cred);
 			if (err)
 				goto recover;
 			if (buffer_new(bh)) {
@@ -1760,6 +1761,7 @@ recover:
 static int __block_prepare_write(struct inode *inode, struct page *page,
 		unsigned from, unsigned to, get_block_t *get_block)
 {
+	struct cred *cred = current->cred;
 	unsigned block_start, block_end;
 	sector_t block;
 	int err = 0;
@@ -1793,7 +1795,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
 			clear_buffer_new(bh);
 		if (!buffer_mapped(bh)) {
 			WARN_ON(bh->b_size != blocksize);
-			err = get_block(inode, block, bh, 1);
+			err = get_block(inode, block, bh, 1, cred);
 			if (err)
 				break;
 			if (buffer_new(bh)) {
@@ -1917,6 +1919,7 @@ static int __block_commit_write(struct inode *inode, struct page *page,
  */
 int block_read_full_page(struct page *page, get_block_t *get_block)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = page->mapping->host;
 	sector_t iblock, lblock;
 	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
@@ -1946,7 +1949,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
 			fully_mapped = 0;
 			if (iblock < lblock) {
 				WARN_ON(bh->b_size != blocksize);
-				err = get_block(inode, iblock, bh, 0);
+				err = get_block(inode, iblock, bh, 0, cred);
 				if (err)
 					SetPageError(page);
 			}
@@ -2269,6 +2272,7 @@ static void end_buffer_read_nobh(struct buffer_head *bh, int uptodate)
 int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
 			get_block_t *get_block)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = page->mapping->host;
 	const unsigned blkbits = inode->i_blkbits;
 	const unsigned blocksize = 1 << blkbits;
@@ -2306,7 +2310,7 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
 			create = 0;
 		map_bh.b_size = blocksize;
 		ret = get_block(inode, block_in_file + block_in_page,
-					&map_bh, create);
+					&map_bh, create, cred);
 		if (ret)
 			goto failed;
 		if (!buffer_mapped(&map_bh))
@@ -2511,6 +2515,7 @@ EXPORT_SYMBOL(nobh_truncate_page);
 int block_truncate_page(struct address_space *mapping,
 			loff_t from, get_block_t *get_block)
 {
+	struct cred *cred = current->cred;
 	pgoff_t index = from >> PAGE_CACHE_SHIFT;
 	unsigned offset = from & (PAGE_CACHE_SIZE-1);
 	unsigned blocksize;
@@ -2551,7 +2556,7 @@ int block_truncate_page(struct address_space *mapping,
 	err = 0;
 	if (!buffer_mapped(bh)) {
 		WARN_ON(bh->b_size != blocksize);
-		err = get_block(inode, iblock, bh, 0);
+		err = get_block(inode, iblock, bh, 0, cred);
 		if (err)
 			goto unlock;
 		/* unmapped? It's a hole - nothing to do */
@@ -2625,12 +2630,13 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
 sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
 			    get_block_t *get_block)
 {
+	struct cred *cred = current->cred;
 	struct buffer_head tmp;
 	struct inode *inode = mapping->host;
 	tmp.b_state = 0;
 	tmp.b_blocknr = 0;
 	tmp.b_size = 1 << inode->i_blkbits;
-	get_block(inode, block, &tmp, 0);
+	get_block(inode, block, &tmp, 0, cred);
 	return tmp.b_blocknr;
 }
 
diff --git a/fs/direct-io.c b/fs/direct-io.c
index b5928a7..dacd0e8 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -499,6 +499,7 @@ static int dio_bio_reap(struct dio *dio)
 static int get_more_blocks(struct dio *dio)
 {
 	int ret;
+	struct cred *cred = current->cred;
 	struct buffer_head *map_bh = &dio->map_bh;
 	sector_t fs_startblk;	/* Into file, in filesystem-sized blocks */
 	unsigned long fs_count;	/* Number of filesystem-sized blocks */
@@ -539,7 +540,7 @@ static int get_more_blocks(struct dio *dio)
 		 * writes.
 		 */
 		ret = (*dio->get_block)(dio->inode, fs_startblk,
-						map_bh, create);
+						map_bh, create, cred);
 	}
 	return ret;
 }
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 57a2e74..a7ef05c 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -948,9 +948,9 @@ out:
 #define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
 
 static int ext3_get_block(struct inode *inode, sector_t iblock,
-			struct buffer_head *bh_result, int create)
+			struct buffer_head *bh_result, int create,
+			struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle = ext3_journal_current_handle();
 	int ret = 0;
 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
@@ -1769,6 +1769,7 @@ void ext3_set_aops(struct inode *inode)
 static int ext3_block_truncate_page(handle_t *handle, struct page *page,
 		struct address_space *mapping, loff_t from)
 {
+	struct cred *cred = current->cred;
 	ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT;
 	unsigned offset = from & (PAGE_CACHE_SIZE-1);
 	unsigned blocksize, iblock, length, pos;
@@ -1811,7 +1812,7 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
 
 	if (!buffer_mapped(bh)) {
 		BUFFER_TRACE(bh, "unmapped");
-		ext3_get_block(inode, iblock, bh, 0);
+		ext3_get_block(inode, iblock, bh, 0, cred);
 		/* unmapped? It's a hole - nothing to do */
 		if (!buffer_mapped(bh)) {
 			BUFFER_TRACE(bh, "still unmapped");
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 9ae2e9f..43c6f4a 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -106,7 +106,8 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
 }
 
 static int fat_get_block(struct inode *inode, sector_t iblock,
-			 struct buffer_head *bh_result, int create)
+			 struct buffer_head *bh_result, int create,
+			 struct cred *cred)
 {
 	struct super_block *sb = inode->i_sb;
 	unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
diff --git a/fs/mpage.c b/fs/mpage.c
index b1c3e58..7fc2dce 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -169,6 +169,7 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
 		sector_t *last_block_in_bio, struct buffer_head *map_bh,
 		unsigned long *first_logical_block, get_block_t get_block)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = page->mapping->host;
 	const unsigned blkbits = inode->i_blkbits;
 	const unsigned blocks_per_page = PAGE_CACHE_SIZE >> blkbits;
@@ -229,7 +230,7 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
 
 		if (block_in_file < last_block) {
 			map_bh->b_size = (last_block-block_in_file) << blkbits;
-			if (get_block(inode, block_in_file, map_bh, 0))
+			if (get_block(inode, block_in_file, map_bh, 0, cred))
 				goto confused;
 			*first_logical_block = block_in_file;
 		}
@@ -456,6 +457,7 @@ struct mpage_data {
 static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
 			     void *data)
 {
+	struct cred *cred = current->cred;
 	struct mpage_data *mpd = data;
 	struct bio *bio = mpd->bio;
 	struct address_space *mapping = page->mapping;
@@ -538,7 +540,7 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
 
 		map_bh.b_state = 0;
 		map_bh.b_size = 1 << blkbits;
-		if (mpd->get_block(inode, block_in_file, &map_bh, 1))
+		if (mpd->get_block(inode, block_in_file, &map_bh, 1, cred))
 			goto confused;
 		if (buffer_new(&map_bh))
 			unmap_underlying_metadata(map_bh.b_bdev,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1be33c8..6d9bfc4 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -309,7 +309,8 @@ extern void __init files_init(unsigned long);
 
 struct buffer_head;
 typedef int (get_block_t)(struct inode *inode, sector_t iblock,
-			struct buffer_head *bh_result, int create);
+			struct buffer_head *bh_result, int create,
+			struct cred *cred);
 typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 			ssize_t bytes, void *private);
 


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

* [PATCH 12/52] CRED: Make mpage read functions take a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (10 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 11/52] CRED: Give the get_block() callback a credentials pointer David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 13/52] CRED: Make block_prepare_write() and co " David Howells
                   ` (41 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make the mpage read functions take a credentials pointer.

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

 fs/ext3/inode.c       |    5 +++--
 fs/fat/inode.c        |    5 +++--
 fs/mpage.c            |   12 ++++++------
 include/linux/mpage.h |    5 +++--
 4 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index a7ef05c..70e9e6f 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1582,14 +1582,15 @@ out_unlock:
 
 static int ext3_readpage(struct file *file, struct page *page)
 {
-	return mpage_readpage(page, ext3_get_block);
+	return mpage_readpage(page, ext3_get_block, file->f_cred);
 }
 
 static int
 ext3_readpages(struct file *file, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, ext3_get_block);
+	return mpage_readpages(mapping, pages, nr_pages, ext3_get_block,
+			       file->f_cred);
 }
 
 static void ext3_invalidatepage(struct page *page, unsigned long offset)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 43c6f4a..2745ce2 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -133,13 +133,14 @@ static int fat_writepages(struct address_space *mapping,
 
 static int fat_readpage(struct file *file, struct page *page)
 {
-	return mpage_readpage(page, fat_get_block);
+	return mpage_readpage(page, fat_get_block, file->f_cred);
 }
 
 static int fat_readpages(struct file *file, struct address_space *mapping,
 			 struct list_head *pages, unsigned nr_pages)
 {
-	return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
+	return mpage_readpages(mapping, pages, nr_pages, fat_get_block,
+			       file->f_cred);
 }
 
 static int fat_prepare_write(struct file *file, struct page *page,
diff --git a/fs/mpage.c b/fs/mpage.c
index 7fc2dce..af97410 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -167,9 +167,9 @@ map_buffer_to_page(struct page *page, struct buffer_head *bh, int page_block)
 static struct bio *
 do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
 		sector_t *last_block_in_bio, struct buffer_head *map_bh,
-		unsigned long *first_logical_block, get_block_t get_block)
+		unsigned long *first_logical_block, get_block_t get_block,
+		struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = page->mapping->host;
 	const unsigned blkbits = inode->i_blkbits;
 	const unsigned blocks_per_page = PAGE_CACHE_SIZE >> blkbits;
@@ -375,7 +375,7 @@ confused:
  */
 int
 mpage_readpages(struct address_space *mapping, struct list_head *pages,
-				unsigned nr_pages, get_block_t get_block)
+		unsigned nr_pages, get_block_t get_block, struct cred *cred)
 {
 	struct bio *bio = NULL;
 	unsigned page_idx;
@@ -397,7 +397,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
 					nr_pages - page_idx,
 					&last_block_in_bio, &map_bh,
 					&first_logical_block,
-					get_block);
+					get_block, cred);
 			if (!pagevec_add(&lru_pvec, page))
 				__pagevec_lru_add(&lru_pvec);
 		} else {
@@ -415,7 +415,7 @@ EXPORT_SYMBOL(mpage_readpages);
 /*
  * This isn't called much at all
  */
-int mpage_readpage(struct page *page, get_block_t get_block)
+int mpage_readpage(struct page *page, get_block_t get_block, struct cred *cred)
 {
 	struct bio *bio = NULL;
 	sector_t last_block_in_bio = 0;
@@ -424,7 +424,7 @@ int mpage_readpage(struct page *page, get_block_t get_block)
 
 	clear_buffer_mapped(&map_bh);
 	bio = do_mpage_readpage(bio, page, 1, &last_block_in_bio,
-			&map_bh, &first_logical_block, get_block);
+			&map_bh, &first_logical_block, get_block, cred);
 	if (bio)
 		mpage_bio_submit(READ, bio);
 	return 0;
diff --git a/include/linux/mpage.h b/include/linux/mpage.h
index 068a0c9..5235842 100644
--- a/include/linux/mpage.h
+++ b/include/linux/mpage.h
@@ -14,8 +14,9 @@
 struct writeback_control;
 
 int mpage_readpages(struct address_space *mapping, struct list_head *pages,
-				unsigned nr_pages, get_block_t get_block);
-int mpage_readpage(struct page *page, get_block_t get_block);
+				unsigned nr_pages, get_block_t get_block,
+				struct cred *cred);
+int mpage_readpage(struct page *page, get_block_t get_block, struct cred *cred);
 int mpage_writepages(struct address_space *mapping,
 		struct writeback_control *wbc, get_block_t get_block);
 int mpage_writepage(struct page *page, get_block_t *get_block,


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

* [PATCH 13/52] CRED: Make block_prepare_write() and co take a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (11 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 12/52] CRED: Make mpage read functions take " David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 14/52] CRED: Provide a writeback credentials record David Howells
                   ` (40 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make block_prepare_write() and co take a credentials pointer.

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

 fs/block_dev.c              |    2 +-
 fs/buffer.c                 |   23 +++++++++++++----------
 fs/ext3/inode.c             |    8 +++++---
 fs/fat/inode.c              |    3 ++-
 include/linux/buffer_head.h |    8 +++++---
 5 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1a51716..ef70bba 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -382,7 +382,7 @@ static int blkdev_readpage(struct file * file, struct page * page)
 
 static int blkdev_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 {
-	return block_prepare_write(page, from, to, blkdev_get_block);
+	return block_prepare_write(page, from, to, blkdev_get_block, file->f_cred);
 }
 
 static int blkdev_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
diff --git a/fs/buffer.c b/fs/buffer.c
index c5b2ebc..bb6ab45 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1759,9 +1759,9 @@ recover:
 }
 
 static int __block_prepare_write(struct inode *inode, struct page *page,
-		unsigned from, unsigned to, get_block_t *get_block)
+		unsigned from, unsigned to, get_block_t *get_block,
+		struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	unsigned block_start, block_end;
 	sector_t block;
 	int err = 0;
@@ -2089,7 +2089,8 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
  */
 
 int cont_prepare_write(struct page *page, unsigned offset,
-		unsigned to, get_block_t *get_block, loff_t *bytes)
+		unsigned to, get_block_t *get_block, loff_t *bytes,
+		struct cred *cred)
 {
 	struct address_space *mapping = page->mapping;
 	struct inode *inode = mapping->host;
@@ -2116,7 +2117,8 @@ int cont_prepare_write(struct page *page, unsigned offset,
 			(*bytes)++;
 		}
 		status = __block_prepare_write(inode, new_page, zerofrom,
-						PAGE_CACHE_SIZE, get_block);
+						PAGE_CACHE_SIZE, get_block,
+						cred);
 		if (status)
 			goto out_unmap;
 		zero_user_page(new_page, zerofrom, PAGE_CACHE_SIZE - zerofrom,
@@ -2143,7 +2145,8 @@ int cont_prepare_write(struct page *page, unsigned offset,
 		if (offset <= zerofrom)
 			zerofrom = offset;
 	}
-	status = __block_prepare_write(inode, page, zerofrom, to, get_block);
+	status = __block_prepare_write(inode, page, zerofrom, to, get_block,
+				       cred);
 	if (status)
 		goto out1;
 	if (zerofrom < offset) {
@@ -2164,10 +2167,10 @@ out:
 }
 
 int block_prepare_write(struct page *page, unsigned from, unsigned to,
-			get_block_t *get_block)
+			get_block_t *get_block, struct cred *cred)
 {
 	struct inode *inode = page->mapping->host;
-	int err = __block_prepare_write(inode, page, from, to, get_block);
+	int err = __block_prepare_write(inode, page, from, to, get_block, cred);
 	if (err)
 		ClearPageUptodate(page);
 	return err;
@@ -2217,6 +2220,7 @@ block_page_mkwrite(struct vm_area_struct *vma, struct page *page,
 		   get_block_t get_block)
 {
 	struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+	struct cred *cred = vma->vm_file->f_cred;
 	unsigned long end;
 	loff_t size;
 	int ret = -EINVAL;
@@ -2235,7 +2239,7 @@ block_page_mkwrite(struct vm_area_struct *vma, struct page *page,
 	else
 		end = PAGE_CACHE_SIZE;
 
-	ret = block_prepare_write(page, 0, end, get_block);
+	ret = block_prepare_write(page, 0, end, get_block, cred);
 	if (!ret)
 		ret = block_commit_write(page, 0, end);
 
@@ -2270,9 +2274,8 @@ static void end_buffer_read_nobh(struct buffer_head *bh, int uptodate)
  * On exit the page is fully uptodate in the areas outside (from,to)
  */
 int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
-			get_block_t *get_block)
+			get_block_t *get_block, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = page->mapping->host;
 	const unsigned blkbits = inode->i_blkbits;
 	const unsigned blocksize = 1 << blkbits;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 70e9e6f..d7e1390 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1158,6 +1158,7 @@ static int ext3_prepare_write(struct file *file, struct page *page,
 			      unsigned from, unsigned to)
 {
 	struct inode *inode = page->mapping->host;
+	struct cred *cred = file->f_cred;
 	int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
 	handle_t *handle;
 	int retries = 0;
@@ -1169,9 +1170,9 @@ retry:
 		goto out;
 	}
 	if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode))
-		ret = nobh_prepare_write(page, from, to, ext3_get_block);
+		ret = nobh_prepare_write(page, from, to, ext3_get_block, cred);
 	else
-		ret = block_prepare_write(page, from, to, ext3_get_block);
+		ret = block_prepare_write(page, from, to, ext3_get_block, cred);
 	if (ret)
 		goto prepare_write_failed;
 
@@ -1525,6 +1526,7 @@ static int ext3_journalled_writepage(struct page *page,
 				struct writeback_control *wbc)
 {
 	struct inode *inode = page->mapping->host;
+	struct cred *cred = current->cred;
 	handle_t *handle = NULL;
 	int ret = 0;
 	int err;
@@ -1545,7 +1547,7 @@ static int ext3_journalled_writepage(struct page *page,
 		 */
 		ClearPageChecked(page);
 		ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE,
-					ext3_get_block);
+					ext3_get_block, cred);
 		if (ret != 0) {
 			ext3_journal_stop(handle);
 			goto out_unlock;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 2745ce2..955ccaf 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -147,7 +147,8 @@ static int fat_prepare_write(struct file *file, struct page *page,
 			     unsigned from, unsigned to)
 {
 	return cont_prepare_write(page, from, to, fat_get_block,
-				  &MSDOS_I(page->mapping->host)->mmu_private);
+				  &MSDOS_I(page->mapping->host)->mmu_private,
+				  file->f_cred);
 }
 
 static int fat_commit_write(struct file *file, struct page *page,
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 35cadad..fe059f8 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -203,9 +203,10 @@ void block_invalidatepage(struct page *page, unsigned long offset);
 int block_write_full_page(struct page *page, get_block_t *get_block,
 				struct writeback_control *wbc);
 int block_read_full_page(struct page*, get_block_t*);
-int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
+int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
+			struct cred *);
 int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
-				loff_t *);
+				loff_t *, struct cred *);
 int generic_cont_expand(struct inode *inode, loff_t size);
 int generic_cont_expand_simple(struct inode *inode, loff_t size);
 int block_commit_write(struct page *page, unsigned from, unsigned to);
@@ -216,7 +217,8 @@ sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
 int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
 int block_truncate_page(struct address_space *, loff_t, get_block_t *);
 int file_fsync(struct file *, struct dentry *, int);
-int nobh_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
+int nobh_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
+		       struct cred *);
 int nobh_commit_write(struct file *, struct page *, unsigned, unsigned);
 int nobh_truncate_page(struct address_space *, loff_t);
 int nobh_writepage(struct page *page, get_block_t *get_block,


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

* [PATCH 14/52] CRED: Provide a writeback credentials record
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (12 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 13/52] CRED: Make block_prepare_write() and co " David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 15/52] CRED: Make Ext3 use the writeback credentials David Howells
                   ` (39 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Provide a set of credentials specifically for the writeback functions.  Since
writeback may well occur in some other process context than the original write
into the pagecache, the current process's credentials are not applicable, and
so there are used instead.

If writeback needs to know the credentials, then those credentials should be
cached by prepare_write(), page_mkwrite() or similar.  Filesystems such as NFS
and AFS need to do this as they need to communicate to a remote store the
appropriate security details under which the write should be made.
Filesystems such as Ext3 should perform allocation and reservation checks
before letting the write to the pagecache occur.

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

 fs/buffer.c          |    2 +-
 fs/mpage.c           |    2 +-
 include/linux/cred.h |    1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index bb6ab45..0c8444a 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1599,7 +1599,7 @@ EXPORT_SYMBOL(unmap_underlying_metadata);
 static int __block_write_full_page(struct inode *inode, struct page *page,
 			get_block_t *get_block, struct writeback_control *wbc)
 {
-	struct cred *cred = current->cred;
+	struct cred *cred = &writeback_cred;
 	int err;
 	sector_t block;
 	sector_t last_block;
diff --git a/fs/mpage.c b/fs/mpage.c
index af97410..c04672d 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -457,7 +457,7 @@ struct mpage_data {
 static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
 			     void *data)
 {
-	struct cred *cred = current->cred;
+	struct cred *cred = &writeback_cred;
 	struct mpage_data *mpd = data;
 	struct bio *bio = mpd->bio;
 	struct address_space *mapping = page->mapping;
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 6ec0132..46f4a64 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -29,6 +29,7 @@ struct cred {
 };
 
 extern struct cred init_cred;
+#define writeback_cred init_cred
 
 struct inode;
 


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

* [PATCH 15/52] CRED: Make Ext3 use the writeback credentials
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (13 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 14/52] CRED: Provide a writeback credentials record David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 16/52] CRED: Pass credentials through the internals of ext3 truncation David Howells
                   ` (38 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make Ext3 use the writeback credentials when performing writebacks.

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

 fs/ext3/inode.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index d7e1390..73b64f3 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1526,7 +1526,7 @@ static int ext3_journalled_writepage(struct page *page,
 				struct writeback_control *wbc)
 {
 	struct inode *inode = page->mapping->host;
-	struct cred *cred = current->cred;
+	struct cred *cred = &writeback_cred;
 	handle_t *handle = NULL;
 	int ret = 0;
 	int err;


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

* [PATCH 16/52] CRED: Pass credentials through the internals of ext3 truncation
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (14 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 15/52] CRED: Make Ext3 use the writeback credentials David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 17/52] CRED: Make rpcauth_lookupcred() take a credentials pointer David Howells
                   ` (37 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the internals of ext3 truncation.

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

 fs/ext3/inode.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 73b64f3..4313d20 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1770,9 +1770,8 @@ void ext3_set_aops(struct inode *inode)
  * of that block so it doesn't yield old data if the file is later grown.
  */
 static int ext3_block_truncate_page(handle_t *handle, struct page *page,
-		struct address_space *mapping, loff_t from)
+		struct address_space *mapping, loff_t from, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT;
 	unsigned offset = from & (PAGE_CACHE_SIZE-1);
 	unsigned blocksize, iblock, length, pos;
@@ -2230,6 +2229,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
  */
 void ext3_truncate(struct inode *inode)
 {
+	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	__le32 *i_data = ei->i_data;
@@ -2281,7 +2281,8 @@ void ext3_truncate(struct inode *inode)
 					>> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
 
 	if (page)
-		ext3_block_truncate_page(handle, page, mapping, inode->i_size);
+		ext3_block_truncate_page(handle, page, mapping, inode->i_size,
+					 cred);
 
 	n = ext3_block_to_path(inode, last_block, offsets, NULL);
 	if (n == 0)


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

* [PATCH 17/52] CRED: Make rpcauth_lookupcred() take a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (15 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 16/52] CRED: Pass credentials through the internals of ext3 truncation David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 18/52] CRED: Make rpcauth_bindcred() " David Howells
                   ` (36 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make rpcauth_lookupcred() take a credentials pointer.

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

 fs/nfs/dir.c                |    3 ++-
 fs/nfs/inode.c              |    2 +-
 fs/nfs/nfs4proc.c           |   12 ++++++++----
 fs/nfs/unlink.c             |    3 ++-
 include/linux/sunrpc/auth.h |    3 ++-
 net/sunrpc/auth.c           |    4 ++--
 6 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e4a04d1..53b9e24 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1959,6 +1959,7 @@ out:
 
 int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct rpc_cred *cred;
 	int res = 0;
 
@@ -1995,7 +1996,7 @@ force_lookup:
 	if (!NFS_PROTO(inode)->access)
 		goto out_notsup;
 
-	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0, acred);
 	if (!IS_ERR(cred)) {
 		res = nfs_do_access(inode, cred, mask);
 		put_rpccred(cred);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 71a49c3..0dd2ac3 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -555,7 +555,7 @@ int nfs_open(struct inode *inode, struct file *filp)
 	struct nfs_open_context *ctx;
 	struct rpc_cred *cred;
 
-	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0, filp->f_cred);
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
 	ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4b90e17..9a02b61 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1403,6 +1403,7 @@ out_close:
 struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct path path = {
 		.mnt = nd->mnt,
 		.dentry = dentry,
@@ -1422,7 +1423,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 		BUG_ON(nd->intent.open.flags & O_CREAT);
 	}
 
-	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0, acred);
 	if (IS_ERR(cred))
 		return (struct dentry *)cred;
 	state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
@@ -1442,6 +1443,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 int
 nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct path path = {
 		.mnt = nd->mnt,
 		.dentry = dentry,
@@ -1449,7 +1451,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
 	struct rpc_cred *cred;
 	struct nfs4_state *state;
 
-	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0, acred);
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
 	state = nfs4_do_open(dir, &path, openflags, NULL, cred);
@@ -1657,6 +1659,7 @@ static int
 nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 		  struct iattr *sattr)
 {
+	struct cred *acred = current->cred;
 	struct rpc_cred *cred;
 	struct inode *inode = dentry->d_inode;
 	struct nfs_open_context *ctx;
@@ -1665,7 +1668,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 	nfs_fattr_init(fattr);
 	
-	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0, acred);
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
 
@@ -1885,6 +1888,7 @@ static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                  int flags, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct path path = {
 		.mnt = nd->mnt,
 		.dentry = dentry,
@@ -1893,7 +1897,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 	struct rpc_cred *cred;
 	int status = 0;
 
-	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0, acred);
 	if (IS_ERR(cred)) {
 		status = PTR_ERR(cred);
 		goto out;
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 045ab80..c6bcd5c 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -144,6 +144,7 @@ out_free:
 int
 nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *acred = current->cred;
 	struct nfs_unlinkdata *data;
 	int status = -ENOMEM;
 
@@ -151,7 +152,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 	if (data == NULL)
 		goto out;
 
-	data->cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
+	data->cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0, acred);
 	if (IS_ERR(data->cred)) {
 		status = PTR_ERR(data->cred);
 		goto out_free;
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 8f97f9a..63fe023 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -129,7 +129,8 @@ struct rpc_auth *	rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
 void			rpcauth_release(struct rpc_auth *);
 struct rpc_cred *	rpcauth_lookup_credcache(struct rpc_auth *, struct cred *, int);
 void			rpcauth_init_cred(struct rpc_cred *, const struct cred *, struct rpc_auth *, const struct rpc_credops *);
-struct rpc_cred *	rpcauth_lookupcred(struct rpc_auth *, int);
+struct rpc_cred *	rpcauth_lookupcred(struct rpc_auth *, int,
+					   struct cred *);
 struct rpc_cred *	rpcauth_bindcred(struct rpc_task *);
 void			rpcauth_holdcred(struct rpc_task *);
 void			put_rpccred(struct rpc_cred *);
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 362a0de..d1cc555 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -334,11 +334,11 @@ out:
 }
 
 struct rpc_cred *
-rpcauth_lookupcred(struct rpc_auth *auth, int flags)
+rpcauth_lookupcred(struct rpc_auth *auth, int flags, struct cred *acred)
 {
 	dprintk("RPC:       looking up %s cred\n",
 		auth->au_ops->au_name);
-	return auth->au_ops->lookup_cred(auth, current->cred, flags);
+	return auth->au_ops->lookup_cred(auth, acred, flags);
 }
 
 void


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

* [PATCH 18/52] CRED: Make rpcauth_bindcred() take a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (16 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 17/52] CRED: Make rpcauth_lookupcred() take a credentials pointer David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:06 ` [PATCH 19/52] CRED: Add a credentials pointer to struct rpc_task David Howells
                   ` (35 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make rpcauth_bindcred() take a credentials pointer.

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

 fs/nfs/nfs3proc.c           |    6 +++---
 fs/nfs/nfs4proc.c           |   18 +++++++++---------
 fs/nfs/proc.c               |    4 ++--
 fs/nfs/unlink.c             |    2 +-
 include/linux/sunrpc/auth.h |    2 +-
 include/linux/sunrpc/clnt.h |    3 ++-
 net/sunrpc/auth.c           |    4 ++--
 net/sunrpc/clnt.c           |    7 ++++---
 net/sunrpc/rpcb_clnt.c      |    2 +-
 9 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index c7ca5d7..329e6a2 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -739,7 +739,7 @@ static void nfs3_proc_read_setup(struct nfs_read_data *data)
 		.rpc_cred	= data->cred,
 	};
 
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(&data->task, &msg, 0, current->cred);
 }
 
 static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -768,7 +768,7 @@ static void nfs3_proc_write_setup(struct nfs_write_data *data, int how)
 	}
 
 	/* Finalize the task. */
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(&data->task, &msg, 0, current->cred);
 }
 
 static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -789,7 +789,7 @@ static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
 		.rpc_cred	= data->cred,
 	};
 
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(&data->task, &msg, 0, current->cred);
 }
 
 static int
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9a02b61..24c5021 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -729,7 +729,7 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
 		.rpc_cred = data->owner->so_cred,
 	};
 	data->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0);
+	rpc_call_setup(task, &msg, 0, current->cred);
 }
 
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
@@ -838,7 +838,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
 		nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
 	}
 	data->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0);
+	rpc_call_setup(task, &msg, 0, current->cred);
 	return;
 out_no_action:
 	task->tk_action = NULL;
@@ -1316,7 +1316,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
 		calldata->arg.open_flags = FMODE_WRITE;
 	}
 	calldata->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0);
+	rpc_call_setup(task, &msg, 0, current->cred);
 }
 
 static const struct rpc_call_ops nfs4_close_ops = {
@@ -2434,7 +2434,7 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data)
 
 	data->timestamp   = jiffies;
 
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(&data->task, &msg, 0, current->cred);
 }
 
 static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -2478,7 +2478,7 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, int how)
 	data->timestamp   = jiffies;
 
 	/* Finalize the task. */
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(&data->task, &msg, 0, current->cred);
 }
 
 static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -2507,7 +2507,7 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
 	data->args.bitmask = server->attr_bitmask;
 	data->res.server = server;
 
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(&data->task, &msg, 0, current->cred);
 }
 
 /*
@@ -3007,7 +3007,7 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata)
 		.rpc_cred = data->cred,
 	};
 	nfs_fattr_init(data->res.fattr);
-	rpc_call_setup(task, &msg, 0);
+	rpc_call_setup(task, &msg, 0, current->cred);
 }
 
 static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
@@ -3255,7 +3255,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 		return;
 	}
 	calldata->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0);
+	rpc_call_setup(task, &msg, 0, current->cred);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -3384,7 +3384,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
 		data->arg.new_lock_owner = 1;
 	}
 	data->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0);
+	rpc_call_setup(task, &msg, 0, current->cred);
 out:
 	dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status);
 }
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 845cdde..d6baeb4 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -570,7 +570,7 @@ static void nfs_proc_read_setup(struct nfs_read_data *data)
 		.rpc_cred	= data->cred,
 	};
 
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(&data->task, &msg, 0, current->cred);
 }
 
 static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -593,7 +593,7 @@ static void nfs_proc_write_setup(struct nfs_write_data *data, int how)
 	data->args.stable = NFS_FILE_SYNC;
 
 	/* Finalize the task. */
-	rpc_call_setup(&data->task, &msg, 0);
+	rpc_call_setup(&data->task, &msg, 0, current->cred);
 }
 
 static void
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index c6bcd5c..b5e2575 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -68,7 +68,7 @@ static void nfs_async_unlink_init(struct rpc_task *task, void *calldata)
 
 	nfs_begin_data_update(dir);
 	NFS_PROTO(dir)->unlink_setup(&msg, dir);
-	rpc_call_setup(task, &msg, 0);
+	rpc_call_setup(task, &msg, 0, current->cred);
 }
 
 /**
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 63fe023..34b7166 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -131,7 +131,7 @@ struct rpc_cred *	rpcauth_lookup_credcache(struct rpc_auth *, struct cred *, int
 void			rpcauth_init_cred(struct rpc_cred *, const struct cred *, struct rpc_auth *, const struct rpc_credops *);
 struct rpc_cred *	rpcauth_lookupcred(struct rpc_auth *, int,
 					   struct cred *);
-struct rpc_cred *	rpcauth_bindcred(struct rpc_task *);
+struct rpc_cred *	rpcauth_bindcred(struct rpc_task *, struct cred *);
 void			rpcauth_holdcred(struct rpc_task *);
 void			put_rpccred(struct rpc_cred *);
 void			rpcauth_unbindcred(struct rpc_task *);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index c0d9d14..ae52668 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -126,7 +126,8 @@ int		rpcb_register(u32, u32, int, unsigned short, int *);
 int		rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int);
 void		rpcb_getport_async(struct rpc_task *);
 
-void		rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
+void		rpc_call_setup(struct rpc_task *, struct rpc_message *, int,
+			       struct cred *);
 
 int		rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
 			       int flags, const struct rpc_call_ops *tk_ops,
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index d1cc555..7cb8d5e 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -359,7 +359,7 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct cred *acred,
 EXPORT_SYMBOL(rpcauth_init_cred);
 
 struct rpc_cred *
-rpcauth_bindcred(struct rpc_task *task)
+rpcauth_bindcred(struct rpc_task *task, struct cred *acred)
 {
 	struct rpc_auth *auth = task->tk_client->cl_auth;
 	struct rpc_cred *ret;
@@ -369,7 +369,7 @@ rpcauth_bindcred(struct rpc_task *task)
 		task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
 	if (task->tk_flags & RPC_TASK_ROOTCREDS)
 		flags |= RPCAUTH_LOOKUP_ROOTCREDS;
-	ret = auth->au_ops->lookup_cred(auth, current->cred, flags);
+	ret = auth->au_ops->lookup_cred(auth, acred, flags);
 	if (!IS_ERR(ret))
 		task->tk_msg.rpc_cred = ret;
 	else
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 52429b1..a02a776 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -534,7 +534,7 @@ struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
 	/* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
 	rpc_task_sigmask(task, &oldset);
 	if (msg != NULL) {
-		rpc_call_setup(task, msg, 0);
+		rpc_call_setup(task, msg, 0, current->cred);
 		if (task->tk_status != 0) {
 			ret = ERR_PTR(task->tk_status);
 			rpc_put_task(task);
@@ -607,7 +607,8 @@ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
 EXPORT_SYMBOL(rpc_run_task);
 
 void
-rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
+rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags,
+	       struct cred *acred)
 {
 	task->tk_msg   = *msg;
 	task->tk_flags |= flags;
@@ -615,7 +616,7 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
 	if (task->tk_msg.rpc_cred != NULL)
 		rpcauth_holdcred(task);
 	else
-		rpcauth_bindcred(task);
+		rpcauth_bindcred(task, acred);
 
 	if (task->tk_status == 0)
 		task->tk_action = call_start;
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index d1740db..6d167f0 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -152,7 +152,7 @@ static void rpcb_getport_prepare(struct rpc_task *task, void *calldata)
 		.rpc_resp	= &map->r_port,
 	};
 
-	rpc_call_setup(task, &msg, 0);
+	rpc_call_setup(task, &msg, 0, current->cred);
 }
 
 static void rpcb_map_release(void *data)


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

* [PATCH 19/52] CRED: Add a credentials pointer to struct rpc_task
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (17 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 18/52] CRED: Make rpcauth_bindcred() " David Howells
@ 2007-10-12 16:06 ` David Howells
  2007-10-12 16:07 ` [PATCH 20/52] CRED: Pass credentials into rpc_init_task() David Howells
                   ` (34 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:06 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Add a credentials pointer to struct rpc_task and make use of it in the
rpc_call_prepare() operation.

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

 fs/nfs/nfs4proc.c            |   12 ++++++------
 fs/nfs/unlink.c              |    2 +-
 include/linux/sunrpc/sched.h |    1 +
 net/sunrpc/rpcb_clnt.c       |    2 +-
 net/sunrpc/sched.c           |    4 ++++
 5 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 24c5021..943095d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -729,7 +729,7 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
 		.rpc_cred = data->owner->so_cred,
 	};
 	data->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0, current->cred);
+	rpc_call_setup(task, &msg, 0, task->tk_acred);
 }
 
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
@@ -838,7 +838,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
 		nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
 	}
 	data->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0, current->cred);
+	rpc_call_setup(task, &msg, 0, task->tk_acred);
 	return;
 out_no_action:
 	task->tk_action = NULL;
@@ -1316,7 +1316,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
 		calldata->arg.open_flags = FMODE_WRITE;
 	}
 	calldata->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0, current->cred);
+	rpc_call_setup(task, &msg, 0, task->tk_acred);
 }
 
 static const struct rpc_call_ops nfs4_close_ops = {
@@ -3007,7 +3007,7 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata)
 		.rpc_cred = data->cred,
 	};
 	nfs_fattr_init(data->res.fattr);
-	rpc_call_setup(task, &msg, 0, current->cred);
+	rpc_call_setup(task, &msg, 0, task->tk_acred);
 }
 
 static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
@@ -3255,7 +3255,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 		return;
 	}
 	calldata->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0, current->cred);
+	rpc_call_setup(task, &msg, 0, task->tk_acred);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -3384,7 +3384,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
 		data->arg.new_lock_owner = 1;
 	}
 	data->timestamp = jiffies;
-	rpc_call_setup(task, &msg, 0, current->cred);
+	rpc_call_setup(task, &msg, 0, task->tk_acred);
 out:
 	dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status);
 }
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index b5e2575..d4e7d09 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -68,7 +68,7 @@ static void nfs_async_unlink_init(struct rpc_task *task, void *calldata)
 
 	nfs_begin_data_update(dir);
 	NFS_PROTO(dir)->unlink_setup(&msg, dir);
-	rpc_call_setup(task, &msg, 0, current->cred);
+	rpc_call_setup(task, &msg, 0, task->tk_acred);
 }
 
 /**
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 8ea077d..fed97e0 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -69,6 +69,7 @@ struct rpc_task {
 	void			(*tk_action)(struct rpc_task *);
 	const struct rpc_call_ops *tk_ops;
 	void *			tk_calldata;
+	struct cred *		tk_acred;
 
 	/*
 	 * tk_timer is used for async processing by the RPC scheduling
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 6d167f0..82a863c 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -152,7 +152,7 @@ static void rpcb_getport_prepare(struct rpc_task *task, void *calldata)
 		.rpc_resp	= &map->r_port,
 	};
 
-	rpc_call_setup(task, &msg, 0, current->cred);
+	rpc_call_setup(task, &msg, 0, task->tk_acred);
 }
 
 static void rpcb_map_release(void *data)
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 954d7ec..d9d4219 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -808,6 +808,8 @@ void rpc_free(void *buffer)
  */
 void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
 {
+	struct cred *acred = current->cred;
+
 	memset(task, 0, sizeof(*task));
 	init_timer(&task->tk_timer);
 	task->tk_timer.data     = (unsigned long) task;
@@ -819,6 +821,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
 	if (tk_ops->rpc_call_prepare != NULL)
 		task->tk_action = rpc_prepare_task;
 	task->tk_calldata = calldata;
+	task->tk_acred = get_cred(acred);
 	INIT_LIST_HEAD(&task->tk_task);
 
 	/* Initialize retry counters */
@@ -897,6 +900,7 @@ void rpc_put_task(struct rpc_task *task)
 		rpc_release_client(task->tk_client);
 		task->tk_client = NULL;
 	}
+	put_cred(task->tk_acred);
 	if (task->tk_flags & RPC_TASK_DYNAMIC)
 		call_rcu_bh(&task->u.tk_rcu, rpc_free_task);
 	rpc_release_calldata(tk_ops, calldata);


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

* [PATCH 20/52] CRED: Pass credentials into rpc_init_task()
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (18 preceding siblings ...)
  2007-10-12 16:06 ` [PATCH 19/52] CRED: Add a credentials pointer to struct rpc_task David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 21/52] CRED: Pass credentials through the truncate() inode operation David Howells
                   ` (33 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials into rpc_init_task().

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

 fs/lockd/clntlock.c            |    2 
 fs/lockd/clntproc.c            |   34 ++-
 fs/lockd/host.c                |    6 
 fs/lockd/mon.c                 |   21 +-
 fs/lockd/svc.c                 |    2 
 fs/lockd/svc4proc.c            |    6 
 fs/lockd/svclock.c             |   13 +
 fs/lockd/svcproc.c             |    7 -
 fs/nfs/callback.c              |    2 
 fs/nfs/callback.h              |    2 
 fs/nfs/client.c                |  103 +++++---
 fs/nfs/delegation.c            |   24 +-
 fs/nfs/delegation.h            |   10 +
 fs/nfs/dir.c                   |  111 ++++++---
 fs/nfs/direct.c                |   29 +-
 fs/nfs/file.c                  |   14 +
 fs/nfs/getroot.c               |   22 +-
 fs/nfs/inode.c                 |   45 +++-
 fs/nfs/internal.h              |   24 +-
 fs/nfs/mount_clnt.c            |    7 -
 fs/nfs/namespace.c             |    5 
 fs/nfs/nfs3acl.c               |   43 ++-
 fs/nfs/nfs3proc.c              |  130 ++++++----
 fs/nfs/nfs4_fs.h               |   30 ++
 fs/nfs/nfs4namespace.c         |    7 -
 fs/nfs/nfs4proc.c              |  496 ++++++++++++++++++++++++----------------
 fs/nfs/nfs4renewd.c            |    2 
 fs/nfs/nfs4state.c             |   16 +
 fs/nfs/proc.c                  |   99 ++++----
 fs/nfs/read.c                  |    7 -
 fs/nfs/super.c                 |   41 ++-
 fs/nfs/symlink.c               |   24 ++
 fs/nfs/unlink.c                |   18 +
 fs/nfs/write.c                 |   17 +
 include/linux/lockd/bind.h     |    5 
 include/linux/lockd/lockd.h    |    5 
 include/linux/lockd/sm_inter.h |    4 
 include/linux/nfs_fs.h         |   38 ++-
 include/linux/nfs_xdr.h        |   54 +++-
 include/linux/sunrpc/clnt.h    |   10 -
 include/linux/sunrpc/sched.h   |   13 +
 net/sunrpc/auth_gss/auth_gss.c |    2 
 net/sunrpc/clnt.c              |   50 +++-
 net/sunrpc/rpcb_clnt.c         |   14 +
 net/sunrpc/sched.c             |   22 +-
 net/sunrpc/svc.c               |    5 
 46 files changed, 980 insertions(+), 661 deletions(-)

diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index d070b18..653a83e 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -174,7 +174,7 @@ reclaimer(void *ptr)
 	/* This one ensures that our parent doesn't terminate while the
 	 * reclaim is in progress */
 	lock_kernel();
-	lockd_up(0); /* note: this cannot fail as lockd is already running */
+	lockd_up(0, &init_cred); /* note: this cannot fail as lockd is already running */
 
 	dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
 
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index a10343b..fde8f25 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -28,7 +28,8 @@ static int	nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
 static int	nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
 static int	nlm_stat_to_errno(__be32 stat);
 static void	nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
-static int	nlmclnt_cancel(struct nlm_host *, int , struct file_lock *);
+static int	nlmclnt_cancel(struct nlm_host *, int , struct file_lock *,
+			       struct cred *);
 
 static const struct rpc_call_ops nlmclnt_unlock_ops;
 static const struct rpc_call_ops nlmclnt_cancel_ops;
@@ -149,7 +150,8 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
  * This is the main entry point for the NLM client.
  */
 int
-nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
+nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl,
+	     struct cred *acred)
 {
 	struct rpc_clnt		*client = NFS_CLIENT(inode);
 	struct sockaddr_in	addr;
@@ -173,7 +175,7 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
 	if (host == NULL)
 		return -ENOLCK;
 
-	call = nlm_alloc_call(host);
+	call = nlm_alloc_call(host, acred);
 	if (call == NULL)
 		return -ENOMEM;
 
@@ -227,7 +229,7 @@ EXPORT_SYMBOL(nlmclnt_proc);
  * Note: the caller must hold a reference to host. In case of failure,
  * this reference will be released.
  */
-struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
+struct nlm_rqst *nlm_alloc_call(struct nlm_host *host, struct cred *acred)
 {
 	struct nlm_rqst	*call;
 
@@ -237,6 +239,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
 			locks_init_lock(&call->a_args.lock.fl);
 			locks_init_lock(&call->a_res.lock.fl);
 			call->a_host = host;
+			call->a_acred = get_cred(acred);
 			return call;
 		}
 		if (signalled())
@@ -252,10 +255,11 @@ void nlm_release_call(struct nlm_rqst *call)
 {
 	nlm_release_host(call->a_host);
 	nlmclnt_release_lockargs(call);
+	put_cred(call->a_acred);
 	kfree(call);
 }
 
-static void nlmclnt_rpc_release(void *data)
+static void nlmclnt_rpc_release(struct cred *acred, void *data)
 {
 	return nlm_release_call(data);
 }
@@ -300,12 +304,12 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
 			goto in_grace_period;
 
 		/* If we have no RPC client yet, create one. */
-		if ((clnt = nlm_bind_host(host)) == NULL)
+		if ((clnt = nlm_bind_host(host, req->a_acred)) == NULL)
 			return -ENOLCK;
 		msg.rpc_proc = &clnt->cl_procinfo[proc];
 
 		/* Perform the RPC call. If an error occurs, try again */
-		if ((status = rpc_call_sync(clnt, &msg, 0)) < 0) {
+		if ((status = rpc_call_sync(clnt, &msg, 0, req->a_acred)) < 0) {
 			dprintk("lockd: rpc_call returned error %d\n", -status);
 			switch (status) {
 			case -EPROTONOSUPPORT:
@@ -365,15 +369,16 @@ static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *
 			(int)proc, host->h_name);
 
 	/* If we have no RPC client yet, create one. */
-	clnt = nlm_bind_host(host);
+	clnt = nlm_bind_host(host, req->a_acred);
 	if (clnt == NULL)
 		goto out_err;
 	msg->rpc_proc = &clnt->cl_procinfo[proc];
 
         /* bootstrap and kick off the async RPC call */
-        return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req);
+        return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req,
+			      req->a_acred);
 out_err:
-	tk_ops->rpc_release(req);
+	tk_ops->rpc_release(req->a_acred, req);
 	return -ENOLCK;
 }
 
@@ -499,7 +504,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
 	unsigned char fl_flags = fl->fl_flags;
 	int status = -ENOLCK;
 
-	if (nsm_monitor(host) < 0) {
+	if (nsm_monitor(host, req->a_acred) < 0) {
 		printk(KERN_NOTICE "lockd: failed to monitor %s\n",
 					host->h_name);
 		goto out;
@@ -553,7 +558,7 @@ out_unblock:
 	nlmclnt_finish_block(block);
 	/* Cancel the blocked request if it is still pending */
 	if (resp->status == nlm_lck_blocked)
-		nlmclnt_cancel(host, req->a_args.block, fl);
+		nlmclnt_cancel(host, req->a_args.block, fl, req->a_acred);
 out:
 	nlm_release_call(req);
 	fl->fl_flags = fl_flags;
@@ -681,7 +686,8 @@ static const struct rpc_call_ops nlmclnt_unlock_ops = {
  * We always use an async RPC call for this in order not to hang a
  * process that has been Ctrl-C'ed.
  */
-static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl)
+static int nlmclnt_cancel(struct nlm_host *host, int block,
+			  struct file_lock *fl, struct cred *acred)
 {
 	struct nlm_rqst	*req;
 	unsigned long	flags;
@@ -695,7 +701,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
 	recalc_sigpending();
 	spin_unlock_irqrestore(&current->sighand->siglock, flags);
 
-	req = nlm_alloc_call(nlm_get_host(host));
+	req = nlm_alloc_call(nlm_get_host(host), acred);
 	if (!req)
 		return -ENOMEM;
 	req->a_flags = RPC_TASK_ASYNC;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 572601e..15071a2 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -163,7 +163,7 @@ nlm_destroy_host(struct nlm_host *host)
 	/*
 	 * Release NSM handle and unmonitor host.
 	 */
-	nsm_unmonitor(host);
+	nsm_unmonitor(host, current->cred);
 
 	clnt = host->h_rpcclnt;
 	if (clnt != NULL)
@@ -203,7 +203,7 @@ nlmsvc_lookup_host(struct svc_rqst *rqstp,
  * Create the NLM RPC client for an NLM peer
  */
 struct rpc_clnt *
-nlm_bind_host(struct nlm_host *host)
+nlm_bind_host(struct nlm_host *host, struct cred *acred)
 {
 	struct rpc_clnt	*clnt;
 
@@ -246,7 +246,7 @@ nlm_bind_host(struct nlm_host *host)
 					   RPC_CLNT_CREATE_AUTOBIND),
 		};
 
-		clnt = rpc_create(&args);
+		clnt = rpc_create(&args, acred);
 		if (!IS_ERR(clnt))
 			host->h_rpcclnt = clnt;
 		else {
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 3353ed8..f2ca99f 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -17,7 +17,7 @@
 
 #define NLMDBG_FACILITY		NLMDBG_MONITOR
 
-static struct rpc_clnt *	nsm_create(void);
+static struct rpc_clnt *	nsm_create(struct cred *);
 
 static struct rpc_program	nsm_program;
 
@@ -30,7 +30,8 @@ int				nsm_local_state;
  * Common procedure for SM_MON/SM_UNMON calls
  */
 static int
-nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
+nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
+	      struct cred *acred)
 {
 	struct rpc_clnt	*clnt;
 	int		status;
@@ -40,7 +41,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
 		.rpc_resp	= res,
 	};
 
-	clnt = nsm_create();
+	clnt = nsm_create(acred);
 	if (IS_ERR(clnt)) {
 		status = PTR_ERR(clnt);
 		goto out;
@@ -55,7 +56,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
 	memset(res, 0, sizeof(*res));
 
 	msg.rpc_proc = &clnt->cl_procinfo[proc];
-	status = rpc_call_sync(clnt, &msg, 0);
+	status = rpc_call_sync(clnt, &msg, 0, acred);
 	if (status < 0)
 		printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n",
 			status);
@@ -70,7 +71,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
  * Set up monitoring of a remote host
  */
 int
-nsm_monitor(struct nlm_host *host)
+nsm_monitor(struct nlm_host *host, struct cred *acred)
 {
 	struct nsm_handle *nsm = host->h_nsmhandle;
 	struct nsm_res	res;
@@ -82,7 +83,7 @@ nsm_monitor(struct nlm_host *host)
 	if (nsm->sm_monitored)
 		return 0;
 
-	status = nsm_mon_unmon(nsm, SM_MON, &res);
+	status = nsm_mon_unmon(nsm, SM_MON, &res, acred);
 
 	if (status < 0 || res.status != 0)
 		printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name);
@@ -95,7 +96,7 @@ nsm_monitor(struct nlm_host *host)
  * Cease to monitor remote host
  */
 int
-nsm_unmonitor(struct nlm_host *host)
+nsm_unmonitor(struct nlm_host *host, struct cred *acred)
 {
 	struct nsm_handle *nsm = host->h_nsmhandle;
 	struct nsm_res	res;
@@ -109,7 +110,7 @@ nsm_unmonitor(struct nlm_host *host)
 	 && nsm->sm_monitored && !nsm->sm_sticky) {
 		dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name);
 
-		status = nsm_mon_unmon(nsm, SM_UNMON, &res);
+		status = nsm_mon_unmon(nsm, SM_UNMON, &res, acred);
 		if (status < 0)
 			printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
 					host->h_name);
@@ -124,7 +125,7 @@ nsm_unmonitor(struct nlm_host *host)
  * Create NSM client for the local host
  */
 static struct rpc_clnt *
-nsm_create(void)
+nsm_create(struct cred *acred)
 {
 	struct sockaddr_in	sin = {
 		.sin_family	= AF_INET,
@@ -141,7 +142,7 @@ nsm_create(void)
 		.authflavor	= RPC_AUTH_NULL,
 	};
 
-	return rpc_create(&args);
+	return rpc_create(&args, acred);
 }
 
 /*
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 82e2192..d4fd193 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -264,7 +264,7 @@ static int make_socks(struct svc_serv *serv, int proto)
  * Bring up the lockd process if it's not already up.
  */
 int
-lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
+lockd_up(int proto, struct cred *acred) /* Maybe add a 'family' option when IPv6 is supported ?? */
 {
 	struct svc_serv *	serv;
 	int			error = 0;
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index bf27b6c..16efd5a 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -39,7 +39,7 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 
 	/* Obtain host handle */
 	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
-	 || (argp->monitor && nsm_monitor(host) < 0))
+	 || (argp->monitor && nsm_monitor(host, current->cred) < 0))
 		goto no_locks;
 	*hostp = host;
 
@@ -242,7 +242,7 @@ static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
 			-task->tk_status);
 }
 
-static void nlm4svc_callback_release(void *data)
+static void nlm4svc_callback_release(struct cred *acred, void *data)
 {
 	nlm_release_call(data);
 }
@@ -270,7 +270,7 @@ static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args
 	if (host == NULL)
 		return rpc_system_err;
 
-	call = nlm_alloc_call(host);
+	call = nlm_alloc_call(host, current->cred);
 	if (call == NULL)
 		return rpc_system_err;
 
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index d120ec3..50d89ea 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -174,12 +174,12 @@ found:
 static struct nlm_block *
 nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
 		    struct nlm_file *file, struct nlm_lock *lock,
-		    struct nlm_cookie *cookie)
+		    struct nlm_cookie *cookie, struct cred *acred)
 {
 	struct nlm_block	*block;
 	struct nlm_rqst		*call = NULL;
 
-	call = nlm_alloc_call(host);
+	call = nlm_alloc_call(host, acred);
 	if (call == NULL)
 		return NULL;
 
@@ -360,6 +360,7 @@ __be32
 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
 			struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
 {
+	struct cred		*acred = current->cred;
 	struct nlm_block	*block = NULL;
 	struct nlm_host		*host;
 	int			error;
@@ -386,7 +387,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
 	block = nlmsvc_lookup_block(file, lock);
 	if (block == NULL) {
 		block = nlmsvc_create_block(rqstp, nlm_get_host(host), file,
-				lock, cookie);
+				lock, cookie, acred);
 		ret = nlm_lck_denied_nolocks;
 		if (block == NULL)
 			goto out;
@@ -463,6 +464,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
 		struct nlm_lock *lock, struct nlm_lock *conflock,
 		struct nlm_cookie *cookie)
 {
+	struct cred		*acred = current->cred;
 	struct nlm_block 	*block = NULL;
 	int			error;
 	__be32			ret;
@@ -489,7 +491,8 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
 			kfree(conf);
 			return nlm_lck_denied_nolocks;
 		}
-		block = nlmsvc_create_block(rqstp, host, file, lock, cookie);
+		block = nlmsvc_create_block(rqstp, host, file, lock, cookie,
+					    acred);
 		if (block == NULL) {
 			kfree(conf);
 			return nlm_granted;
@@ -796,7 +799,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
 	svc_wake_up(block->b_daemon);
 }
 
-static void nlmsvc_grant_release(void *data)
+static void nlmsvc_grant_release(struct cred *acred, void *data)
 {
 	struct nlm_rqst		*call = data;
 
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 9cd5c8b..f3265ed 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -68,7 +68,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 
 	/* Obtain host handle */
 	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
-	 || (argp->monitor && nsm_monitor(host) < 0))
+	 || (argp->monitor && nsm_monitor(host, current->cred) < 0))
 		goto no_locks;
 	*hostp = host;
 
@@ -272,7 +272,7 @@ static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
 			-task->tk_status);
 }
 
-static void nlmsvc_callback_release(void *data)
+static void nlmsvc_callback_release(struct cred *acred, void *data)
 {
 	nlm_release_call(data);
 }
@@ -290,6 +290,7 @@ static const struct rpc_call_ops nlmsvc_callback_ops = {
 static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
 		__be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
 {
+	struct cred *acred = current->cred;
 	struct nlm_host	*host;
 	struct nlm_rqst	*call;
 	__be32 stat;
@@ -300,7 +301,7 @@ static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args
 	if (host == NULL)
 		return rpc_system_err;
 
-	call = nlm_alloc_call(host);
+	call = nlm_alloc_call(host, acred);
 	if (call == NULL)
 		return rpc_system_err;
 
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index a796be5..bca7d28 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -107,7 +107,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
 /*
  * Bring up the server process if it is not already up.
  */
-int nfs_callback_up(void)
+int nfs_callback_up(struct cred *acred)
 {
 	struct svc_serv *serv;
 	int ret = 0;
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index c2bb14e..8425611 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -63,7 +63,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getat
 extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
 
 #ifdef CONFIG_NFS_V4
-extern int nfs_callback_up(void);
+extern int nfs_callback_up(struct cred *acred);
 extern void nfs_callback_down(void);
 #else
 #define nfs_callback_up()	(0)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index a204484..61a1b20 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -99,7 +99,8 @@ struct rpc_program		nfsacl_program = {
  */
 static struct nfs_client *nfs_alloc_client(const char *hostname,
 					   const struct sockaddr_in *addr,
-					   int nfsversion)
+					   int nfsversion,
+					   struct cred *acred)
 {
 	struct nfs_client *clp;
 
@@ -107,7 +108,7 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
 		goto error_0;
 
 	if (nfsversion == 4) {
-		if (nfs_callback_up() < 0)
+		if (nfs_callback_up(acred) < 0)
 			goto error_2;
 		__set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
 	}
@@ -257,7 +258,8 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversio
  */
 static struct nfs_client *nfs_get_client(const char *hostname,
 					 const struct sockaddr_in *addr,
-					 int nfsversion)
+					 int nfsversion,
+					 struct cred *acred)
 {
 	struct nfs_client *clp, *new = NULL;
 	int error;
@@ -278,7 +280,7 @@ static struct nfs_client *nfs_get_client(const char *hostname,
 
 		spin_unlock(&nfs_client_lock);
 
-		new = nfs_alloc_client(hostname, addr, nfsversion);
+		new = nfs_alloc_client(hostname, addr, nfsversion, acred);
 	} while (new);
 
 	return ERR_PTR(-ENOMEM);
@@ -368,7 +370,8 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
 						unsigned int timeo,
 						unsigned int retrans,
 						rpc_authflavor_t flavor,
-						int flags)
+						int flags,
+						struct cred *acred)
 {
 	struct rpc_timeout	timeparms;
 	struct rpc_clnt		*clnt = NULL;
@@ -391,7 +394,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
 	clp->retrans_timeo = timeparms.to_initval;
 	clp->retrans_count = timeparms.to_retries;
 
-	clnt = rpc_create(&args);
+	clnt = rpc_create(&args, acred);
 	if (IS_ERR(clnt)) {
 		dprintk("%s: cannot create RPC client. Error = %ld\n",
 				__FUNCTION__, PTR_ERR(clnt));
@@ -417,7 +420,7 @@ static void nfs_destroy_server(struct nfs_server *server)
 /*
  * Version 2 or 3 lockd setup
  */
-static int nfs_start_lockd(struct nfs_server *server)
+static int nfs_start_lockd(struct nfs_server *server, struct cred *acred)
 {
 	int error = 0;
 
@@ -426,7 +429,7 @@ static int nfs_start_lockd(struct nfs_server *server)
 	if (server->flags & NFS_MOUNT_NONLM)
 		goto out;
 	error = lockd_up((server->flags & NFS_MOUNT_TCP) ?
-			IPPROTO_TCP : IPPROTO_UDP);
+			IPPROTO_TCP : IPPROTO_UDP, acred);
 	if (error < 0)
 		server->flags |= NFS_MOUNT_NONLM;
 	else
@@ -439,14 +442,16 @@ out:
  * Initialise an NFSv3 ACL client connection
  */
 #ifdef CONFIG_NFS_V3_ACL
-static void nfs_init_server_aclclient(struct nfs_server *server)
+static void nfs_init_server_aclclient(struct nfs_server *server,
+				      struct cred *acred)
 {
 	if (server->nfs_client->cl_nfsversion != 3)
 		goto out_noacl;
 	if (server->flags & NFS_MOUNT_NOACL)
 		goto out_noacl;
 
-	server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
+	server->client_acl = rpc_bind_new_program(server->client,
+						  &nfsacl_program, 3, acred);
 	if (IS_ERR(server->client_acl))
 		goto out_noacl;
 
@@ -501,7 +506,9 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t
 /*
  * Initialise an NFS2 or NFS3 client
  */
-static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data)
+static int nfs_init_client(struct nfs_client *clp,
+			   const struct nfs_mount_data *data,
+			   struct cred *acred)
 {
 	int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
 	int error;
@@ -523,7 +530,7 @@ static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *
 	 * - RFC 2623, sec 2.3.2
 	 */
 	error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans,
-					RPC_AUTH_UNIX, 0);
+					RPC_AUTH_UNIX, 0, acred);
 	if (error < 0)
 		goto error;
 	nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -538,7 +545,9 @@ error:
 /*
  * Create a version 2 or 3 client
  */
-static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data)
+static int nfs_init_server(struct nfs_server *server,
+			   const struct nfs_mount_data *data,
+			   struct cred *acred)
 {
 	struct nfs_client *clp;
 	int error, nfsvers = 2;
@@ -551,13 +560,13 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
 #endif
 
 	/* Allocate or find a client reference we can use */
-	clp = nfs_get_client(data->hostname, &data->addr, nfsvers);
+	clp = nfs_get_client(data->hostname, &data->addr, nfsvers, acred);
 	if (IS_ERR(clp)) {
 		dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
 		return PTR_ERR(clp);
 	}
 
-	error = nfs_init_client(clp, data);
+	error = nfs_init_client(clp, data, acred);
 	if (error < 0)
 		goto error;
 
@@ -577,7 +586,7 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
 	server->acdirmax = data->acdirmax * HZ;
 
 	/* Start lockd here, before we might error out */
-	error = nfs_start_lockd(server);
+	error = nfs_start_lockd(server, acred);
 	if (error < 0)
 		goto error;
 
@@ -587,7 +596,7 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
 
 	server->namelen  = data->namlen;
 	/* Create a client RPC handle for the NFSv3 ACL management interface */
-	nfs_init_server_aclclient(server);
+	nfs_init_server_aclclient(server, acred);
 	dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
 	return 0;
 
@@ -651,7 +660,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
 /*
  * Probe filesystem information, including the FSID on v2/v3
  */
-static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
+static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh,
+			    struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct nfs_fsinfo fsinfo;
 	struct nfs_client *clp = server->nfs_client;
@@ -660,14 +670,14 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
 	dprintk("--> nfs_probe_fsinfo()\n");
 
 	if (clp->rpc_ops->set_capabilities != NULL) {
-		error = clp->rpc_ops->set_capabilities(server, mntfh);
+		error = clp->rpc_ops->set_capabilities(server, mntfh, acred);
 		if (error < 0)
 			goto out_error;
 	}
 
 	fsinfo.fattr = fattr;
 	nfs_fattr_init(fattr);
-	error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
+	error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo, acred);
 	if (error < 0)
 		goto out_error;
 
@@ -680,7 +690,8 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
 		pathinfo.fattr = fattr;
 		nfs_fattr_init(fattr);
 
-		if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
+		if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo,
+					   acred) >= 0)
 			server->namelen = pathinfo.max_namelen;
 	}
 
@@ -761,7 +772,7 @@ void nfs_free_server(struct nfs_server *server)
  * - keyed on server and FSID
  */
 struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
-				     struct nfs_fh *mntfh)
+				     struct nfs_fh *mntfh, struct cred *acred)
 {
 	struct nfs_server *server;
 	struct nfs_fattr fattr;
@@ -772,7 +783,7 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
 		return ERR_PTR(-ENOMEM);
 
 	/* Get a client representation */
-	error = nfs_init_server(server, data);
+	error = nfs_init_server(server, data, acred);
 	if (error < 0)
 		goto error;
 
@@ -781,7 +792,7 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
 	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
 	/* Probe the root fh to retrieve its FSID */
-	error = nfs_probe_fsinfo(server, mntfh, &fattr);
+	error = nfs_probe_fsinfo(server, mntfh, &fattr, acred);
 	if (error < 0)
 		goto error;
 	if (server->nfs_client->rpc_ops->version == 3) {
@@ -795,7 +806,8 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
 	}
 
 	if (!(fattr.valid & NFS_ATTR_FATTR)) {
-		error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+		error = server->nfs_client->rpc_ops->getattr(server, mntfh,
+							     &fattr, acred);
 		if (error < 0) {
 			dprintk("nfs_create_server: getattr error = %d\n", -error);
 			goto error;
@@ -831,7 +843,8 @@ error:
 static int nfs4_init_client(struct nfs_client *clp,
 		int proto, int timeo, int retrans,
 		const char *ip_addr,
-		rpc_authflavor_t authflavour)
+		rpc_authflavor_t authflavour,
+		struct cred *acred)
 {
 	int error;
 
@@ -845,7 +858,7 @@ static int nfs4_init_client(struct nfs_client *clp,
 	clp->rpc_ops = &nfs_v4_clientops;
 
 	error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour,
-					RPC_CLNT_CREATE_DISCRTRY);
+					RPC_CLNT_CREATE_DISCRTRY, acred);
 	if (error < 0)
 		goto error;
 	memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
@@ -874,7 +887,8 @@ static int nfs4_set_client(struct nfs_server *server,
 		const char *hostname, const struct sockaddr_in *addr,
 		const char *ip_addr,
 		rpc_authflavor_t authflavour,
-		int proto, int timeo, int retrans)
+		int proto, int timeo, int retrans,
+		struct cred *acred)
 {
 	struct nfs_client *clp;
 	int error;
@@ -882,12 +896,13 @@ static int nfs4_set_client(struct nfs_server *server,
 	dprintk("--> nfs4_set_client()\n");
 
 	/* Allocate or find a client reference we can use */
-	clp = nfs_get_client(hostname, addr, 4);
+	clp = nfs_get_client(hostname, addr, 4, acred);
 	if (IS_ERR(clp)) {
 		error = PTR_ERR(clp);
 		goto error;
 	}
-	error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour);
+	error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr,
+				 authflavour, acred);
 	if (error < 0)
 		goto error_put;
 
@@ -943,7 +958,8 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
 				      const char *mntpath,
 				      const char *ip_addr,
 				      rpc_authflavor_t authflavour,
-				      struct nfs_fh *mntfh)
+				      struct nfs_fh *mntfh,
+				      struct cred *acred)
 {
 	struct nfs_fattr fattr;
 	struct nfs_server *server;
@@ -957,7 +973,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
 
 	/* Get a client record */
 	error = nfs4_set_client(server, hostname, addr, ip_addr, authflavour,
-			data->proto, data->timeo, data->retrans);
+			data->proto, data->timeo, data->retrans, acred);
 	if (error < 0)
 		goto error;
 
@@ -971,7 +987,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
 	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
 	/* Probe the root fh to retrieve its FSID */
-	error = nfs4_path_walk(server, mntfh, mntpath);
+	error = nfs4_path_walk(server, mntfh, mntpath, acred);
 	if (error < 0)
 		goto error;
 
@@ -980,7 +996,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
 		(unsigned long long) server->fsid.minor);
 	dprintk("Mount FH: %d\n", mntfh->size);
 
-	error = nfs_probe_fsinfo(server, mntfh, &fattr);
+	error = nfs_probe_fsinfo(server, mntfh, &fattr, acred);
 	if (error < 0)
 		goto error;
 
@@ -1010,7 +1026,8 @@ error:
  * Create an NFS4 referral server record
  */
 struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
-					       struct nfs_fh *mntfh)
+					       struct nfs_fh *mntfh,
+					       struct cred *acred)
 {
 	struct nfs_client *parent_client;
 	struct nfs_server *server, *parent_server;
@@ -1033,7 +1050,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
 			data->authflavor,
 			parent_server->client->cl_xprt->prot,
 			parent_client->retrans_timeo,
-			parent_client->retrans_count);
+			parent_client->retrans_count,
+			acred);
 	if (error < 0)
 		goto error;
 
@@ -1050,12 +1068,12 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
 	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
 	/* Probe the root fh to retrieve its FSID and filehandle */
-	error = nfs4_path_walk(server, mntfh, data->mnt_path);
+	error = nfs4_path_walk(server, mntfh, data->mnt_path, acred);
 	if (error < 0)
 		goto error;
 
 	/* probe the filesystem info for this server filesystem */
-	error = nfs_probe_fsinfo(server, mntfh, &fattr);
+	error = nfs_probe_fsinfo(server, mntfh, &fattr, acred);
 	if (error < 0)
 		goto error;
 
@@ -1089,7 +1107,8 @@ error:
  */
 struct nfs_server *nfs_clone_server(struct nfs_server *source,
 				    struct nfs_fh *fh,
-				    struct nfs_fattr *fattr)
+				    struct nfs_fattr *fattr,
+				    struct cred *acred)
 {
 	struct nfs_server *server;
 	struct nfs_fattr fattr_fsinfo;
@@ -1114,10 +1133,10 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
 	if (error < 0)
 		goto out_free_server;
 	if (!IS_ERR(source->client_acl))
-		nfs_init_server_aclclient(server);
+		nfs_init_server_aclclient(server, acred);
 
 	/* probe the filesystem info for this server filesystem */
-	error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo);
+	error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo, acred);
 	if (error < 0)
 		goto out_free_server;
 
@@ -1128,7 +1147,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
 		(unsigned long long) server->fsid.major,
 		(unsigned long long) server->fsid.minor);
 
-	error = nfs_start_lockd(server);
+	error = nfs_start_lockd(server, acred);
 	if (error < 0)
 		goto out_free_server;
 
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index c55a761..3686cc0 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -29,6 +29,7 @@ static void nfs_free_delegation_callback(struct rcu_head *head)
 {
 	struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
 
+	put_cred(delegation->acred);
 	nfs_do_free_delegation(delegation);
 }
 
@@ -106,7 +107,8 @@ again:
 /*
  * Set up a delegation on an inode
  */
-void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
+void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
+				  struct nfs_openres *res, struct cred *acred)
 {
 	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
 
@@ -118,6 +120,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
 	delegation->maxsize = res->maxsize;
 	put_rpccred(cred);
 	delegation->cred = get_rpccred(cred);
+	put_cred(delegation->acred);
+	delegation->acred = get_cred(acred);
 	delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
 	NFS_I(inode)->delegation_state = delegation->type;
 	smp_wmb();
@@ -126,7 +130,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
 /*
  * Set up a delegation on an inode
  */
-int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
+int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred,
+			     struct nfs_openres *res, struct cred *acred)
 {
 	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
 	struct nfs_inode *nfsi = NFS_I(inode);
@@ -142,6 +147,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
 	delegation->maxsize = res->maxsize;
 	delegation->change_attr = nfsi->change_attr;
 	delegation->cred = get_rpccred(cred);
+	delegation->acred = get_cred(acred);
 	delegation->inode = inode;
 
 	spin_lock(&clp->cl_lock);
@@ -170,11 +176,14 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
 	return status;
 }
 
-static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
+static int nfs_do_return_delegation(struct inode *inode,
+				    struct nfs_delegation *delegation,
+				    struct cred *acred)
 {
 	int res = 0;
 
-	res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
+	res = nfs4_proc_delegreturn(inode, delegation->cred,
+				    &delegation->stateid, acred);
 	nfs_free_delegation(delegation);
 	return res;
 }
@@ -190,7 +199,8 @@ static void nfs_msync_inode(struct inode *inode)
 /*
  * Basic procedure for returning a delegation to the server
  */
-static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
+static int __nfs_inode_return_delegation(struct inode *inode,
+					 struct nfs_delegation *delegation)
 {
 	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
 	struct nfs_inode *nfsi = NFS_I(inode);
@@ -204,7 +214,7 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat
 	up_read(&clp->cl_sem);
 	nfs_msync_inode(inode);
 
-	return nfs_do_return_delegation(inode, delegation);
+	return nfs_do_return_delegation(inode, delegation, delegation->acred);
 }
 
 static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
@@ -383,7 +393,7 @@ static int recall_thread(void *data)
 	nfs_msync_inode(inode);
 
 	if (delegation != NULL)
-		nfs_do_return_delegation(inode, delegation);
+		nfs_do_return_delegation(inode, delegation, &init_cred);
 	iput(inode);
 	module_put_and_exit(0);
 }
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 5874ce7..6319594 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -15,6 +15,7 @@
 struct nfs_delegation {
 	struct list_head super_list;
 	struct rpc_cred *cred;
+	struct cred *acred;
 	struct inode *inode;
 	nfs4_stateid stateid;
 	int type;
@@ -25,8 +26,10 @@ struct nfs_delegation {
 	struct rcu_head rcu;
 };
 
-int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
+int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred,
+			     struct nfs_openres *res, struct cred *acred);
+void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
+				  struct nfs_openres *res, struct cred *acred);
 int nfs_inode_return_delegation(struct inode *inode);
 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
 
@@ -39,7 +42,8 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp);
 void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
 
 /* NFSv4 delegation-related procedures */
-int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
+int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred,
+			  const nfs4_stateid *stateid, struct cred *acred);
 int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
 int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 53b9e24..35a63cf 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -175,6 +175,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
 {
 	struct file	*file = desc->file;
 	struct inode	*inode = file->f_path.dentry->d_inode;
+	struct cred	*acred = file->f_cred;
 	struct rpc_cred	*cred = nfs_file_cred(file);
 	unsigned long	timestamp;
 	int		error;
@@ -186,7 +187,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
  again:
 	timestamp = jiffies;
 	error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
-					  NFS_SERVER(inode)->dtsize, desc->plus);
+					  NFS_SERVER(inode)->dtsize, desc->plus,
+					  acred);
 	if (error < 0) {
 		/* We requested READDIRPLUS, but the server doesn't grok it */
 		if (error == -ENOTSUPP && desc->plus) {
@@ -472,6 +474,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
 {
 	struct file	*file = desc->file;
 	struct inode	*inode = file->f_path.dentry->d_inode;
+	struct cred	*acred = file->f_cred;
 	struct rpc_cred	*cred = nfs_file_cred(file);
 	struct page	*page = NULL;
 	int		status;
@@ -489,7 +492,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
 	desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie,
 						page,
 						NFS_SERVER(inode)->dtsize,
-						desc->plus);
+						desc->plus, acred);
 	spin_lock(&inode->i_lock);
 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
 	spin_unlock(&inode->i_lock);
@@ -527,6 +530,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
  */
 static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
+	struct cred	*acred = filp->f_cred;
 	struct dentry	*dentry = filp->f_path.dentry;
 	struct inode	*inode = dentry->d_inode;
 	nfs_readdir_descriptor_t my_desc,
@@ -543,7 +547,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
 	lock_kernel();
 
-	res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping);
+	res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping, acred);
 	if (res < 0) {
 		unlock_kernel();
 		return res;
@@ -703,7 +707,8 @@ static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigne
  *
  */
 static inline
-int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
+int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd,
+			    struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 
@@ -718,9 +723,9 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
 				 S_ISDIR(inode->i_mode)))
 			goto out_force;
 	}
-	return nfs_revalidate_inode(server, inode);
+	return nfs_revalidate_inode(server, inode, acred);
 out_force:
-	return __nfs_revalidate_inode(server, inode);
+	return __nfs_revalidate_inode(server, inode, acred);
 }
 
 /*
@@ -753,6 +758,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
  */
 static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct inode *dir;
 	struct inode *inode;
 	struct dentry *parent;
@@ -768,7 +774,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 	inode = dentry->d_inode;
 
 	/* Revalidate parent directory attribute cache */
-	if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
+	if (nfs_revalidate_inode(NFS_SERVER(dir), dir, acred) < 0)
 		goto out_zap_parent;
 
 	if (!inode) {
@@ -786,7 +792,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 
 	/* Force a full look up iff the parent directory has changed */
 	if (nfs_check_verifier(dir, dentry)) {
-		if (nfs_lookup_verify_inode(inode, nd))
+		if (nfs_lookup_verify_inode(inode, nd, acred))
 			goto out_zap_parent;
 		goto out_valid;
 	}
@@ -795,7 +801,8 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 		goto out_bad;
 
 	verifier = nfs_save_change_attribute(dir);
-	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr,
+				       acred);
 	if (error)
 		goto out_bad;
 	if (nfs_compare_fh(NFS_FH(inode), &fhandle))
@@ -869,7 +876,7 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
 		lock_kernel();
 		drop_nlink(inode);
-		nfs_complete_unlink(dentry, inode);
+		nfs_complete_unlink(dentry, inode, &init_cred);
 		unlock_kernel();
 	}
 	/* When creating a negative dentry, we want to renew d_time */
@@ -897,18 +904,20 @@ int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
 	return (nd->intent.open.flags & O_EXCL) != 0;
 }
 
-static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
+static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr,
+				 struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 
 	if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
 		/* Revalidate fsid using the parent directory */
-		return __nfs_revalidate_inode(server, dir);
+		return __nfs_revalidate_inode(server, dir, acred);
 	return 0;
 }
 
 static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct dentry *res;
 	struct inode *inode = NULL;
 	int error;
@@ -938,14 +947,15 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
 		goto out_unlock;
 	}
 
-	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr,
+				       acred);
 	if (error == -ENOENT)
 		goto no_entry;
 	if (error < 0) {
 		res = ERR_PTR(error);
 		goto out_unlock;
 	}
-	error = nfs_reval_fsid(dir, &fattr);
+	error = nfs_reval_fsid(dir, &fattr, acred);
 	if (error < 0) {
 		res = ERR_PTR(error);
 		goto out_unlock;
@@ -1004,6 +1014,7 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd)
 
 static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct dentry *res = NULL;
 	int error;
 
@@ -1029,7 +1040,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 	/* Open the file on the server */
 	lock_kernel();
 	/* Revalidate parent directory attribute cache */
-	error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
+	error = nfs_revalidate_inode(NFS_SERVER(dir), dir, acred);
 	if (error < 0) {
 		res = ERR_PTR(error);
 		unlock_kernel();
@@ -1038,10 +1049,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 
 	if (nd->intent.open.flags & O_CREAT) {
 		nfs_begin_data_update(dir);
-		res = nfs4_atomic_open(dir, dentry, nd);
+		res = nfs4_atomic_open(dir, dentry, nd, acred);
 		nfs_end_data_update(dir);
 	} else
-		res = nfs4_atomic_open(dir, dentry, nd);
+		res = nfs4_atomic_open(dir, dentry, nd, acred);
 	unlock_kernel();
 	if (IS_ERR(res)) {
 		error = PTR_ERR(res);
@@ -1073,6 +1084,7 @@ no_open:
 
 static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct dentry *parent = NULL;
 	struct inode *inode = dentry->d_inode;
 	struct inode *dir;
@@ -1105,7 +1117,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 	 */
 	lock_kernel();
 	verifier = nfs_save_change_attribute(dir);
-	ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
+	ret = nfs4_open_revalidate(dir, dentry, openflags, nd, acred);
 	if (!ret)
 		nfs_refresh_verifier(dentry, verifier);
 	unlock_kernel();
@@ -1196,7 +1208,7 @@ out_renew:
  * Code common to create, mkdir, and mknod.
  */
 int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
-				struct nfs_fattr *fattr)
+				struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct inode *inode;
 	int error = -EACCES;
@@ -1206,13 +1218,15 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 		return 0;
 	if (fhandle->size == 0) {
 		struct inode *dir = dentry->d_parent->d_inode;
-		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
+		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle,
+					       fattr, acred);
 		if (error)
 			return error;
 	}
 	if (!(fattr->valid & NFS_ATTR_FATTR)) {
 		struct nfs_server *server = NFS_SB(dentry->d_sb);
-		error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr);
+		error = server->nfs_client->rpc_ops->getattr(server, fhandle,
+							     fattr, acred);
 		if (error < 0)
 			return error;
 	}
@@ -1235,6 +1249,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 		struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct iattr attr;
 	int error;
 	int open_flags = 0;
@@ -1250,7 +1265,8 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
+	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd,
+				       acred);
 	nfs_end_data_update(dir);
 	if (error != 0)
 		goto out_err;
@@ -1270,6 +1286,7 @@ out_err:
 static int
 nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 {
+	struct cred *acred = current->cred;
 	struct iattr attr;
 	int status;
 
@@ -1284,7 +1301,7 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev);
+	status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev, acred);
 	nfs_end_data_update(dir);
 	if (status != 0)
 		goto out_err;
@@ -1303,6 +1320,7 @@ out_err:
  */
 static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
+	struct cred *acred = current->cred;
 	struct iattr attr;
 	int error;
 
@@ -1314,7 +1332,7 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr);
+	error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr, acred);
 	nfs_end_data_update(dir);
 	if (error != 0)
 		goto out_err;
@@ -1330,6 +1348,7 @@ out_err:
 
 static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *acred = current->cred;
 	int error;
 
 	dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
@@ -1337,7 +1356,7 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
+	error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name, acred);
 	/* Ensure the VFS deletes this inode */
 	if (error == 0 && dentry->d_inode != NULL)
 		clear_nlink(dentry->d_inode);
@@ -1347,7 +1366,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 	return error;
 }
 
-static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
+static int nfs_sillyrename(struct inode *dir, struct dentry *dentry,
+			   struct cred *acred)
 {
 	static unsigned int sillycounter;
 	const int      i_inosize  = sizeof(dir->i_ino)*2;
@@ -1402,18 +1422,18 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
 	if (dentry->d_inode) {
 		nfs_begin_data_update(dentry->d_inode);
 		error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-				dir, &qsilly);
+				dir, &qsilly, acred);
 		nfs_mark_for_revalidate(dentry->d_inode);
 		nfs_end_data_update(dentry->d_inode);
 	} else
 		error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-				dir, &qsilly);
+				dir, &qsilly, acred);
 	nfs_end_data_update(dir);
 	if (!error) {
 		nfs_renew_times(dentry);
 		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 		d_move(dentry, sdentry);
-		error = nfs_async_unlink(dir, dentry);
+		error = nfs_async_unlink(dir, dentry, acred);
  		/* If we return 0 we don't unlink */
 	}
 	dput(sdentry);
@@ -1428,7 +1448,7 @@ out:
  * We invalidate the attribute cache and free the inode prior to the operation
  * to avoid possible races if the server reuses the inode.
  */
-static int nfs_safe_remove(struct dentry *dentry)
+static int nfs_safe_remove(struct dentry *dentry, struct cred *acred)
 {
 	struct inode *dir = dentry->d_parent->d_inode;
 	struct inode *inode = dentry->d_inode;
@@ -1447,14 +1467,14 @@ static int nfs_safe_remove(struct dentry *dentry)
 	if (inode != NULL) {
 		nfs_inode_return_delegation(inode);
 		nfs_begin_data_update(inode);
-		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name, acred);
 		/* The VFS may want to delete this inode */
 		if (error == 0)
 			drop_nlink(inode);
 		nfs_mark_for_revalidate(inode);
 		nfs_end_data_update(inode);
 	} else
-		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name, acred);
 	nfs_end_data_update(dir);
 out:
 	return error;
@@ -1467,6 +1487,7 @@ out:
  */
 static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *acred = current->cred;
 	int error;
 	int need_rehash = 0;
 
@@ -1481,7 +1502,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 		spin_unlock(&dcache_lock);
 		/* Start asynchronous writeout of the inode */
 		write_inode_now(dentry->d_inode, 0);
-		error = nfs_sillyrename(dir, dentry);
+		error = nfs_sillyrename(dir, dentry, acred);
 		unlock_kernel();
 		return error;
 	}
@@ -1491,7 +1512,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 	}
 	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
-	error = nfs_safe_remove(dentry);
+	error = nfs_safe_remove(dentry, acred);
 	if (!error) {
 		nfs_renew_times(dentry);
 		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -1518,6 +1539,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
  */
 static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
+	struct cred *acred = current->cred;
 	struct pagevec lru_pvec;
 	struct page *page;
 	char *kaddr;
@@ -1549,7 +1571,8 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
 	kunmap_atomic(kaddr, KM_USER0);
 
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
+	error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr,
+					acred);
 	nfs_end_data_update(dir);
 	if (error != 0) {
 		dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n",
@@ -1582,6 +1605,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
 static int 
 nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = old_dentry->d_inode;
 	int error;
 
@@ -1592,7 +1616,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 	lock_kernel();
 	nfs_begin_data_update(dir);
 	nfs_begin_data_update(inode);
-	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
+	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name, acred);
 	if (error == 0) {
 		atomic_inc(&inode->i_count);
 		d_instantiate(dentry, inode);
@@ -1630,6 +1654,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		      struct inode *new_dir, struct dentry *new_dentry)
 {
+	struct cred *acred = current->cred;
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	struct dentry *dentry = NULL, *rehash = NULL;
@@ -1673,7 +1698,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			goto out;
 
 		/* silly-rename the existing target ... */
-		err = nfs_sillyrename(new_dir, new_dentry);
+		err = nfs_sillyrename(new_dir, new_dentry, acred);
 		if (!err) {
 			new_dentry = rehash = dentry;
 			new_inode = NULL;
@@ -1705,7 +1730,8 @@ go_ahead:
 	nfs_begin_data_update(new_dir);
 	nfs_begin_data_update(old_inode);
 	error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
-					   new_dir, &new_dentry->d_name);
+					   new_dir, &new_dentry->d_name,
+					   acred);
 	nfs_mark_for_revalidate(old_inode);
 	nfs_end_data_update(old_inode);
 	nfs_end_data_update(new_dir);
@@ -1934,7 +1960,8 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
 	}
 }
 
-static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask,
+			 struct cred *acred)
 {
 	struct nfs_access_entry cache;
 	int status;
@@ -1947,7 +1974,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
 	cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
 	cache.cred = cred;
 	cache.jiffies = jiffies;
-	status = NFS_PROTO(inode)->access(inode, &cache);
+	status = NFS_PROTO(inode)->access(inode, &cache, acred);
 	if (status != 0)
 		return status;
 	nfs_access_add_cache(inode, &cache);
@@ -1998,7 +2025,7 @@ force_lookup:
 
 	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0, acred);
 	if (!IS_ERR(cred)) {
-		res = nfs_do_access(inode, cred, mask);
+		res = nfs_do_access(inode, cred, mask, acred);
 		put_rpccred(cred);
 	} else
 		res = PTR_ERR(cred);
@@ -2008,7 +2035,7 @@ out:
 		inode->i_sb->s_id, inode->i_ino, mask, res);
 	return res;
 out_notsup:
-	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	res = nfs_revalidate_inode(NFS_SERVER(inode), inode, acred);
 	if (res == 0)
 		res = generic_permission(inode, mask, NULL);
 	unlock_kernel();
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index fcf4d38..6c9491b 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -291,14 +291,14 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
 					data->npages, 1, 0, data->pagevec, NULL);
 		up_read(&current->mm->mmap_sem);
 		if (result < 0) {
-			nfs_readdata_release(data);
+			nfs_readdata_release(ctx->acred, data);
 			break;
 		}
 		if ((unsigned)result < data->npages) {
 			bytes = result * PAGE_SIZE;
 			if (bytes <= pgbase) {
 				nfs_direct_release_pages(data->pagevec, result);
-				nfs_readdata_release(data);
+				nfs_readdata_release(ctx->acred, data);
 				break;
 			}
 			bytes -= pgbase;
@@ -321,8 +321,8 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
 		data->res.count = bytes;
 
 		rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
-				&nfs_read_direct_ops, data);
-		NFS_PROTO(inode)->read_setup(data);
+			      &nfs_read_direct_ops, data, ctx->acred);
+		NFS_PROTO(inode)->read_setup(data, ctx->acred);
 
 		data->task.tk_cookie = (unsigned long) inode;
 
@@ -389,7 +389,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
 		struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages);
 		list_del(&data->pages);
 		nfs_direct_release_pages(data->pagevec, data->npages);
-		nfs_writedata_release(data);
+		nfs_writedata_release(dreq->ctx->acred, data);
 	}
 }
 
@@ -420,8 +420,9 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 		 * since the original request was sent.
 		 */
 		rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
-				&nfs_write_direct_ops, data);
-		NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE);
+				&nfs_write_direct_ops, data, dreq->ctx->acred);
+		NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE,
+					      dreq->ctx->acred);
 
 		data->task.tk_priority = RPC_PRIORITY_NORMAL;
 		data->task.tk_cookie = (unsigned long) inode;
@@ -484,8 +485,8 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
 	data->res.verf = &data->verf;
 
 	rpc_init_task(&data->task, NFS_CLIENT(dreq->inode), RPC_TASK_ASYNC,
-				&nfs_commit_direct_ops, data);
-	NFS_PROTO(data->inode)->commit_setup(data, 0);
+				&nfs_commit_direct_ops, data, dreq->ctx->acred);
+	NFS_PROTO(data->inode)->commit_setup(data, 0, dreq->ctx->acred);
 
 	data->task.tk_priority = RPC_PRIORITY_NORMAL;
 	data->task.tk_cookie = (unsigned long)data->inode;
@@ -582,7 +583,7 @@ out_unlock:
  * NB: Return the value of the first error return code.  Subsequent
  *     errors after the first one are ignored.
  */
-static void nfs_direct_write_release(void *calldata)
+static void nfs_direct_write_release(struct cred *acred, void *calldata)
 {
 	struct nfs_write_data *data = calldata;
 	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
@@ -631,14 +632,14 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
 					data->npages, 0, 0, data->pagevec, NULL);
 		up_read(&current->mm->mmap_sem);
 		if (result < 0) {
-			nfs_writedata_release(data);
+			nfs_writedata_release(ctx->acred, data);
 			break;
 		}
 		if ((unsigned)result < data->npages) {
 			bytes = result * PAGE_SIZE;
 			if (bytes <= pgbase) {
 				nfs_direct_release_pages(data->pagevec, result);
-				nfs_writedata_release(data);
+				nfs_writedata_release(ctx->acred, data);
 				break;
 			}
 			bytes -= pgbase;
@@ -663,8 +664,8 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
 		data->res.verf = &data->verf;
 
 		rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
-				&nfs_write_direct_ops, data);
-		NFS_PROTO(inode)->write_setup(data, sync);
+				&nfs_write_direct_ops, data, ctx->acred);
+		NFS_PROTO(inode)->write_setup(data, sync, ctx->acred);
 
 		data->task.tk_priority = RPC_PRIORITY_NORMAL;
 		data->task.tk_cookie = (unsigned long) inode;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 579cf8a..72f0850 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -158,7 +158,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
 	if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
 		return 0;
 force_reval:
-	return __nfs_revalidate_inode(server, inode);
+	return __nfs_revalidate_inode(server, inode, filp->f_cred);
 }
 
 static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
@@ -196,7 +196,8 @@ nfs_file_flush(struct file *file, fl_owner_t id)
 		status = ctx->error;
 		ctx->error = 0;
 		if (!status)
-			nfs_revalidate_inode(NFS_SERVER(inode), inode);
+			nfs_revalidate_inode(NFS_SERVER(inode), inode,
+					     ctx->acred);
 	}
 	unlock_kernel();
 	return status;
@@ -208,6 +209,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
 {
 	struct dentry * dentry = iocb->ki_filp->f_path.dentry;
 	struct inode * inode = dentry->d_inode;
+	struct cred *acred = iocb->ki_filp->f_cred;
 	ssize_t result;
 	size_t count = iov_length(iov, nr_segs);
 
@@ -220,7 +222,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long) pos);
 
-	result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
+	result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping, acred);
 	nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
 	if (!result)
 		result = generic_file_aio_read(iocb, iov, nr_segs, pos);
@@ -234,13 +236,14 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
 {
 	struct dentry *dentry = filp->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
+	struct cred *acred = filp->f_cred;
 	ssize_t res;
 
 	dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long long) *ppos);
 
-	res = nfs_revalidate_mapping(inode, filp->f_mapping);
+	res = nfs_revalidate_mapping(inode, filp->f_mapping, acred);
 	if (!res)
 		res = generic_file_splice_read(filp, ppos, pipe, count, flags);
 	return res;
@@ -251,12 +254,13 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
 	struct dentry *dentry = file->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
+	struct cred *acred = file->f_cred;
 	int	status;
 
 	dfprintk(VFS, "nfs: mmap(%s/%s)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	status = nfs_revalidate_mapping(inode, file->f_mapping);
+	status = nfs_revalidate_mapping(inode, file->f_mapping, acred);
 	if (!status)
 		status = generic_file_mmap(file, vma);
 	return status;
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 93d1479..17a0ac8 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -45,7 +45,8 @@
 /*
  * get an NFS2/NFS3 root dentry from the root filehandle
  */
-struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+			    struct cred *acred)
 {
 	struct nfs_server *server = NFS_SB(sb);
 	struct nfs_fsinfo fsinfo;
@@ -84,7 +85,8 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	/* get the actual root for this mount */
 	fsinfo.fattr = &fattr;
 
-	error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+	error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo,
+						     acred);
 	if (error < 0) {
 		dprintk("nfs_get_root: getattr error = %d\n", -error);
 		return ERR_PTR(error);
@@ -126,7 +128,8 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
  */
 int nfs4_path_walk(struct nfs_server *server,
 		   struct nfs_fh *mntfh,
-		   const char *path)
+		   const char *path,
+		   struct cred *acred)
 {
 	struct nfs_fsinfo fsinfo;
 	struct nfs_fattr fattr;
@@ -144,7 +147,8 @@ int nfs4_path_walk(struct nfs_server *server,
 		path++;
 
 	/* Start by getting the root filehandle from the server */
-	ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+	ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo,
+						   acred);
 	if (ret < 0) {
 		dprintk("nfs4_get_root: getroot error = %d\n", -ret);
 		return ret;
@@ -201,7 +205,7 @@ eat_dot_dir:
 	dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path);
 
 	ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name,
-						    mntfh, &fattr);
+						    mntfh, &fattr, acred);
 	if (ret < 0) {
 		dprintk("nfs4_get_root: getroot error = %d\n", -ret);
 		return ret;
@@ -231,7 +235,8 @@ path_walk_complete:
 /*
  * get an NFS4 root dentry from the root filehandle
  */
-struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+			     struct cred *acred)
 {
 	struct nfs_server *server = NFS_SB(sb);
 	struct nfs_fattr fattr;
@@ -269,7 +274,7 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	}
 
 	/* get the info about the server and filesystem */
-	error = nfs4_server_capabilities(server, mntfh);
+	error = nfs4_server_capabilities(server, mntfh, acred);
 	if (error < 0) {
 		dprintk("nfs_get_root: getcaps error = %d\n",
 			-error);
@@ -277,7 +282,8 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	}
 
 	/* get the actual root for this mount */
-	error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+	error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr,
+						     acred);
 	if (error < 0) {
 		dprintk("nfs_get_root: getattr error = %d\n", -error);
 		return ERR_PTR(error);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 0dd2ac3..300560f 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -321,6 +321,7 @@ out_no_inode:
 int
 nfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct nfs_fattr fattr;
 	int error;
@@ -349,7 +350,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
 	 */
 	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
 		nfs_inode_return_delegation(inode);
-	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
+	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr, acred);
 	if (error == 0)
 		nfs_refresh_inode(inode, &fattr);
 	nfs_end_data_update(inode);
@@ -425,6 +426,7 @@ static void nfs_wake_up_inode(struct inode *inode)
 
 int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
 	int err;
@@ -447,15 +449,18 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 		need_atime = 0;
 
 	if (need_atime)
-		err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+		err = __nfs_revalidate_inode(NFS_SERVER(inode), inode, acred);
 	else
-		err = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+		err = nfs_revalidate_inode(NFS_SERVER(inode), inode, acred);
 	if (!err)
 		generic_fillattr(inode, stat);
 	return err;
 }
 
-static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred)
+static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt,
+						       struct dentry *dentry,
+						       struct rpc_cred *cred,
+						       struct cred *acred)
 {
 	struct nfs_open_context *ctx;
 
@@ -463,6 +468,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
 	if (ctx != NULL) {
 		ctx->path.dentry = dget(dentry);
 		ctx->path.mnt = mntget(mnt);
+		ctx->acred = get_cred(acred);
 		ctx->cred = get_rpccred(cred);
 		ctx->state = NULL;
 		ctx->lockowner = current->files;
@@ -489,9 +495,10 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
 	list_del(&ctx->list);
 	spin_unlock(&inode->i_lock);
 	if (ctx->state != NULL)
-		nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+		nfs4_close_state(&ctx->path, ctx->state, ctx->mode, ctx->acred);
 	if (ctx->cred != NULL)
 		put_rpccred(ctx->cred);
+	put_cred(ctx->acred);
 	dput(ctx->path.dentry);
 	mntput(ctx->path.mnt);
 	kfree(ctx);
@@ -558,7 +565,8 @@ int nfs_open(struct inode *inode, struct file *filp)
 	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0, filp->f_cred);
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
+	ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred,
+				     filp->f_cred);
 	put_rpccred(cred);
 	if (ctx == NULL)
 		return -ENOMEM;
@@ -579,7 +587,8 @@ int nfs_release(struct inode *inode, struct file *filp)
  * the cached attributes have to be refreshed.
  */
 int
-__nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+__nfs_revalidate_inode(struct nfs_server *server, struct inode *inode,
+		       struct cred *acred)
 {
 	int		 status = -ESTALE;
 	struct nfs_fattr fattr;
@@ -609,7 +618,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		}
 	}
 
-	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
+	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr,
+					   acred);
 	if (status != 0) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
 			 inode->i_sb->s_id,
@@ -661,15 +671,17 @@ int nfs_attribute_timeout(struct inode *inode)
  * nfs_revalidate_inode - Revalidate the inode attributes
  * @server - pointer to nfs_server struct
  * @inode - pointer to inode struct
+ * @acred - the credentials to use
  *
  * Updates inode attribute information by retrieving the data from the server.
  */
-int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode,
+			 struct cred *acred)
 {
 	if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR)
 			&& !nfs_attribute_timeout(inode))
 		return NFS_STALE(inode) ? -ESTALE : 0;
-	return __nfs_revalidate_inode(server, inode);
+	return __nfs_revalidate_inode(server, inode, acred);
 }
 
 static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_space *mapping)
@@ -713,15 +725,18 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map
  * nfs_revalidate_mapping_nolock - Revalidate the pagecache
  * @inode - pointer to host inode
  * @mapping - pointer to mapping
+ * @acred - the credentials to use
  */
-int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping)
+int nfs_revalidate_mapping_nolock(struct inode *inode,
+				  struct address_space *mapping,
+				  struct cred *acred)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	int ret = 0;
 
 	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
 			|| nfs_attribute_timeout(inode) || NFS_STALE(inode)) {
-		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode, acred);
 		if (ret < 0)
 			goto out;
 	}
@@ -735,18 +750,20 @@ out:
  * nfs_revalidate_mapping - Revalidate the pagecache
  * @inode - pointer to host inode
  * @mapping - pointer to mapping
+ * @acred - the credentials to use
  *
  * This version of the function will take the inode->i_mutex and attempt to
  * flush out all dirty data if it needs to invalidate the page cache.
  */
-int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping,
+			   struct cred *acred)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	int ret = 0;
 
 	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
 			|| nfs_attribute_timeout(inode) || NFS_STALE(inode)) {
-		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode, acred);
 		if (ret < 0)
 			goto out;
 	}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 76cf55d..777f1ac 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -33,20 +33,23 @@ extern struct rpc_program nfs_program;
 extern void nfs_put_client(struct nfs_client *);
 extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int);
 extern struct nfs_server *nfs_create_server(const struct nfs_mount_data *,
-					    struct nfs_fh *);
+					    struct nfs_fh *, struct cred *);
 extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *,
 					     const char *,
 					     const struct sockaddr_in *,
 					     const char *,
 					     const char *,
 					     rpc_authflavor_t,
-					     struct nfs_fh *);
+					     struct nfs_fh *,
+					     struct cred *);
 extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
-						      struct nfs_fh *);
+						      struct nfs_fh *,
+						      struct cred *);
 extern void nfs_free_server(struct nfs_server *server);
 extern struct nfs_server *nfs_clone_server(struct nfs_server *,
 					   struct nfs_fh *,
-					   struct nfs_fattr *);
+					   struct nfs_fattr *,
+					   struct cred *);
 #ifdef CONFIG_PROC_FS
 extern int __init nfs_fs_proc_init(void);
 extern void nfs_fs_proc_exit(void);
@@ -62,7 +65,9 @@ static inline void nfs_fs_proc_exit(void)
 
 /* nfs4namespace.c */
 #ifdef CONFIG_NFS_V4
-extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
+extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent,
+					struct dentry *dentry,
+					struct cred *acred);
 #else
 static inline
 struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
@@ -140,13 +145,16 @@ extern char *nfs_path(const char *base,
 		      char *buffer, ssize_t buflen);
 
 /* getroot.c */
-extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *);
+extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
+				   struct cred *);
 #ifdef CONFIG_NFS_V4
-extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *);
+extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
+				    struct cred *);
 
 extern int nfs4_path_walk(struct nfs_server *server,
 			  struct nfs_fh *mntfh,
-			  const char *path);
+			  const char *path,
+			  struct cred *acred);
 #endif
 
 /*
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 8afd9f7..50da910 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -35,11 +35,12 @@ struct mnt_fhstatus {
  * @version: mount version to use for this request
  * @protocol: transport protocol to use for thie request
  * @fh: pointer to location to place returned file handle
+ * @cred: the credentials to use
  *
  * Uses default timeout parameters specified by underlying transport.
  */
 int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
-	      int version, int protocol, struct nfs_fh *fh)
+	      int version, int protocol, struct nfs_fh *fh, struct cred *acred)
 {
 	struct mnt_fhstatus	result = {
 		.fh		= fh
@@ -64,7 +65,7 @@ int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
 	dprintk("NFS: sending MNT request for %s:%s\n",
 		(hostname ? hostname : "server"), path);
 
-	mnt_clnt = rpc_create(&args);
+	mnt_clnt = rpc_create(&args, acred);
 	if (IS_ERR(mnt_clnt))
 		goto out_clnt_err;
 
@@ -73,7 +74,7 @@ int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
 	else
 		msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
 
-	status = rpc_call_sync(mnt_clnt, &msg, 0);
+	status = rpc_call_sync(mnt_clnt, &msg, 0, acred);
 	rpc_shutdown_client(mnt_clnt);
 
 	if (status < 0)
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index acfc56f..b8d3576 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -96,6 +96,7 @@ Elong:
  */
 static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
 {
+	struct cred *acred = current->cred;
 	struct vfsmount *mnt;
 	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
 	struct dentry *parent;
@@ -114,13 +115,13 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
 	parent = dget_parent(nd->dentry);
 	err = server->nfs_client->rpc_ops->lookup(parent->d_inode,
 						  &nd->dentry->d_name,
-						  &fh, &fattr);
+						  &fh, &fattr, acred);
 	dput(parent);
 	if (err != 0)
 		goto out_err;
 
 	if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL)
-		mnt = nfs_do_refmount(nd->mnt, nd->dentry);
+		mnt = nfs_do_refmount(nd->mnt, nd->dentry, acred);
 	else
 		mnt = nfs_do_submount(nd->mnt, nd->dentry, &fh, &fattr);
 	err = PTR_ERR(mnt);
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 7322da4..0fefed1 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -9,6 +9,7 @@
 
 ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl;
 	int pos=0, len=0;
@@ -21,7 +22,7 @@ ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
 			len += sizeof(s);				\
 		} while(0)
 
-	acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS);
+	acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS, acred);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl) {
@@ -30,7 +31,7 @@ ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
 	}
 
 	if (S_ISDIR(inode->i_mode)) {
-		acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT);
+		acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT, acred);
 		if (IS_ERR(acl))
 			return PTR_ERR(acl);
 		if (acl) {
@@ -49,6 +50,7 @@ ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
 ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
 		void *buffer, size_t size)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl;
 	int type, error = 0;
@@ -60,7 +62,7 @@ ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
 	else
 		return -EOPNOTSUPP;
 
-	acl = nfs3_proc_getacl(inode, type);
+	acl = nfs3_proc_getacl(inode, type, acred);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	else if (acl) {
@@ -78,6 +80,7 @@ ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
 int nfs3_setxattr(struct dentry *dentry, const char *name,
 	     const void *value, size_t size, int flags)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl;
 	int type, error;
@@ -92,7 +95,7 @@ int nfs3_setxattr(struct dentry *dentry, const char *name,
 	acl = posix_acl_from_xattr(value, size);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
-	error = nfs3_proc_setacl(inode, type, acl);
+	error = nfs3_proc_setacl(inode, type, acl, acred);
 	posix_acl_release(acl);
 
 	return error;
@@ -100,6 +103,7 @@ int nfs3_setxattr(struct dentry *dentry, const char *name,
 
 int nfs3_removexattr(struct dentry *dentry, const char *name)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int type;
 
@@ -110,7 +114,7 @@ int nfs3_removexattr(struct dentry *dentry, const char *name)
 	else
 		return -EOPNOTSUPP;
 
-	return nfs3_proc_setacl(inode, type, NULL);
+	return nfs3_proc_setacl(inode, type, NULL, acred);
 }
 
 static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
@@ -179,7 +183,8 @@ static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
 	spin_unlock(&inode->i_lock);
 }
 
-struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
+struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type,
+				   struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs_fattr fattr;
@@ -202,7 +207,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
 	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
 		return ERR_PTR(-EOPNOTSUPP);
 
-	status = nfs_revalidate_inode(server, inode);
+	status = nfs_revalidate_inode(server, inode, acred);
 	if (status < 0)
 		return ERR_PTR(status);
 	acl = nfs3_get_cached_acl(inode, type);
@@ -225,7 +230,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
 
 	dprintk("NFS call getacl\n");
 	msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL];
-	status = rpc_call_sync(server->client_acl, &msg, 0);
+	status = rpc_call_sync(server->client_acl, &msg, 0, acred);
 	dprintk("NFS reply getacl: %d\n", status);
 
 	/* pages may have been allocated at the xdr layer. */
@@ -283,7 +288,7 @@ getout:
 }
 
 static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
-		  struct posix_acl *dfacl)
+		  struct posix_acl *dfacl, struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs_fattr fattr;
@@ -319,7 +324,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
 	dprintk("NFS call setacl\n");
 	nfs_begin_data_update(inode);
 	msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL];
-	status = rpc_call_sync(server->client_acl, &msg, 0);
+	status = rpc_call_sync(server->client_acl, &msg, 0, acred);
 	spin_lock(&inode->i_lock);
 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS;
 	spin_unlock(&inode->i_lock);
@@ -347,7 +352,8 @@ out:
 	return status;
 }
 
-int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
+int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl,
+		     struct cred *acred)
 {
 	struct posix_acl *alloc = NULL, *dfacl = NULL;
 	int status;
@@ -356,7 +362,7 @@ int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
 		switch(type) {
 			case ACL_TYPE_ACCESS:
 				alloc = dfacl = nfs3_proc_getacl(inode,
-						ACL_TYPE_DEFAULT);
+						ACL_TYPE_DEFAULT, acred);
 				if (IS_ERR(alloc))
 					goto fail;
 				break;
@@ -364,7 +370,7 @@ int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
 			case ACL_TYPE_DEFAULT:
 				dfacl = acl;
 				alloc = acl = nfs3_proc_getacl(inode,
-						ACL_TYPE_ACCESS);
+						ACL_TYPE_ACCESS, acred);
 				if (IS_ERR(alloc))
 					goto fail;
 				break;
@@ -380,7 +386,7 @@ int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
 		if (IS_ERR(alloc))
 			goto fail;
 	}
-	status = nfs3_proc_setacls(inode, acl, dfacl);
+	status = nfs3_proc_setacls(inode, acl, dfacl, acred);
 	posix_acl_release(alloc);
 	return status;
 
@@ -389,12 +395,12 @@ fail:
 }
 
 int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-		mode_t mode)
+		mode_t mode, struct cred *acred)
 {
 	struct posix_acl *dfacl, *acl;
 	int error = 0;
 
-	dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT);
+	dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT, acred);
 	if (IS_ERR(dfacl)) {
 		error = PTR_ERR(dfacl);
 		return (error == -EOPNOTSUPP) ? 0 : error;
@@ -408,8 +414,9 @@ int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
 	error = posix_acl_create_masq(acl, &mode);
 	if (error < 0)
 		goto out_release_acl;
-	error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
-						      dfacl : NULL);
+	error = nfs3_proc_setacls(inode, acl,
+				  S_ISDIR(inode->i_mode) ? dfacl : NULL,
+				  acred);
 out_release_acl:
 	posix_acl_release(acl);
 out_release_dfacl:
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 329e6a2..4d66cfd 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -25,13 +25,14 @@
 
 /* A wrapper to handle the EJUKEBOX error message */
 static int
-nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
+		 struct cred *acred)
 {
 	sigset_t oldset;
 	int res;
 	rpc_clnt_sigmask(clnt, &oldset);
 	do {
-		res = rpc_call_sync(clnt, msg, flags);
+		res = rpc_call_sync(clnt, msg, flags, acred);
 		if (res != -EJUKEBOX)
 			break;
 		schedule_timeout_interruptible(NFS_JUKEBOX_RETRY_TIME);
@@ -41,7 +42,8 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 	return res;
 }
 
-#define rpc_call_sync(clnt, msg, flags)	nfs3_rpc_wrapper(clnt, msg, flags)
+#define rpc_call_sync(clnt, msg, flags, acred) \
+	nfs3_rpc_wrapper(clnt, msg, flags, acred)
 
 static int
 nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
@@ -57,7 +59,7 @@ nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
 
 static int
 do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
-		 struct nfs_fsinfo *info)
+		 struct nfs_fsinfo *info, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_FSINFO],
@@ -68,12 +70,12 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
 
 	dprintk("%s: call  fsinfo\n", __FUNCTION__);
 	nfs_fattr_init(info->fattr);
-	status = rpc_call_sync(client, &msg, 0);
+	status = rpc_call_sync(client, &msg, 0, acred);
 	dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status);
 	if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
 		msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
 		msg.rpc_resp = info->fattr;
-		status = rpc_call_sync(client, &msg, 0);
+		status = rpc_call_sync(client, &msg, 0, acred);
 		dprintk("%s: reply getattr: %d\n", __FUNCTION__, status);
 	}
 	return status;
@@ -84,13 +86,14 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
  */
 static int
 nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
-		   struct nfs_fsinfo *info)
+		   struct nfs_fsinfo *info, struct cred *acred)
 {
 	int	status;
 
-	status = do_proc_get_root(server->client, fhandle, info);
+	status = do_proc_get_root(server->client, fhandle, info, acred);
 	if (status && server->nfs_client->cl_rpcclient != server->client)
-		status = do_proc_get_root(server->nfs_client->cl_rpcclient, fhandle, info);
+		status = do_proc_get_root(server->nfs_client->cl_rpcclient,
+					  fhandle, info, acred);
 	return status;
 }
 
@@ -99,7 +102,7 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 static int
 nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_GETATTR],
@@ -110,14 +113,14 @@ nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	dprintk("NFS call  getattr\n");
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	dprintk("NFS reply getattr: %d\n", status);
 	return status;
 }
 
 static int
 nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
-			struct iattr *sattr)
+			struct iattr *sattr, struct cred *acred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct nfs3_sattrargs	arg = {
@@ -133,7 +136,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 	dprintk("NFS call  setattr\n");
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	if (status == 0)
 		nfs_setattr_update_inode(inode, sattr);
 	dprintk("NFS reply setattr: %d\n", status);
@@ -142,7 +145,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 static int
 nfs3_proc_lookup(struct inode *dir, struct qstr *name,
-		 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		 struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		 struct cred *acred)
 {
 	struct nfs_fattr	dir_attr;
 	struct nfs3_diropargs	arg = {
@@ -165,12 +169,12 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
 	dprintk("NFS call  lookup %s\n", name->name);
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
 		msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
 		msg.rpc_argp = fhandle;
 		msg.rpc_resp = fattr;
-		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	}
 	dprintk("NFS reply lookup: %d\n", status);
 	if (status >= 0)
@@ -178,7 +182,8 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
 	return status;
 }
 
-static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
+static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry,
+			    struct cred *acred)
 {
 	struct nfs_fattr	fattr;
 	struct nfs3_accessargs	arg = {
@@ -212,7 +217,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 			arg.access |= NFS3_ACCESS_EXECUTE;
 	}
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	nfs_refresh_inode(inode, &fattr);
 	if (status == 0) {
 		entry->mask = 0;
@@ -228,7 +233,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 }
 
 static int nfs3_proc_readlink(struct inode *inode, struct page *page,
-		unsigned int pgbase, unsigned int pglen)
+		unsigned int pgbase, unsigned int pglen, struct cred *acred)
 {
 	struct nfs_fattr	fattr;
 	struct nfs3_readlinkargs args = {
@@ -246,7 +251,7 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page,
 
 	dprintk("NFS call  readlink\n");
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	nfs_refresh_inode(inode, &fattr);
 	dprintk("NFS reply readlink: %d\n", status);
 	return status;
@@ -258,7 +263,7 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page,
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		 int flags, struct nameidata *nd)
+		 int flags, struct nameidata *nd, struct cred *acred)
 {
 	struct nfs_fh		fhandle;
 	struct nfs_fattr	fattr;
@@ -295,7 +300,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 again:
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_refresh_inode(dir, &dir_attr);
 
 	/* If the server doesn't support the exclusive creation semantics,
@@ -317,7 +322,7 @@ again:
 	}
 
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 	if (status != 0)
 		goto out;
 
@@ -334,20 +339,20 @@ again:
 		/* Note: we could use a guarded setattr here, but I'm
 		 * not sure this buys us anything (and I'd have
 		 * to revamp the NFSv3 XDR code) */
-		status = nfs3_proc_setattr(dentry, &fattr, sattr);
+		status = nfs3_proc_setattr(dentry, &fattr, sattr, acred);
 		nfs_post_op_update_inode(dentry->d_inode, &fattr);
 		dprintk("NFS reply setattr (post-create): %d\n", status);
 	}
 	if (status != 0)
 		goto out;
-	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode, acred);
 out:
 	dprintk("NFS reply create: %d\n", status);
 	return status;
 }
 
 static int
-nfs3_proc_remove(struct inode *dir, struct qstr *name)
+nfs3_proc_remove(struct inode *dir, struct qstr *name, struct cred *acred)
 {
 	struct nfs_removeargs arg = {
 		.fh = NFS_FH(dir),
@@ -364,7 +369,7 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name)
 
 	dprintk("NFS call  remove %s\n", name->name);
 	nfs_fattr_init(&res.dir_attr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_post_op_update_inode(dir, &res.dir_attr);
 	dprintk("NFS reply remove: %d\n", status);
 	return status;
@@ -389,7 +394,8 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 
 static int
 nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
-		 struct inode *new_dir, struct qstr *new_name)
+		 struct inode *new_dir, struct qstr *new_name,
+		 struct cred *acred)
 {
 	struct nfs_fattr	old_dir_attr, new_dir_attr;
 	struct nfs3_renameargs	arg = {
@@ -414,7 +420,7 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
 	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
 	nfs_fattr_init(&old_dir_attr);
 	nfs_fattr_init(&new_dir_attr);
-	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0, acred);
 	nfs_post_op_update_inode(old_dir, &old_dir_attr);
 	nfs_post_op_update_inode(new_dir, &new_dir_attr);
 	dprintk("NFS reply rename: %d\n", status);
@@ -422,7 +428,8 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
 }
 
 static int
-nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name,
+	       struct cred *acred)
 {
 	struct nfs_fattr	dir_attr, fattr;
 	struct nfs3_linkargs	arg = {
@@ -445,7 +452,7 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 	dprintk("NFS call  link %s\n", name->name);
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	nfs_post_op_update_inode(dir, &dir_attr);
 	nfs_post_op_update_inode(inode, &fattr);
 	dprintk("NFS reply link: %d\n", status);
@@ -454,7 +461,7 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 
 static int
 nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
-		  unsigned int len, struct iattr *sattr)
+		  unsigned int len, struct iattr *sattr, struct cred *acred)
 {
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr, dir_attr;
@@ -485,18 +492,18 @@ nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
 
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_post_op_update_inode(dir, &dir_attr);
 	if (status != 0)
 		goto out;
-	status = nfs_instantiate(dentry, &fhandle, &fattr);
+	status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 out:
 	dprintk("NFS reply symlink: %d\n", status);
 	return status;
 }
 
 static int
-nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
+nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr, struct cred *acred)
 {
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr, dir_attr;
@@ -525,21 +532,21 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_post_op_update_inode(dir, &dir_attr);
 	if (status != 0)
 		goto out;
-	status = nfs_instantiate(dentry, &fhandle, &fattr);
+	status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 	if (status != 0)
 		goto out;
-	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode, acred);
 out:
 	dprintk("NFS reply mkdir: %d\n", status);
 	return status;
 }
 
 static int
-nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
+nfs3_proc_rmdir(struct inode *dir, struct qstr *name, struct cred *acred)
 {
 	struct nfs_fattr	dir_attr;
 	struct nfs3_diropargs	arg = {
@@ -556,7 +563,7 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
 
 	dprintk("NFS call  rmdir %s\n", name->name);
 	nfs_fattr_init(&dir_attr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_post_op_update_inode(dir, &dir_attr);
 	dprintk("NFS reply rmdir: %d\n", status);
 	return status;
@@ -573,7 +580,8 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
  */
 static int
 nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-		  u64 cookie, struct page *page, unsigned int count, int plus)
+		  u64 cookie, struct page *page, unsigned int count, int plus,
+		  struct cred *acred)
 {
 	struct inode		*dir = dentry->d_inode;
 	struct nfs_fattr	dir_attr;
@@ -606,7 +614,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 			plus? "plus" : "", (unsigned int) cookie);
 
 	nfs_fattr_init(&dir_attr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_refresh_inode(dir, &dir_attr);
 	dprintk("NFS reply readdir: %d\n", status);
 	return status;
@@ -614,7 +622,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 
 static int
 nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		dev_t rdev)
+		dev_t rdev, struct cred *acred)
 {
 	struct nfs_fh fh;
 	struct nfs_fattr fattr, dir_attr;
@@ -653,14 +661,14 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 
 	nfs_fattr_init(&dir_attr);
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_post_op_update_inode(dir, &dir_attr);
 	if (status != 0)
 		goto out;
-	status = nfs_instantiate(dentry, &fh, &fattr);
+	status = nfs_instantiate(dentry, &fh, &fattr, acred);
 	if (status != 0)
 		goto out;
-	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode, acred);
 out:
 	dprintk("NFS reply mknod: %d\n", status);
 	return status;
@@ -668,7 +676,7 @@ out:
 
 static int
 nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
-		 struct nfs_fsstat *stat)
+		 struct nfs_fsstat *stat, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_FSSTAT],
@@ -679,14 +687,14 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	dprintk("NFS call  fsstat\n");
 	nfs_fattr_init(stat->fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	dprintk("NFS reply statfs: %d\n", status);
 	return status;
 }
 
 static int
 nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
-		 struct nfs_fsinfo *info)
+		 struct nfs_fsinfo *info, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_FSINFO],
@@ -697,14 +705,15 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	dprintk("NFS call  fsinfo\n");
 	nfs_fattr_init(info->fattr);
-	status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+	status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0,
+			       acred);
 	dprintk("NFS reply fsinfo: %d\n", status);
 	return status;
 }
 
 static int
 nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
-		   struct nfs_pathconf *info)
+		   struct nfs_pathconf *info, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_PATHCONF],
@@ -715,7 +724,7 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	dprintk("NFS call  pathconf\n");
 	nfs_fattr_init(info->fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	dprintk("NFS reply pathconf: %d\n", status);
 	return status;
 }
@@ -730,7 +739,7 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
 	return 0;
 }
 
-static void nfs3_proc_read_setup(struct nfs_read_data *data)
+static void nfs3_proc_read_setup(struct nfs_read_data *data, struct cred *acred)
 {
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],
@@ -739,7 +748,7 @@ static void nfs3_proc_read_setup(struct nfs_read_data *data)
 		.rpc_cred	= data->cred,
 	};
 
-	rpc_call_setup(&data->task, &msg, 0, current->cred);
+	rpc_call_setup(&data->task, &msg, 0, acred);
 }
 
 static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -751,7 +760,8 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
 	return 0;
 }
 
-static void nfs3_proc_write_setup(struct nfs_write_data *data, int how)
+static void nfs3_proc_write_setup(struct nfs_write_data *data, int how,
+				  struct cred *acred)
 {
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_WRITE],
@@ -768,7 +778,7 @@ static void nfs3_proc_write_setup(struct nfs_write_data *data, int how)
 	}
 
 	/* Finalize the task. */
-	rpc_call_setup(&data->task, &msg, 0, current->cred);
+	rpc_call_setup(&data->task, &msg, 0, acred);
 }
 
 static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -780,7 +790,8 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
 	return 0;
 }
 
-static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
+static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how,
+				   struct cred *acred)
 {
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_COMMIT],
@@ -789,13 +800,14 @@ static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
 		.rpc_cred	= data->cred,
 	};
 
-	rpc_call_setup(&data->task, &msg, 0, current->cred);
+	rpc_call_setup(&data->task, &msg, 0, acred);
 }
 
 static int
 nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
-	return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl);
+	return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl,
+			    filp->f_cred);
 }
 
 const struct nfs_rpc_ops nfs_v3_clientops = {
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d2802b1..007329e 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -174,16 +174,25 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
 
 /* nfs4proc.c */
 extern int nfs4_map_errors(int err);
-extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *);
-extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
-extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
-extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
-extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
+extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short,
+				 struct rpc_cred *, struct cred *);
+extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *,
+					 struct cred *);
+extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *,
+				 struct cred *);
+extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *,
+			   struct cred *);
+extern int nfs4_do_close(struct path *path, struct nfs4_state *state,
+			 struct cred *acred);
+extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *,
+				       struct nameidata *, struct cred *);
+extern int nfs4_open_revalidate(struct inode *, struct dentry *, int,
+				struct nameidata *, struct cred *);
+extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle,
+				    struct cred *acred);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
-		struct nfs4_fs_locations *fs_locations, struct page *page);
+		struct nfs4_fs_locations *fs_locations, struct page *page,
+		struct cred *acred);
 
 extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
 extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
@@ -208,7 +217,8 @@ extern void nfs4_put_state_owner(struct nfs4_state_owner *);
 extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
-extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
+extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t,
+			     struct cred *);
 extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
 extern void nfs4_schedule_state_recovery(struct nfs_client *);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index dd5fef2..1d2f2f2 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -212,9 +212,11 @@ out:
  * nfs_do_refmount - handle crossing a referral on server
  * @dentry - dentry of referral
  * @nd - nameidata info
+ * @acred - the credentials to use
  *
  */
-struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent,
+				 struct dentry *dentry, struct cred *acred)
 {
 	struct vfsmount *mnt = ERR_PTR(-ENOMEM);
 	struct dentry *parent;
@@ -240,7 +242,8 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr
 	dprintk("%s: getting locations for %s/%s\n",
 		__FUNCTION__, parent->d_name.name, dentry->d_name.name);
 
-	err = nfs4_proc_fs_locations(parent->d_inode, &dentry->d_name, fs_locations, page);
+	err = nfs4_proc_fs_locations(parent->d_inode, &dentry->d_name,
+				     fs_locations, page, acred);
 	dput(parent);
 	if (err != 0 ||
 	    fs_locations->nlocations <= 0 ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 943095d..83c9b66 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -59,15 +59,22 @@
 #define NFS4_POLL_RETRY_MAX	(15*HZ)
 
 struct nfs4_opendata;
-static int _nfs4_proc_open(struct nfs4_opendata *data);
-static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
+static int _nfs4_proc_open(struct nfs4_opendata *data, struct cred *acred);
+static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *,
+			  struct nfs_fsinfo *, struct cred *);
 static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
-static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
+static int _nfs4_proc_access(struct inode *inode,
+			     struct nfs_access_entry *entry,
+			     struct cred *acred);
 static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
 static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
-static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
-static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
-static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred,
+			   int openflags, struct cred *acred);
+static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
+			     struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+			     struct cred *acred);
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+			      struct nfs_fattr *fattr, struct cred *acred);
 
 /* Prevent leaks of NFSv4 errors into userland */
 int nfs4_map_errors(int err)
@@ -424,7 +431,8 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, mode_t open
 	nfs_inode_return_delegation(inode);
 }
 
-static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
+static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata,
+					       struct cred *acred)
 {
 	struct nfs4_state *state = opendata->state;
 	struct nfs_inode *nfsi = NFS_I(state->inode);
@@ -454,7 +462,8 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
 		memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data));
 		rcu_read_unlock();
 		lock_kernel();
-		ret = _nfs4_do_access(state->inode, state->owner->so_cred, open_mode);
+		ret = _nfs4_do_access(state->inode, state->owner->so_cred,
+				      open_mode, acred);
 		unlock_kernel();
 		if (ret != 0)
 			goto out;
@@ -479,7 +488,8 @@ out_return_state:
 	return state;
 }
 
-static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
+static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data,
+						      struct cred *acred)
 {
 	struct inode *inode;
 	struct nfs4_state *state = NULL;
@@ -488,7 +498,7 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
 	int ret;
 
 	if (!data->rpc_done) {
-		state = nfs4_try_open_cached(data);
+		state = nfs4_try_open_cached(data, acred);
 		goto out;
 	}
 
@@ -514,11 +524,11 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
 		if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
 			nfs_inode_set_delegation(state->inode,
 					data->owner->so_cred,
-					&data->o_res);
+					&data->o_res, acred);
 		else
 			nfs_inode_reclaim_delegation(state->inode,
 					data->owner->so_cred,
-					&data->o_res);
+					&data->o_res, acred);
 	}
 	rcu_read_lock();
 	delegation = rcu_dereference(NFS_I(inode)->delegation);
@@ -564,7 +574,9 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
 	return opendata;
 }
 
-static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res)
+static int nfs4_open_recover_helper(struct nfs4_opendata *opendata,
+				    mode_t openflags, struct nfs4_state **res,
+				    struct cred *acred)
 {
 	struct nfs4_state *newstate;
 	int ret;
@@ -573,18 +585,19 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openf
 	memset(&opendata->o_res, 0, sizeof(opendata->o_res));
 	memset(&opendata->c_res, 0, sizeof(opendata->c_res));
 	nfs4_init_opendata_res(opendata);
-	ret = _nfs4_proc_open(opendata);
+	ret = _nfs4_proc_open(opendata, acred);
 	if (ret != 0)
 		return ret; 
-	newstate = nfs4_opendata_to_nfs4_state(opendata);
+	newstate = nfs4_opendata_to_nfs4_state(opendata, acred);
 	if (IS_ERR(newstate))
 		return PTR_ERR(newstate);
-	nfs4_close_state(&opendata->path, newstate, openflags);
+	nfs4_close_state(&opendata->path, newstate, openflags, acred);
 	*res = newstate;
 	return 0;
 }
 
-static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state)
+static int nfs4_open_recover(struct nfs4_opendata *opendata,
+			     struct nfs4_state *state, struct cred *acred)
 {
 	struct nfs4_state *newstate;
 	int ret;
@@ -593,21 +606,24 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
 	clear_bit(NFS_DELEGATED_STATE, &state->flags);
 	smp_rmb();
 	if (state->n_rdwr != 0) {
-		ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
+		ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE,
+					       &newstate, acred);
 		if (ret != 0)
 			return ret;
 		if (newstate != state)
 			return -ESTALE;
 	}
 	if (state->n_wronly != 0) {
-		ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
+		ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate,
+					       acred);
 		if (ret != 0)
 			return ret;
 		if (newstate != state)
 			return -ESTALE;
 	}
 	if (state->n_rdonly != 0) {
-		ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
+		ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate,
+					       acred);
 		if (ret != 0)
 			return ret;
 		if (newstate != state)
@@ -631,7 +647,8 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
  * OPEN_RECLAIM:
  * 	reclaim state on the server after a reboot.
  */
-static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
+static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx,
+				 struct nfs4_state *state, struct cred *acred)
 {
 	struct nfs_delegation *delegation;
 	struct nfs4_opendata *opendata;
@@ -649,18 +666,19 @@ static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
 		delegation_type = delegation->type;
 	rcu_read_unlock();
 	opendata->o_arg.u.delegation_type = delegation_type;
-	status = nfs4_open_recover(opendata, state);
+	status = nfs4_open_recover(opendata, state, acred);
 	nfs4_opendata_put(opendata);
 	return status;
 }
 
-static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
+static int nfs4_do_open_reclaim(struct nfs_open_context *ctx,
+				struct nfs4_state *state, struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(state->inode);
 	struct nfs4_exception exception = { };
 	int err;
 	do {
-		err = _nfs4_do_open_reclaim(ctx, state);
+		err = _nfs4_do_open_reclaim(ctx, state, acred);
 		if (err != -NFS4ERR_DELAY)
 			break;
 		nfs4_handle_exception(server, err, &exception);
@@ -668,7 +686,8 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
 	return err;
 }
 
-static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int nfs4_open_reclaim(struct nfs4_state_owner *sp,
+			     struct nfs4_state *state)
 {
 	struct nfs_open_context *ctx;
 	int ret;
@@ -676,7 +695,7 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
 	ctx = nfs4_state_find_open_context(state);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
-	ret = nfs4_do_open_reclaim(ctx, state);
+	ret = nfs4_do_open_reclaim(ctx, state, ctx->acred);
 	put_nfs_open_context(ctx);
 	return ret;
 }
@@ -692,7 +711,7 @@ static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs
 	opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
 	memcpy(opendata->o_arg.u.delegation.data, stateid->data,
 			sizeof(opendata->o_arg.u.delegation.data));
-	ret = nfs4_open_recover(opendata, state);
+	ret = nfs4_open_recover(opendata, state, ctx->acred);
 	nfs4_opendata_put(opendata);
 	return ret;
 }
@@ -749,7 +768,7 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
 	nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
 }
 
-static void nfs4_open_confirm_release(void *calldata)
+static void nfs4_open_confirm_release(struct cred *acred, void *calldata)
 {
 	struct nfs4_opendata *data = calldata;
 	struct nfs4_state *state = NULL;
@@ -761,9 +780,10 @@ static void nfs4_open_confirm_release(void *calldata)
 	if (!data->rpc_done)
 		goto out_free;
 	nfs_confirm_seqid(&data->owner->so_seqid, 0);
-	state = nfs4_opendata_to_nfs4_state(data);
+	state = nfs4_opendata_to_nfs4_state(data, acred);
 	if (!IS_ERR(state))
-		nfs4_close_state(&data->path, state, data->o_arg.open_flags);
+		nfs4_close_state(&data->path, state, data->o_arg.open_flags,
+				 acred);
 out_free:
 	nfs4_opendata_put(data);
 }
@@ -777,7 +797,8 @@ static const struct rpc_call_ops nfs4_open_confirm_ops = {
 /*
  * Note: On error, nfs4_proc_open_confirm will free the struct nfs4_opendata
  */
-static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
+static int _nfs4_proc_open_confirm(struct nfs4_opendata *data,
+				   struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
 	struct rpc_task *task;
@@ -786,7 +807,8 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
 	kref_get(&data->kref);
 	data->rpc_done = 0;
 	data->rpc_status = 0;
-	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
+	task = rpc_run_task(server->client, RPC_TASK_ASYNC,
+			    &nfs4_open_confirm_ops, data, acred);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
 	status = nfs4_wait_for_completion_rpc_task(task);
@@ -873,7 +895,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
 	data->rpc_done = 1;
 }
 
-static void nfs4_open_release(void *calldata)
+static void nfs4_open_release(struct cred *acred, void *calldata)
 {
 	struct nfs4_opendata *data = calldata;
 	struct nfs4_state *state = NULL;
@@ -888,9 +910,10 @@ static void nfs4_open_release(void *calldata)
 	if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
 		goto out_free;
 	nfs_confirm_seqid(&data->owner->so_seqid, 0);
-	state = nfs4_opendata_to_nfs4_state(data);
+	state = nfs4_opendata_to_nfs4_state(data, acred);
 	if (!IS_ERR(state))
-		nfs4_close_state(&data->path, state, data->o_arg.open_flags);
+		nfs4_close_state(&data->path, state, data->o_arg.open_flags,
+				 acred);
 out_free:
 	nfs4_opendata_put(data);
 }
@@ -904,7 +927,7 @@ static const struct rpc_call_ops nfs4_open_ops = {
 /*
  * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
  */
-static int _nfs4_proc_open(struct nfs4_opendata *data)
+static int _nfs4_proc_open(struct nfs4_opendata *data, struct cred *acred)
 {
 	struct inode *dir = data->dir->d_inode;
 	struct nfs_server *server = NFS_SERVER(dir);
@@ -917,7 +940,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 	data->rpc_done = 0;
 	data->rpc_status = 0;
 	data->cancelled = 0;
-	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data);
+	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops,
+			    data, acred);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
 	status = nfs4_wait_for_completion_rpc_task(task);
@@ -931,7 +955,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 		return status;
 
 	if (o_res->fh.size == 0)
-		_nfs4_proc_lookup(dir, o_arg->name, &o_res->fh, o_res->f_attr);
+		_nfs4_proc_lookup(dir, o_arg->name, &o_res->fh, o_res->f_attr,
+				  acred);
 
 	if (o_arg->open_flags & O_CREAT) {
 		update_changeattr(dir, &o_res->cinfo);
@@ -939,16 +964,17 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 	} else
 		nfs_refresh_inode(dir, o_res->dir_attr);
 	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
-		status = _nfs4_proc_open_confirm(data);
+		status = _nfs4_proc_open_confirm(data, acred);
 		if (status != 0)
 			return status;
 	}
 	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
-		_nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr);
+		_nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, acred);
 	return 0;
 }
 
-static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags)
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred,
+			   int openflags, struct cred *acred)
 {
 	struct nfs_access_entry cache;
 	int mask = 0;
@@ -968,7 +994,7 @@ static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openf
 	cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
 	cache.cred = cred;
 	cache.jiffies = jiffies;
-	status = _nfs4_proc_access(inode, &cache);
+	status = _nfs4_proc_access(inode, &cache, acred);
 	if (status != 0)
 		return status;
 	nfs_access_add_cache(inode, &cache);
@@ -1007,7 +1033,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
 	opendata = nfs4_open_recoverdata_alloc(ctx, state);
 	if (IS_ERR(opendata))
 		return PTR_ERR(opendata);
-	ret = nfs4_open_recover(opendata, state);
+	ret = nfs4_open_recover(opendata, state, ctx->acred);
 	if (ret == -ESTALE) {
 		/* Invalidate the state owner so we don't ever use it again */
 		nfs4_drop_state_owner(state->owner);
@@ -1063,7 +1089,9 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct
 /*
  * Returns a referenced nfs4_state
  */
-static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_do_open(struct inode *dir, struct path *path, int flags,
+			 struct iattr *sattr, struct rpc_cred *cred,
+			 struct nfs4_state **res, struct cred *acred)
 {
 	struct nfs4_state_owner  *sp;
 	struct nfs4_state     *state = NULL;
@@ -1092,14 +1120,14 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct
 	if (path->dentry->d_inode != NULL)
 		opendata->state = nfs4_get_open_state(path->dentry->d_inode, sp);
 
-	status = _nfs4_proc_open(opendata);
+	status = _nfs4_proc_open(opendata, acred);
 	if (status != 0)
 		goto err_opendata_put;
 
 	if (opendata->o_arg.open_flags & O_EXCL)
 		nfs4_exclusive_attrset(opendata, sattr);
 
-	state = nfs4_opendata_to_nfs4_state(opendata);
+	state = nfs4_opendata_to_nfs4_state(opendata, acred);
 	status = PTR_ERR(state);
 	if (IS_ERR(state))
 		goto err_opendata_put;
@@ -1120,14 +1148,18 @@ out_err:
 }
 
 
-static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path,
+				       int flags, struct iattr *sattr,
+				       struct rpc_cred *cred,
+				       struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	struct nfs4_state *res;
 	int status;
 
 	do {
-		status = _nfs4_do_open(dir, path, flags, sattr, cred, &res);
+		status = _nfs4_do_open(dir, path, flags, sattr, cred, &res,
+				       acred);
 		if (status == 0)
 			break;
 		/* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1170,7 +1202,8 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int
 }
 
 static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
-                struct iattr *sattr, struct nfs4_state *state)
+                struct iattr *sattr, struct nfs4_state *state,
+		struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
         struct nfs_setattrargs  arg = {
@@ -1201,21 +1234,23 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
 	} else
 		memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
 
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	if (status == 0 && state != NULL)
 		renew_lease(server, timestamp);
 	return status;
 }
 
 static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
-                struct iattr *sattr, struct nfs4_state *state)
+                struct iattr *sattr, struct nfs4_state *state,
+		struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_do_setattr(inode, fattr, sattr, state),
+				_nfs4_do_setattr(inode, fattr, sattr, state,
+						 acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1231,7 +1266,7 @@ struct nfs4_closedata {
 	unsigned long timestamp;
 };
 
-static void nfs4_free_closedata(void *data)
+static void nfs4_free_closedata(struct cred *acred, void *data)
 {
 	struct nfs4_closedata *calldata = data;
 	struct nfs4_state_owner *sp = calldata->state->owner;
@@ -1336,7 +1371,8 @@ static const struct rpc_call_ops nfs4_close_ops = {
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int nfs4_do_close(struct path *path, struct nfs4_state *state)
+int nfs4_do_close(struct path *path, struct nfs4_state *state,
+		  struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(state->inode);
 	struct nfs4_closedata *calldata;
@@ -1361,7 +1397,8 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state)
 	calldata->path.mnt = mntget(path->mnt);
 	calldata->path.dentry = dget(path->dentry);
 
-	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
+	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops,
+			    calldata, acred);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
 	rpc_put_task(task);
@@ -1374,7 +1411,8 @@ out:
 	return status;
 }
 
-static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct path *path,
+				struct nfs4_state *state, struct cred *acred)
 {
 	struct file *filp;
 	int ret;
@@ -1383,7 +1421,7 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
 	if (nd->intent.open.flags & FMODE_EXEC) {
 		ret = _nfs4_do_access(state->inode,
 				state->owner->so_cred,
-				nd->intent.open.flags);
+				      nd->intent.open.flags, acred);
 		if (ret < 0)
 			goto out_close;
 	}
@@ -1396,14 +1434,14 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
 	}
 	ret = PTR_ERR(filp);
 out_close:
-	nfs4_close_state(path, state, nd->intent.open.flags);
+	nfs4_close_state(path, state, nd->intent.open.flags, acred);
 	return ret;
 }
 
 struct dentry *
-nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd,
+		 struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct path path = {
 		.mnt = nd->mnt,
 		.dentry = dentry,
@@ -1426,7 +1464,8 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0, acred);
 	if (IS_ERR(cred))
 		return (struct dentry *)cred;
-	state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
+	state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred,
+			     acred);
 	put_rpccred(cred);
 	if (IS_ERR(state)) {
 		if (PTR_ERR(state) == -ENOENT)
@@ -1436,14 +1475,14 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 	res = d_add_unique(dentry, igrab(state->inode));
 	if (res != NULL)
 		path.dentry = res;
-	nfs4_intent_set_file(nd, &path, state);
+	nfs4_intent_set_file(nd, &path, state, acred);
 	return res;
 }
 
 int
-nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
+nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags,
+		     struct nameidata *nd, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct path path = {
 		.mnt = nd->mnt,
 		.dentry = dentry,
@@ -1454,7 +1493,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
 	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0, acred);
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	state = nfs4_do_open(dir, &path, openflags, NULL, cred);
+	state = nfs4_do_open(dir, &path, openflags, NULL, cred, acred);
 	put_rpccred(cred);
 	if (IS_ERR(state)) {
 		switch (PTR_ERR(state)) {
@@ -1470,17 +1509,18 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
 		}
 	}
 	if (state->inode == dentry->d_inode) {
-		nfs4_intent_set_file(nd, &path, state);
+		nfs4_intent_set_file(nd, &path, state, acred);
 		return 1;
 	}
-	nfs4_close_state(&path, state, openflags);
+	nfs4_close_state(&path, state, openflags, acred);
 out_drop:
 	d_drop(dentry);
 	return 0;
 }
 
 
-static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
+static int _nfs4_server_capabilities(struct nfs_server *server,
+				     struct nfs_fh *fhandle, struct cred *acred)
 {
 	struct nfs4_server_caps_res res = {};
 	struct rpc_message msg = {
@@ -1490,7 +1530,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
 	};
 	int status;
 
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	if (status == 0) {
 		memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
 		if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
@@ -1504,20 +1544,22 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
 	return status;
 }
 
-int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
+int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle,
+			     struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_server_capabilities(server, fhandle),
+				_nfs4_server_capabilities(server, fhandle,
+							  acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
 static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fsinfo *info)
+		struct nfs_fsinfo *info, struct cred *acred)
 {
 	struct nfs4_lookup_root_arg args = {
 		.bitmask = nfs4_fattr_bitmap,
@@ -1533,17 +1575,17 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_resp = &res,
 	};
 	nfs_fattr_init(info->fattr);
-	return rpc_call_sync(server->client, &msg, 0);
+	return rpc_call_sync(server->client, &msg, 0, acred);
 }
 
 static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fsinfo *info)
+		struct nfs_fsinfo *info, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_lookup_root(server, fhandle, info),
+				_nfs4_lookup_root(server, fhandle, info, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1553,15 +1595,15 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
  * get the file handle for the "/" directory on the server
  */
 static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
-			      struct nfs_fsinfo *info)
+			      struct nfs_fsinfo *info, struct cred *acred)
 {
 	int status;
 
-	status = nfs4_lookup_root(server, fhandle, info);
+	status = nfs4_lookup_root(server, fhandle, info, acred);
 	if (status == 0)
-		status = nfs4_server_capabilities(server, fhandle);
+		status = nfs4_server_capabilities(server, fhandle, acred);
 	if (status == 0)
-		status = nfs4_do_fsinfo(server, fhandle, info);
+		status = nfs4_do_fsinfo(server, fhandle, info, acred);
 	return nfs4_map_errors(status);
 }
 
@@ -1570,7 +1612,9 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  * Note that we'll actually follow the referral later when
  * we detect fsid mismatch in inode revalidation
  */
-static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle)
+static int nfs4_get_referral(struct inode *dir, const struct qstr *name,
+			     struct nfs_fattr *fattr, struct nfs_fh *fhandle,
+			     struct cred *acred)
 {
 	int status = -ENOMEM;
 	struct page *page = NULL;
@@ -1583,7 +1627,7 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct
 	if (locations == NULL)
 		goto out;
 
-	status = nfs4_proc_fs_locations(dir, name, locations, page);
+	status = nfs4_proc_fs_locations(dir, name, locations, page, acred);
 	if (status != 0)
 		goto out;
 	/* Make sure server returned a different fsid for the referral */
@@ -1606,7 +1650,8 @@ out:
 	return status;
 }
 
-static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+			      struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct nfs4_getattr_arg args = {
 		.fh = fhandle,
@@ -1623,16 +1668,18 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 	};
 	
 	nfs_fattr_init(fattr);
-	return rpc_call_sync(server->client, &msg, 0);
+	return rpc_call_sync(server->client, &msg, 0, acred);
 }
 
-static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+			     struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_proc_getattr(server, fhandle, fattr),
+				_nfs4_proc_getattr(server, fhandle, fattr,
+						   acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1657,9 +1704,8 @@ static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 static int
 nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
-		  struct iattr *sattr)
+		  struct iattr *sattr, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct rpc_cred *cred;
 	struct inode *inode = dentry->d_inode;
 	struct nfs_open_context *ctx;
@@ -1677,7 +1723,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 	if (ctx != NULL)
 		state = ctx->state;
 
-	status = nfs4_do_setattr(inode, fattr, sattr, state);
+	status = nfs4_do_setattr(inode, fattr, sattr, state, acred);
 	if (status == 0)
 		nfs_setattr_update_inode(inode, sattr);
 	if (ctx != NULL)
@@ -1688,7 +1734,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh,
 		const struct qstr *name, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct cred *acred)
 {
 	int		       status;
 	struct nfs4_lookup_arg args = {
@@ -1710,19 +1756,20 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
 	nfs_fattr_init(fattr);
 
 	dprintk("NFS call  lookupfh %s\n", name->name);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	dprintk("NFS reply lookupfh: %d\n", status);
 	return status;
 }
 
 static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
 			      struct qstr *name, struct nfs_fh *fhandle,
-			      struct nfs_fattr *fattr)
+			      struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
-		err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr);
+		err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr,
+					  acred);
 		/* FIXME: !!!! */
 		if (err == -NFS4ERR_MOVED) {
 			err = -EREMOTE;
@@ -1734,31 +1781,37 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
 }
 
 static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
-		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		struct cred *acred)
 {
 	int status;
 	
 	dprintk("NFS call  lookup %s\n", name->name);
-	status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr);
+	status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name,
+				     fhandle, fattr, acred);
 	if (status == -NFS4ERR_MOVED)
-		status = nfs4_get_referral(dir, name, fattr, fhandle);
+		status = nfs4_get_referral(dir, name, fattr, fhandle, acred);
 	dprintk("NFS reply lookup: %d\n", status);
 	return status;
 }
 
-static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
+			    struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+			    struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_lookup(dir, name, fhandle, fattr),
+				_nfs4_proc_lookup(dir, name, fhandle, fattr,
+						  acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
-static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
+static int _nfs4_proc_access(struct inode *inode,
+			     struct nfs_access_entry *entry, struct cred *acred)
 {
 	struct nfs4_accessargs args = {
 		.fh = NFS_FH(inode),
@@ -1789,7 +1842,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 		if (mode & MAY_EXEC)
 			args.access |= NFS4_ACCESS_EXECUTE;
 	}
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	if (!status) {
 		entry->mask = 0;
 		if (res.access & NFS4_ACCESS_READ)
@@ -1802,13 +1855,14 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 	return status;
 }
 
-static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
+static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry,
+			    struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(inode),
-				_nfs4_proc_access(inode, entry),
+				_nfs4_proc_access(inode, entry, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1839,7 +1893,7 @@ static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
  * minor, but I decided to leave them for a subsequent patch.
  */
 static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
-		unsigned int pgbase, unsigned int pglen)
+		unsigned int pgbase, unsigned int pglen, struct cred *acred)
 {
 	struct nfs4_readlink args = {
 		.fh       = NFS_FH(inode),
@@ -1853,17 +1907,17 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
 		.rpc_resp = NULL,
 	};
 
-	return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	return rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 }
 
 static int nfs4_proc_readlink(struct inode *inode, struct page *page,
-		unsigned int pgbase, unsigned int pglen)
+		unsigned int pgbase, unsigned int pglen, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(inode),
-				_nfs4_proc_readlink(inode, page, pgbase, pglen),
+				_nfs4_proc_readlink(inode, page, pgbase, pglen, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1886,9 +1940,8 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
 
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags, struct nameidata *nd)
+                 int flags, struct nameidata *nd, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct path path = {
 		.mnt = nd->mnt,
 		.dentry = dentry,
@@ -1902,7 +1955,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		status = PTR_ERR(cred);
 		goto out;
 	}
-	state = nfs4_do_open(dir, &path, flags, sattr, cred);
+	state = nfs4_do_open(dir, &path, flags, sattr, cred, acred);
 	put_rpccred(cred);
 	if (IS_ERR(state)) {
 		status = PTR_ERR(state);
@@ -1911,20 +1964,22 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 	d_instantiate(dentry, igrab(state->inode));
 	if (flags & O_EXCL) {
 		struct nfs_fattr fattr;
-		status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
+		status = nfs4_do_setattr(state->inode, &fattr, sattr, state,
+					 acred);
 		if (status == 0)
 			nfs_setattr_update_inode(state->inode, sattr);
 		nfs_post_op_update_inode(state->inode, &fattr);
 	}
 	if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
-		status = nfs4_intent_set_file(nd, &path, state);
+		status = nfs4_intent_set_file(nd, &path, state, acred);
 	else
-		nfs4_close_state(&path, state, flags);
+		nfs4_close_state(&path, state, flags, acred);
 out:
 	return status;
 }
 
-static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
+static int _nfs4_proc_remove(struct inode *dir, struct qstr *name,
+			     struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_removeargs args = {
@@ -1944,7 +1999,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
 	int			status;
 
 	nfs_fattr_init(&res.dir_attr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	if (status == 0) {
 		update_changeattr(dir, &res.cinfo);
 		nfs_post_op_update_inode(dir, &res.dir_attr);
@@ -1952,13 +2007,14 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
 	return status;
 }
 
-static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
+static int nfs4_proc_remove(struct inode *dir, struct qstr *name,
+			    struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_remove(dir, name),
+				_nfs4_proc_remove(dir, name, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1987,7 +2043,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 }
 
 static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
-		struct inode *new_dir, struct qstr *new_name)
+		struct inode *new_dir, struct qstr *new_name,
+		struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(old_dir);
 	struct nfs4_rename_arg arg = {
@@ -2012,7 +2069,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 	
 	nfs_fattr_init(res.old_fattr);
 	nfs_fattr_init(res.new_fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 
 	if (!status) {
 		update_changeattr(old_dir, &res.old_cinfo);
@@ -2024,20 +2081,22 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 }
 
 static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
-		struct inode *new_dir, struct qstr *new_name)
+		struct inode *new_dir, struct qstr *new_name,
+		struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(old_dir),
 				_nfs4_proc_rename(old_dir, old_name,
-					new_dir, new_name),
+					new_dir, new_name, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
-static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+static int _nfs4_proc_link(struct inode *inode, struct inode *dir,
+			   struct qstr *name, struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_link_arg arg = {
@@ -2061,7 +2120,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
 
 	nfs_fattr_init(res.fattr);
 	nfs_fattr_init(res.dir_attr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	if (!status) {
 		update_changeattr(dir, &res.cinfo);
 		nfs_post_op_update_inode(dir, res.dir_attr);
@@ -2071,20 +2130,22 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
 	return status;
 }
 
-static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+static int nfs4_proc_link(struct inode *inode, struct inode *dir,
+			  struct qstr *name, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(inode),
-				_nfs4_proc_link(inode, dir, name),
+				_nfs4_proc_link(inode, dir, name, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
 static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
-		struct page *page, unsigned int len, struct iattr *sattr)
+		struct page *page, unsigned int len, struct iattr *sattr,
+		struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_fh fhandle;
@@ -2118,31 +2179,32 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
 	nfs_fattr_init(&fattr);
 	nfs_fattr_init(&dir_fattr);
 	
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	if (!status) {
 		update_changeattr(dir, &res.dir_cinfo);
 		nfs_post_op_update_inode(dir, res.dir_fattr);
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 	}
 	return status;
 }
 
 static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
-		struct page *page, unsigned int len, struct iattr *sattr)
+		struct page *page, unsigned int len, struct iattr *sattr,
+		struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
 				_nfs4_proc_symlink(dir, dentry, page,
-							len, sattr),
+							len, sattr, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
 static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
-		struct iattr *sattr)
+		struct iattr *sattr, struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_fh fhandle;
@@ -2171,30 +2233,31 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 	nfs_fattr_init(&fattr);
 	nfs_fattr_init(&dir_fattr);
 	
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	if (!status) {
 		update_changeattr(dir, &res.dir_cinfo);
 		nfs_post_op_update_inode(dir, res.dir_fattr);
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 	}
 	return status;
 }
 
 static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
-		struct iattr *sattr)
+		struct iattr *sattr, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_mkdir(dir, dentry, sattr),
+				_nfs4_proc_mkdir(dir, dentry, sattr, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
 static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                  u64 cookie, struct page *page, unsigned int count, int plus)
+                  u64 cookie, struct page *page, unsigned int count, int plus,
+		  struct cred *acred)
 {
 	struct inode		*dir = dentry->d_inode;
 	struct nfs4_readdir_arg args = {
@@ -2219,7 +2282,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 			(unsigned long long)cookie);
 	nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
 	res.pgbase = args.pgbase;
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	if (status == 0)
 		memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
 	dprintk("%s: returns %d\n", __FUNCTION__, status);
@@ -2227,21 +2290,22 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 }
 
 static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                  u64 cookie, struct page *page, unsigned int count, int plus)
+                  u64 cookie, struct page *page, unsigned int count, int plus,
+		  struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
 				_nfs4_proc_readdir(dentry, cred, cookie,
-					page, count, plus),
+					page, count, plus, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
 static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
-		struct iattr *sattr, dev_t rdev)
+		struct iattr *sattr, dev_t rdev, struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_fh fh;
@@ -2287,30 +2351,31 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
 	else
 		arg.ftype = NF4SOCK;
 	
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	if (status == 0) {
 		update_changeattr(dir, &res.dir_cinfo);
 		nfs_post_op_update_inode(dir, res.dir_fattr);
-		status = nfs_instantiate(dentry, &fh, &fattr);
+		status = nfs_instantiate(dentry, &fh, &fattr, acred);
 	}
 	return status;
 }
 
 static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
-		struct iattr *sattr, dev_t rdev)
+		struct iattr *sattr, dev_t rdev, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_mknod(dir, dentry, sattr, rdev),
+				_nfs4_proc_mknod(dir, dentry, sattr, rdev,
+						 acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
 static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
-		 struct nfs_fsstat *fsstat)
+		 struct nfs_fsstat *fsstat, struct cred *acred)
 {
 	struct nfs4_statfs_arg args = {
 		.fh = fhandle,
@@ -2323,23 +2388,25 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 	};
 
 	nfs_fattr_init(fsstat->fattr);
-	return rpc_call_sync(server->client, &msg, 0);
+	return rpc_call_sync(server->client, &msg, 0, acred);
 }
 
-static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
+static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
+			    struct nfs_fsstat *fsstat, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_proc_statfs(server, fhandle, fsstat),
+				_nfs4_proc_statfs(server, fhandle, fsstat,
+						  acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
 static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fsinfo *fsinfo)
+		struct nfs_fsinfo *fsinfo, struct cred *acred)
 {
 	struct nfs4_fsinfo_arg args = {
 		.fh = fhandle,
@@ -2351,30 +2418,32 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_resp = fsinfo,
 	};
 
-	return rpc_call_sync(server->client, &msg, 0);
+	return rpc_call_sync(server->client, &msg, 0, acred);
 }
 
-static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
+static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
+			  struct nfs_fsinfo *fsinfo, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_do_fsinfo(server, fhandle, fsinfo),
+				_nfs4_do_fsinfo(server, fhandle, fsinfo, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
-static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
+static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
+			    struct nfs_fsinfo *fsinfo, struct cred *acred)
 {
 	nfs_fattr_init(fsinfo->fattr);
-	return nfs4_do_fsinfo(server, fhandle, fsinfo);
+	return nfs4_do_fsinfo(server, fhandle, fsinfo, acred);
 }
 
 static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_pathconf *pathconf)
+		struct nfs_pathconf *pathconf, struct cred *acred)
 {
 	struct nfs4_pathconf_arg args = {
 		.fh = fhandle,
@@ -2393,18 +2462,19 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
 	}
 
 	nfs_fattr_init(pathconf->fattr);
-	return rpc_call_sync(server->client, &msg, 0);
+	return rpc_call_sync(server->client, &msg, 0, acred);
 }
 
 static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_pathconf *pathconf)
+		struct nfs_pathconf *pathconf, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 
 	do {
 		err = nfs4_handle_exception(server,
-				_nfs4_proc_pathconf(server, fhandle, pathconf),
+				_nfs4_proc_pathconf(server, fhandle, pathconf,
+						    acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -2423,7 +2493,7 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
 	return 0;
 }
 
-static void nfs4_proc_read_setup(struct nfs_read_data *data)
+static void nfs4_proc_read_setup(struct nfs_read_data *data, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
@@ -2434,7 +2504,7 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data)
 
 	data->timestamp   = jiffies;
 
-	rpc_call_setup(&data->task, &msg, 0, current->cred);
+	rpc_call_setup(&data->task, &msg, 0, acred);
 }
 
 static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -2452,7 +2522,8 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
 	return 0;
 }
 
-static void nfs4_proc_write_setup(struct nfs_write_data *data, int how)
+static void nfs4_proc_write_setup(struct nfs_write_data *data, int how,
+				  struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
@@ -2478,7 +2549,7 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, int how)
 	data->timestamp   = jiffies;
 
 	/* Finalize the task. */
-	rpc_call_setup(&data->task, &msg, 0, current->cred);
+	rpc_call_setup(&data->task, &msg, 0, acred);
 }
 
 static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -2494,7 +2565,8 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
 	return 0;
 }
 
-static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
+static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how,
+				   struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
@@ -2507,7 +2579,7 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
 	data->args.bitmask = server->attr_bitmask;
 	data->res.server = server;
 
-	rpc_call_setup(&data->task, &msg, 0, current->cred);
+	rpc_call_setup(&data->task, &msg, 0, acred);
 }
 
 /*
@@ -2538,7 +2610,8 @@ static const struct rpc_call_ops nfs4_renew_ops = {
 	.rpc_call_done = nfs4_renew_done,
 };
 
-int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
+int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred,
+			  struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
@@ -2547,10 +2620,11 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
 	};
 
 	return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
-			&nfs4_renew_ops, (void *)jiffies);
+			&nfs4_renew_ops, (void *)jiffies, acred);
 }
 
-int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
+int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred,
+		    struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
@@ -2560,7 +2634,7 @@ int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
 	unsigned long now = jiffies;
 	int status;
 
-	status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+	status = rpc_call_sync(clp->cl_rpcclient, &msg, 0, acred);
 	if (status < 0)
 		return status;
 	spin_lock(&clp->cl_lock);
@@ -2663,7 +2737,8 @@ out:
 	nfs4_set_cached_acl(inode, acl);
 }
 
-static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
+static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
+				       size_t buflen, struct cred *acred)
 {
 	struct page *pages[NFS4ACL_MAXPAGES];
 	struct nfs_getaclargs args = {
@@ -2695,7 +2770,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
 		resp_buf = buf;
 		buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
 	}
-	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	if (ret)
 		goto out_free;
 	if (resp_len > args.acl_len)
@@ -2716,12 +2791,13 @@ out_free:
 	return ret;
 }
 
-static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
+static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf,
+				     size_t buflen, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	ssize_t ret;
 	do {
-		ret = __nfs4_get_acl_uncached(inode, buf, buflen);
+		ret = __nfs4_get_acl_uncached(inode, buf, buflen, acred);
 		if (ret >= 0)
 			break;
 		ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception);
@@ -2729,23 +2805,25 @@ static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bufl
 	return ret;
 }
 
-static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
+static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen,
+				 struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	int ret;
 
 	if (!nfs4_server_supports_acls(server))
 		return -EOPNOTSUPP;
-	ret = nfs_revalidate_inode(server, inode);
+	ret = nfs_revalidate_inode(server, inode, acred);
 	if (ret < 0)
 		return ret;
 	ret = nfs4_read_cached_acl(inode, buf, buflen);
 	if (ret != -ENOENT)
 		return ret;
-	return nfs4_get_acl_uncached(inode, buf, buflen);
+	return nfs4_get_acl_uncached(inode, buf, buflen, acred);
 }
 
-static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
+static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
+			       size_t buflen, struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct page *pages[NFS4ACL_MAXPAGES];
@@ -2765,18 +2843,19 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
 		return -EOPNOTSUPP;
 	nfs_inode_return_delegation(inode);
 	buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
-	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	nfs_zap_caches(inode);
 	return ret;
 }
 
-static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
+static int nfs4_proc_set_acl(struct inode *inode, const void *buf,
+			     size_t buflen, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(inode),
-				__nfs4_proc_set_acl(inode, buf, buflen),
+				__nfs4_proc_set_acl(inode, buf, buflen, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -2897,7 +2976,9 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
 	return nfs4_map_errors(ret);
 }
 
-int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred)
+int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
+			  unsigned short port, struct rpc_cred *cred,
+			  struct cred *acred)
 {
 	nfs4_verifier sc_verifier;
 	struct nfs4_setclientid setclientid = {
@@ -2930,7 +3011,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
 				sizeof(setclientid.sc_uaddr), "%s.%d.%d",
 				clp->cl_ipaddr, port >> 8, port & 255);
 
-		status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+		status = rpc_call_sync(clp->cl_rpcclient, &msg, 0, acred);
 		if (status != -NFS4ERR_CLID_INUSE)
 			break;
 		if (signalled())
@@ -2944,7 +3025,9 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
 	return status;
 }
 
-static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred)
+static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
+					  struct rpc_cred *cred,
+					  struct cred *acred)
 {
 	struct nfs_fsinfo fsinfo;
 	struct rpc_message msg = {
@@ -2957,7 +3040,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre
 	int status;
 
 	now = jiffies;
-	status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+	status = rpc_call_sync(clp->cl_rpcclient, &msg, 0, acred);
 	if (status == 0) {
 		spin_lock(&clp->cl_lock);
 		clp->cl_lease_time = fsinfo.lease_time * HZ;
@@ -2968,12 +3051,13 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre
 	return status;
 }
 
-int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred)
+int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred,
+				  struct cred *acred)
 {
 	long timeout;
 	int err;
 	do {
-		err = _nfs4_proc_setclientid_confirm(clp, cred);
+		err = _nfs4_proc_setclientid_confirm(clp, cred, acred);
 		switch (err) {
 			case 0:
 				return err;
@@ -3018,7 +3102,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
 		renew_lease(data->res.server, data->timestamp);
 }
 
-static void nfs4_delegreturn_release(void *calldata)
+static void nfs4_delegreturn_release(struct cred *acred, void *calldata)
 {
 	struct nfs4_delegreturndata *data = calldata;
 
@@ -3032,7 +3116,9 @@ static const struct rpc_call_ops nfs4_delegreturn_ops = {
 	.rpc_release = nfs4_delegreturn_release,
 };
 
-static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
+static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred,
+				  const nfs4_stateid *stateid,
+				  struct cred *acred)
 {
 	struct nfs4_delegreturndata *data;
 	struct nfs_server *server = NFS_SERVER(inode);
@@ -3053,7 +3139,8 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
 	data->timestamp = jiffies;
 	data->rpc_status = 0;
 
-	task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data);
+	task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC,
+			    &nfs4_delegreturn_ops, data, acred);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
 	status = nfs4_wait_for_completion_rpc_task(task);
@@ -3066,13 +3153,14 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
 	return status;
 }
 
-int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
+int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred,
+			  const nfs4_stateid *stateid, struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_exception exception = { };
 	int err;
 	do {
-		err = _nfs4_proc_delegreturn(inode, cred, stateid);
+		err = _nfs4_proc_delegreturn(inode, cred, stateid, acred);
 		switch (err) {
 			case -NFS4ERR_STALE_STATEID:
 			case -NFS4ERR_EXPIRED:
@@ -3100,7 +3188,8 @@ nfs4_set_lock_task_retry(unsigned long timeout)
 	return timeout;
 }
 
-static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd,
+			    struct file_lock *request, struct cred *acred)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
@@ -3128,7 +3217,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
 		goto out;
 	lsp = request->fl_u.nfs4_fl.owner;
 	arg.lock_owner.id = lsp->ls_id.id;
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	switch (status) {
 		case 0:
 			request->fl_type = F_UNLCK;
@@ -3142,14 +3231,15 @@ out:
 	return status;
 }
 
-static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+static int nfs4_proc_getlk(struct nfs4_state *state, int cmd,
+			   struct file_lock *request, struct cred *acred)
 {
 	struct nfs4_exception exception = { };
 	int err;
 
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(state->inode),
-				_nfs4_proc_getlk(state, cmd, request),
+				_nfs4_proc_getlk(state, cmd, request, acred),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -3205,7 +3295,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
 	return p;
 }
 
-static void nfs4_locku_release_calldata(void *data)
+static void nfs4_locku_release_calldata(struct cred *acred, void *data)
 {
 	struct nfs4_unlockdata *calldata = data;
 	nfs_free_seqid(calldata->arg.seqid);
@@ -3282,7 +3372,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
 		return ERR_PTR(-ENOMEM);
 	}
 
-	return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data);
+	return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC,
+			    &nfs4_locku_ops, data, ctx->acred);
 }
 
 static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -3416,7 +3507,7 @@ out:
 	dprintk("%s: done, ret = %d!\n", __FUNCTION__, data->rpc_status);
 }
 
-static void nfs4_lock_release(void *calldata)
+static void nfs4_lock_release(struct cred *acred, void *calldata)
 {
 	struct nfs4_lockdata *data = calldata;
 
@@ -3460,7 +3551,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
 	if (reclaim != 0)
 		data->arg.reclaim = 1;
 	task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC,
-			&nfs4_lock_ops, data);
+			&nfs4_lock_ops, data, fl->fl_file->f_cred);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
 	ret = nfs4_wait_for_completion_rpc_task(task);
@@ -3584,7 +3675,7 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
 		return -EINVAL;
 
 	if (IS_GETLK(cmd))
-		return nfs4_proc_getlk(state, F_GETLK, request);
+		return nfs4_proc_getlk(state, F_GETLK, request, filp->f_cred);
 
 	if (!(IS_SETLK(cmd) || IS_SETLKW(cmd)))
 		return -EINVAL;
@@ -3628,6 +3719,7 @@ out:
 int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
 		size_t buflen, int flags)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 
 	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
@@ -3637,7 +3729,7 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
 	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
 		return -EPERM;
 
-	return nfs4_proc_set_acl(inode, buf, buflen);
+	return nfs4_proc_set_acl(inode, buf, buflen, acred);
 }
 
 /* The getxattr man page suggests returning -ENODATA for unknown attributes,
@@ -3647,12 +3739,13 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
 ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
 		size_t buflen)
 {
+	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 
 	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
 		return -EOPNOTSUPP;
 
-	return nfs4_proc_get_acl(inode, buf, buflen);
+	return nfs4_proc_get_acl(inode, buf, buflen, acred);
 }
 
 ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
@@ -3669,7 +3762,8 @@ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
 }
 
 int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
-		struct nfs4_fs_locations *fs_locations, struct page *page)
+		struct nfs4_fs_locations *fs_locations, struct page *page,
+		struct cred *acred)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 	u32 bitmask[2] = {
@@ -3693,7 +3787,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
 	nfs_fattr_init(&fs_locations->fattr);
 	fs_locations->server = server;
 	fs_locations->nlocations = 0;
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	dprintk("%s: returned status = %d\n", __FUNCTION__, status);
 	return status;
 }
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 3ea352d..9d648c8 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -86,7 +86,7 @@ nfs4_renew_state(struct work_struct *work)
 		}
 		spin_unlock(&clp->cl_lock);
 		/* Queue an asynchronous RENEW. */
-		nfs4_proc_async_renew(clp, cred);
+		nfs4_proc_async_renew(clp, cred, &init_cred);
 		put_rpccred(cred);
 		timeout = (2 * lease) / 3;
 		spin_lock(&clp->cl_lock);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 3e4adf8..8ffdc68 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -60,12 +60,13 @@ const nfs4_stateid zero_stateid;
 
 static LIST_HEAD(nfs4_clientid_list);
 
-static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
+static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred,
+			    struct cred *acred)
 {
 	int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK,
-			nfs_callback_tcpport, cred);
+			nfs_callback_tcpport, cred, acred);
 	if (status == 0)
-		status = nfs4_proc_setclientid_confirm(clp, cred);
+		status = nfs4_proc_setclientid_confirm(clp, cred, acred);
 	if (status == 0)
 		nfs4_schedule_state_renewal(clp);
 	return status;
@@ -425,7 +426,8 @@ void nfs4_put_open_state(struct nfs4_state *state)
 /*
  * Close the current file.
  */
-void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
+void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode,
+		      struct cred *acred)
 {
 	struct nfs4_state_owner *owner = state->owner;
 	int call_close = 0;
@@ -466,7 +468,7 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
 		nfs4_put_open_state(state);
 		nfs4_put_state_owner(owner);
 	} else
-		nfs4_do_close(path, state);
+		nfs4_do_close(path, state, acred);
 }
 
 /*
@@ -905,7 +907,7 @@ restart_loop:
 	cred = nfs4_get_renew_cred(clp);
 	if (cred != NULL) {
 		/* Yes there are: try to renew the old lease */
-		status = nfs4_proc_renew(clp, cred);
+		status = nfs4_proc_renew(clp, cred, &init_cred);
 		switch (status) {
 			case 0:
 			case -NFS4ERR_CB_PATH_DOWN:
@@ -924,7 +926,7 @@ restart_loop:
 	nfs4_state_mark_reclaim(clp);
 	status = -ENOENT;
 	if (cred != NULL) {
-		status = nfs4_init_client(clp, cred);
+		status = nfs4_init_client(clp, cred, &init_cred);
 		put_rpccred(cred);
 	}
 	if (status)
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index d6baeb4..aeb7e38 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -52,7 +52,7 @@
  */
 static int
 nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
-		  struct nfs_fsinfo *info)
+		  struct nfs_fsinfo *info, struct cred *acred)
 {
 	struct nfs_fattr *fattr = info->fattr;
 	struct nfs2_fsstat fsinfo;
@@ -65,14 +65,16 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	dprintk("%s: call getattr\n", __FUNCTION__);
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+	status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0,
+			       acred);
 	dprintk("%s: reply getattr: %d\n", __FUNCTION__, status);
 	if (status)
 		return status;
 	dprintk("%s: call statfs\n", __FUNCTION__);
 	msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS];
 	msg.rpc_resp = &fsinfo;
-	status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+	status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0,
+			       acred);
 	dprintk("%s: reply statfs: %d\n", __FUNCTION__, status);
 	if (status)
 		return status;
@@ -93,7 +95,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 static int
 nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_GETATTR],
@@ -104,14 +106,14 @@ nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	dprintk("NFS call  getattr\n");
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	dprintk("NFS reply getattr: %d\n", status);
 	return status;
 }
 
 static int
 nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
-		 struct iattr *sattr)
+		 struct iattr *sattr, struct cred *acred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct nfs_sattrargs	arg = { 
@@ -130,7 +132,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 	dprintk("NFS call  setattr\n");
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	if (status == 0)
 		nfs_setattr_update_inode(inode, sattr);
 	dprintk("NFS reply setattr: %d\n", status);
@@ -139,7 +141,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 static int
 nfs_proc_lookup(struct inode *dir, struct qstr *name,
-		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		struct cred *acred)
 {
 	struct nfs_diropargs	arg = {
 		.fh		= NFS_FH(dir),
@@ -159,13 +162,13 @@ nfs_proc_lookup(struct inode *dir, struct qstr *name,
 
 	dprintk("NFS call  lookup %s\n", name->name);
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	dprintk("NFS reply lookup: %d\n", status);
 	return status;
 }
 
 static int nfs_proc_readlink(struct inode *inode, struct page *page,
-		unsigned int pgbase, unsigned int pglen)
+		unsigned int pgbase, unsigned int pglen, struct cred *acred)
 {
 	struct nfs_readlinkargs	args = {
 		.fh		= NFS_FH(inode),
@@ -180,14 +183,14 @@ static int nfs_proc_readlink(struct inode *inode, struct page *page,
 	int			status;
 
 	dprintk("NFS call  readlink\n");
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	dprintk("NFS reply readlink: %d\n", status);
 	return status;
 }
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		int flags, struct nameidata *nd)
+		int flags, struct nameidata *nd, struct cred *acred)
 {
 	struct nfs_fh		fhandle;
 	struct nfs_fattr	fattr;
@@ -210,9 +213,9 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 
 	nfs_fattr_init(&fattr);
 	dprintk("NFS call  create %s\n", dentry->d_name.name);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 	dprintk("NFS reply create: %d\n", status);
 	return status;
 }
@@ -222,7 +225,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
  */
 static int
 nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-	       dev_t rdev)
+	       dev_t rdev, struct cred *acred)
 {
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
@@ -255,22 +258,22 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 	}
 
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_mark_for_revalidate(dir);
 
 	if (status == -EINVAL && S_ISFIFO(mode)) {
 		sattr->ia_mode = mode;
 		nfs_fattr_init(&fattr);
-		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	}
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 	dprintk("NFS reply mknod: %d\n", status);
 	return status;
 }
   
 static int
-nfs_proc_remove(struct inode *dir, struct qstr *name)
+nfs_proc_remove(struct inode *dir, struct qstr *name, struct cred *acred)
 {
 	struct nfs_removeargs arg = {
 		.fh = NFS_FH(dir),
@@ -284,7 +287,7 @@ nfs_proc_remove(struct inode *dir, struct qstr *name)
 	int			status;
 
 	dprintk("NFS call  remove %s\n", name->name);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_mark_for_revalidate(dir);
 
 	dprintk("NFS reply remove: %d\n", status);
@@ -305,7 +308,8 @@ static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 
 static int
 nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
-		struct inode *new_dir, struct qstr *new_name)
+		struct inode *new_dir, struct qstr *new_name,
+		struct cred *acred)
 {
 	struct nfs_renameargs	arg = {
 		.fromfh		= NFS_FH(old_dir),
@@ -322,7 +326,7 @@ nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
 	int			status;
 
 	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
-	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0, acred);
 	nfs_mark_for_revalidate(old_dir);
 	nfs_mark_for_revalidate(new_dir);
 	dprintk("NFS reply rename: %d\n", status);
@@ -330,7 +334,8 @@ nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
 }
 
 static int
-nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name,
+	      struct cred *acred)
 {
 	struct nfs_linkargs	arg = {
 		.fromfh		= NFS_FH(inode),
@@ -345,7 +350,7 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 	int			status;
 
 	dprintk("NFS call  link %s\n", name->name);
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	nfs_mark_for_revalidate(inode);
 	nfs_mark_for_revalidate(dir);
 	dprintk("NFS reply link: %d\n", status);
@@ -354,7 +359,7 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 
 static int
 nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
-		 unsigned int len, struct iattr *sattr)
+		 unsigned int len, struct iattr *sattr, struct cred *acred)
 {
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
@@ -377,7 +382,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
 
 	dprintk("NFS call  symlink %s\n", dentry->d_name.name);
 
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_mark_for_revalidate(dir);
 
 	/*
@@ -388,7 +393,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
 	if (status == 0) {
 		nfs_fattr_init(&fattr);
 		fhandle.size = 0;
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 	}
 
 	dprintk("NFS reply symlink: %d\n", status);
@@ -396,7 +401,8 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
 }
 
 static int
-nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
+nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+	       struct cred *acred)
 {
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
@@ -419,16 +425,16 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 
 	dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
 	nfs_fattr_init(&fattr);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_mark_for_revalidate(dir);
 	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+		status = nfs_instantiate(dentry, &fhandle, &fattr, acred);
 	dprintk("NFS reply mkdir: %d\n", status);
 	return status;
 }
 
 static int
-nfs_proc_rmdir(struct inode *dir, struct qstr *name)
+nfs_proc_rmdir(struct inode *dir, struct qstr *name, struct cred *acred)
 {
 	struct nfs_diropargs	arg = {
 		.fh		= NFS_FH(dir),
@@ -442,7 +448,7 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name)
 	int			status;
 
 	dprintk("NFS call  rmdir %s\n", name->name);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 	nfs_mark_for_revalidate(dir);
 	dprintk("NFS reply rmdir: %d\n", status);
 	return status;
@@ -457,7 +463,8 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name)
  */
 static int
 nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-		 u64 cookie, struct page *page, unsigned int count, int plus)
+		 u64 cookie, struct page *page, unsigned int count, int plus,
+		 struct cred *acred)
 {
 	struct inode		*dir = dentry->d_inode;
 	struct nfs_readdirargs	arg = {
@@ -474,7 +481,7 @@ nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 	int			status;
 
 	dprintk("NFS call  readdir %d\n", (unsigned int)cookie);
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0, acred);
 
 	dprintk("NFS reply readdir: %d\n", status);
 	return status;
@@ -482,7 +489,7 @@ nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 
 static int
 nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
-			struct nfs_fsstat *stat)
+			struct nfs_fsstat *stat, struct cred *acred)
 {
 	struct nfs2_fsstat fsinfo;
 	struct rpc_message msg = {
@@ -494,7 +501,7 @@ nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	dprintk("NFS call  statfs\n");
 	nfs_fattr_init(stat->fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	dprintk("NFS reply statfs: %d\n", status);
 	if (status)
 		goto out;
@@ -510,7 +517,7 @@ out:
 
 static int
 nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
-			struct nfs_fsinfo *info)
+			struct nfs_fsinfo *info, struct cred *acred)
 {
 	struct nfs2_fsstat fsinfo;
 	struct rpc_message msg = {
@@ -522,7 +529,7 @@ nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	dprintk("NFS call  fsinfo\n");
 	nfs_fattr_init(info->fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, 0, acred);
 	dprintk("NFS reply fsinfo: %d\n", status);
 	if (status)
 		goto out;
@@ -541,7 +548,7 @@ out:
 
 static int
 nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
-		  struct nfs_pathconf *info)
+		  struct nfs_pathconf *info, struct cred *acred)
 {
 	info->max_link = 0;
 	info->max_namelen = NFS2_MAXNAMLEN;
@@ -561,7 +568,7 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
 	return 0;
 }
 
-static void nfs_proc_read_setup(struct nfs_read_data *data)
+static void nfs_proc_read_setup(struct nfs_read_data *data, struct cred *acred)
 {
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_READ],
@@ -570,7 +577,7 @@ static void nfs_proc_read_setup(struct nfs_read_data *data)
 		.rpc_cred	= data->cred,
 	};
 
-	rpc_call_setup(&data->task, &msg, 0, current->cred);
+	rpc_call_setup(&data->task, &msg, 0, acred);
 }
 
 static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -580,7 +587,8 @@ static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
 	return 0;
 }
 
-static void nfs_proc_write_setup(struct nfs_write_data *data, int how)
+static void nfs_proc_write_setup(struct nfs_write_data *data, int how,
+				 struct cred *acred)
 {
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_WRITE],
@@ -593,11 +601,11 @@ static void nfs_proc_write_setup(struct nfs_write_data *data, int how)
 	data->args.stable = NFS_FILE_SYNC;
 
 	/* Finalize the task. */
-	rpc_call_setup(&data->task, &msg, 0, current->cred);
+	rpc_call_setup(&data->task, &msg, 0, acred);
 }
 
 static void
-nfs_proc_commit_setup(struct nfs_write_data *data, int how)
+nfs_proc_commit_setup(struct nfs_write_data *data, int how, struct cred *acred)
 {
 	BUG();
 }
@@ -605,7 +613,8 @@ nfs_proc_commit_setup(struct nfs_write_data *data, int how)
 static int
 nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
-	return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl);
+	return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl,
+			    filp->f_cred);
 }
 
 
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 19e0563..8cde60c 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -71,7 +71,7 @@ static void nfs_readdata_free(struct nfs_read_data *rdata)
 	call_rcu_bh(&rdata->task.u.tk_rcu, nfs_readdata_rcu_free);
 }
 
-void nfs_readdata_release(void *data)
+void nfs_readdata_release(struct cred *acred, void *data)
 {
         nfs_readdata_free(data);
 }
@@ -181,8 +181,9 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
 
 	/* Set up the initial task struct. */
 	flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
-	rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data);
-	NFS_PROTO(inode)->read_setup(data);
+	rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data,
+		      req->wb_context->acred);
+	NFS_PROTO(inode)->read_setup(data, req->wb_context->acred);
 
 	data->task.tk_cookie = (unsigned long)inode;
 
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index b878528..0988df4 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -355,6 +355,7 @@ void __exit unregister_nfs_fs(void)
  */
 static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct cred *acred = current->cred;
 	struct nfs_server *server = NFS_SB(dentry->d_sb);
 	unsigned char blockbits;
 	unsigned long blockres;
@@ -367,7 +368,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 
 	lock_kernel();
 
-	error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
+	error = server->nfs_client->rpc_ops->statfs(server, fh, &res, acred);
 	if (error < 0)
 		goto out_err;
 	buf->f_type = NFS_SUPER_MAGIC;
@@ -1008,7 +1009,7 @@ out_unknown:
  * corresponding to the provided path.
  */
 static int nfs_try_mount(struct nfs_parsed_mount_data *args,
-			 struct nfs_fh *root_fh)
+			 struct nfs_fh *root_fh, struct cred *acred)
 {
 	struct sockaddr_in sin;
 	int status;
@@ -1048,7 +1049,8 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
 			   args->nfs_server.export_path,
 			   args->mount_server.version,
 			   args->mount_server.protocol,
-			   root_fh);
+			   root_fh,
+			   acred);
 	if (status < 0)
 		goto out_err;
 
@@ -1081,7 +1083,8 @@ out_err:
  */
 static int nfs_validate_mount_data(struct nfs_mount_data **options,
 				   struct nfs_fh *mntfh,
-				   const char *dev_name)
+				   const char *dev_name,
+				   struct cred *acred)
 {
 	struct nfs_mount_data *data = *options;
 
@@ -1164,7 +1167,7 @@ static int nfs_validate_mount_data(struct nfs_mount_data **options,
 			return -ENAMETOOLONG;
 		args.nfs_server.export_path = c;
 
-		status = nfs_try_mount(&args, mntfh);
+		status = nfs_try_mount(&args, mntfh, acred);
 		if (status)
 			return status;
 
@@ -1376,6 +1379,7 @@ static int nfs_compare_super(struct super_block *sb, void *data)
 static int nfs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
 {
+	struct cred *acred = current->cred;
 	struct nfs_server *server = NULL;
 	struct super_block *s;
 	struct nfs_fh mntfh;
@@ -1388,12 +1392,12 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 	int error;
 
 	/* Validate the mount data */
-	error = nfs_validate_mount_data(&data, &mntfh, dev_name);
+	error = nfs_validate_mount_data(&data, &mntfh, dev_name, acred);
 	if (error < 0)
 		goto out;
 
 	/* Get a volume representation */
-	server = nfs_create_server(data, &mntfh);
+	server = nfs_create_server(data, &mntfh, acred);
 	if (IS_ERR(server)) {
 		error = PTR_ERR(server);
 		goto out;
@@ -1420,7 +1424,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 		nfs_fill_super(s, data);
 	}
 
-	mntroot = nfs_get_root(s, &mntfh);
+	mntroot = nfs_get_root(s, &mntfh, acred);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
@@ -1464,6 +1468,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
 			   const char *dev_name, void *raw_data,
 			   struct vfsmount *mnt)
 {
+	struct cred *acred = current->cred;
 	struct nfs_clone_mount *data = raw_data;
 	struct super_block *s;
 	struct nfs_server *server;
@@ -1477,7 +1482,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
 	dprintk("--> nfs_xdev_get_sb()\n");
 
 	/* create a new volume representation */
-	server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+	server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, acred);
 	if (IS_ERR(server)) {
 		error = PTR_ERR(server);
 		goto out_err_noserver;
@@ -1504,7 +1509,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
 		nfs_clone_super(s, data->sb);
 	}
 
-	mntroot = nfs_get_root(s, data->fh);
+	mntroot = nfs_get_root(s, data->fh, acred);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
@@ -1729,6 +1734,7 @@ out_no_client_address:
 static int nfs4_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
 {
+	struct cred *acred = current->cred;
 	struct nfs4_mount_data *data = raw_data;
 	struct super_block *s;
 	struct nfs_server *server;
@@ -1751,7 +1757,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
 
 	/* Get a volume representation */
 	server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
-				    authflavour, &mntfh);
+				    authflavour, &mntfh, acred);
 	if (IS_ERR(server)) {
 		error = PTR_ERR(server);
 		goto out;
@@ -1778,7 +1784,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
 		nfs4_fill_super(s);
 	}
 
-	mntroot = nfs4_get_root(s, &mntfh);
+	mntroot = nfs4_get_root(s, &mntfh, acred);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
@@ -1823,6 +1829,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
 			    const char *dev_name, void *raw_data,
 			    struct vfsmount *mnt)
 {
+	struct cred *acred = current->cred;
 	struct nfs_clone_mount *data = raw_data;
 	struct super_block *s;
 	struct nfs_server *server;
@@ -1836,7 +1843,8 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
 	dprintk("--> nfs4_xdev_get_sb()\n");
 
 	/* create a new volume representation */
-	server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+	server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr,
+				  acred);
 	if (IS_ERR(server)) {
 		error = PTR_ERR(server);
 		goto out_err_noserver;
@@ -1863,7 +1871,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
 		nfs4_clone_super(s, data->sb);
 	}
 
-	mntroot = nfs4_get_root(s, data->fh);
+	mntroot = nfs4_get_root(s, data->fh, acred);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
@@ -1896,6 +1904,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
 				const char *dev_name, void *raw_data,
 				struct vfsmount *mnt)
 {
+	struct cred *acred = current->cred;
 	struct nfs_clone_mount *data = raw_data;
 	struct super_block *s;
 	struct nfs_server *server;
@@ -1910,7 +1919,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
 	dprintk("--> nfs4_referral_get_sb()\n");
 
 	/* create a new volume representation */
-	server = nfs4_create_referral_server(data, &mntfh);
+	server = nfs4_create_referral_server(data, &mntfh, acred);
 	if (IS_ERR(server)) {
 		error = PTR_ERR(server);
 		goto out_err_noserver;
@@ -1937,7 +1946,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
 		nfs4_fill_super(s);
 	}
 
-	mntroot = nfs4_get_root(s, &mntfh);
+	mntroot = nfs4_get_root(s, &mntfh, acred);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 83e865a..cd1df31 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -24,15 +24,23 @@
 #include <linux/string.h>
 #include <linux/namei.h>
 
+struct nfs_symlink_filler_data {
+	struct inode	*inode;
+	struct cred	*acred;
+};
+
 /* Symlink caching in the page cache is even more simplistic
  * and straight-forward than readdir caching.
  */
 
-static int nfs_symlink_filler(struct inode *inode, struct page *page)
+static int nfs_symlink_filler(void *_data, struct page *page)
 {
+	struct nfs_symlink_filler_data *data = _data;
+	struct inode *inode = data->inode;
+	struct cred *acred = data->acred;
 	int error;
 
-	error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
+	error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE, acred);
 	if (error < 0)
 		goto error;
 	SetPageUptodate(page);
@@ -48,14 +56,20 @@ error:
 static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
+	struct cred *acred = current->cred;
 	struct page *page;
 	void *err;
 
-	err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping));
+	struct nfs_symlink_filler_data data = {
+		.inode = inode,
+		.acred = acred,
+	};
+
+	err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping,
+						    acred));
 	if (err)
 		goto read_failed;
-	page = read_cache_page(&inode->i_data, 0,
-				(filler_t *)nfs_symlink_filler, inode);
+	page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler, &data);
 	if (IS_ERR(page)) {
 		err = page;
 		goto read_failed;
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index d4e7d09..0d1700b 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -95,7 +95,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
  * We need to call nfs_put_unlinkdata as a 'tk_release' task since the
  * rpc_task would be freed too.
  */
-static void nfs_async_unlink_release(void *calldata)
+static void nfs_async_unlink_release(struct cred *acred, void *calldata)
 {
 	struct nfs_unlinkdata	*data = calldata;
 	nfs_free_unlinkdata(data);
@@ -107,7 +107,8 @@ static const struct rpc_call_ops nfs_unlink_ops = {
 	.rpc_release = nfs_async_unlink_release,
 };
 
-static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
+static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data,
+			   struct cred *acred)
 {
 	struct rpc_task *task;
 	struct dentry *parent;
@@ -128,7 +129,8 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
 	data->args.fh = NFS_FH(dir);
 	nfs_fattr_init(&data->res.dir_attr);
 
-	task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data);
+	task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops,
+			    data, acred);
 	if (!IS_ERR(task))
 		rpc_put_task(task);
 	return 1;
@@ -142,9 +144,8 @@ out_free:
  * @dentry: dentry to unlink
  */
 int
-nfs_async_unlink(struct inode *dir, struct dentry *dentry)
+nfs_async_unlink(struct inode *dir, struct dentry *dentry, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct nfs_unlinkdata *data;
 	int status = -ENOMEM;
 
@@ -179,13 +180,15 @@ out:
  * nfs_complete_unlink - Initialize completion of the sillydelete
  * @dentry: dentry to delete
  * @inode: inode
+ * @acred: the credentials to use
  *
  * Since we're most likely to be called by dentry_iput(), we
  * only use the dentry to find the sillydelete. We then copy the name
  * into the qstr.
  */
 void
-nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
+nfs_complete_unlink(struct dentry *dentry, struct inode *inode,
+		    struct cred *acred)
 {
 	struct nfs_unlinkdata	*data = NULL;
 
@@ -196,6 +199,7 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
 	}
 	spin_unlock(&dentry->d_lock);
 
-	if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
+	if (data != NULL &&
+	    (NFS_STALE(inode) || !nfs_call_unlink(dentry, data, acred)))
 		nfs_free_unlinkdata(data);
 }
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0d7a77c..42f5b5d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -105,7 +105,7 @@ static void nfs_writedata_free(struct nfs_write_data *wdata)
 	call_rcu_bh(&wdata->task.u.tk_rcu, nfs_writedata_rcu_free);
 }
 
-void nfs_writedata_release(void *wdata)
+void nfs_writedata_release(struct cred *acred, void *wdata)
 {
 	nfs_writedata_free(wdata);
 }
@@ -806,8 +806,9 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
 
 	/* Set up the initial task struct.  */
 	flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
-	rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data);
-	NFS_PROTO(inode)->write_setup(data, how);
+	rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data,
+		      req->wb_context->acred);
+	NFS_PROTO(inode)->write_setup(data, how, req->wb_context->acred);
 
 	data->task.tk_priority = flush_task_priority(how);
 	data->task.tk_cookie = (unsigned long)inode;
@@ -837,6 +838,7 @@ static void nfs_execute_write(struct nfs_write_data *data)
  */
 static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how)
 {
+	struct cred *acred = &writeback_cred;
 	struct nfs_page *req = nfs_list_entry(head->next);
 	struct page *page = req->wb_page;
 	struct nfs_write_data *data;
@@ -884,7 +886,7 @@ out_bad:
 	while (!list_empty(&list)) {
 		data = list_entry(list.next, struct nfs_write_data, pages);
 		list_del(&data->pages);
-		nfs_writedata_release(data);
+		nfs_writedata_release(acred, data);
 	}
 	nfs_redirty_request(req);
 	nfs_end_page_writeback(req->wb_page);
@@ -1141,7 +1143,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 
 
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-void nfs_commit_release(void *wdata)
+void nfs_commit_release(struct cred *acred, void *wdata)
 {
 	nfs_commit_free(wdata);
 }
@@ -1178,8 +1180,9 @@ static void nfs_commit_rpcsetup(struct list_head *head,
 
 	/* Set up the initial task struct.  */
 	flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
-	rpc_init_task(&data->task, NFS_CLIENT(inode), flags, &nfs_commit_ops, data);
-	NFS_PROTO(inode)->commit_setup(data, how);
+	rpc_init_task(&data->task, NFS_CLIENT(inode), flags, &nfs_commit_ops,
+		      data, first->wb_context->acred);
+	NFS_PROTO(inode)->commit_setup(data, how, first->wb_context->acred);
 
 	data->task.tk_priority = flush_task_priority(how);
 	data->task.tk_cookie = (unsigned long)inode;
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index 6f1637c..aacb15c 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -35,8 +35,9 @@ extern struct nlmsvc_binding *	nlmsvc_ops;
 /*
  * Functions exported by the lockd module
  */
-extern int	nlmclnt_proc(struct inode *, int, struct file_lock *);
-extern int	lockd_up(int proto);
+extern int	nlmclnt_proc(struct inode *, int, struct file_lock *,
+			     struct cred *);
+extern int	lockd_up(int proto, struct cred *acred);
 extern void	lockd_down(void);
 
 unsigned long get_nfs_grace_period(void);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index e2d1ce3..fc5b04e 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -96,6 +96,7 @@ struct nlm_rqst {
 	struct nlm_args		a_args;		/* arguments */
 	struct nlm_res		a_res;		/* result */
 	struct nlm_block *	a_block;
+	struct cred *		a_acred;	/* credentials to use */
 	unsigned int		a_retries;	/* Retry count */
 	u8			a_owner[NLMCLNT_OHSIZE];
 };
@@ -158,7 +159,7 @@ extern int			nsm_use_hostnames;
 /*
  * Lockd client functions
  */
-struct nlm_rqst * nlm_alloc_call(struct nlm_host *host);
+struct nlm_rqst * nlm_alloc_call(struct nlm_host *host, struct cred *acred);
 void		  nlm_release_call(struct nlm_rqst *);
 int		  nlm_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *);
 int		  nlm_async_reply(struct nlm_rqst *, u32, const struct rpc_call_ops *);
@@ -175,7 +176,7 @@ void		  nlmclnt_next_cookie(struct nlm_cookie *);
  */
 struct nlm_host * nlmclnt_lookup_host(const struct sockaddr_in *, int, int, const char *, int);
 struct nlm_host * nlmsvc_lookup_host(struct svc_rqst *, const char *, int);
-struct rpc_clnt * nlm_bind_host(struct nlm_host *);
+struct rpc_clnt * nlm_bind_host(struct nlm_host *, struct cred *);
 void		  nlm_rebind_host(struct nlm_host *);
 struct nlm_host * nlm_get_host(struct nlm_host *);
 void		  nlm_release_host(struct nlm_host *);
diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h
index 22a6458..a7dc1c6 100644
--- a/include/linux/lockd/sm_inter.h
+++ b/include/linux/lockd/sm_inter.h
@@ -40,8 +40,8 @@ struct nsm_res {
 	u32		state;
 };
 
-int		nsm_monitor(struct nlm_host *);
-int		nsm_unmonitor(struct nlm_host *);
+int		nsm_monitor(struct nlm_host *, struct cred *);
+int		nsm_unmonitor(struct nlm_host *, struct cred *);
 extern int	nsm_local_state;
 
 #endif /* LINUX_LOCKD_SM_INTER_H */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 7250eea..f7ab86c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -73,6 +73,7 @@ struct nfs4_state;
 struct nfs_open_context {
 	atomic_t count;
 	struct path path;
+	struct cred *acred;
 	struct rpc_cred *cred;
 	struct nfs4_state *state;
 	fl_owner_t lockowner;
@@ -295,10 +296,16 @@ extern void nfs_access_zap_cache(struct inode *inode);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
 extern int nfs_attribute_timeout(struct inode *inode);
-extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
-extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
-extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
-extern int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping);
+extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode,
+				struct cred *acred);
+extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *,
+				  struct cred *);
+extern int nfs_revalidate_mapping(struct inode *inode,
+				  struct address_space *mapping,
+				  struct cred *acred);
+extern int nfs_revalidate_mapping_nolock(struct inode *inode,
+					 struct address_space *mapping,
+					 struct cred *acred);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern void nfs_begin_attr_update(struct inode *);
@@ -377,7 +384,8 @@ extern const struct inode_operations nfs3_dir_inode_operations;
 extern const struct file_operations nfs_dir_operations;
 extern struct dentry_operations nfs_dentry_operations;
 
-extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
+extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh,
+			   struct nfs_fattr *fattr, struct cred *acred);
 
 /*
  * linux/fs/nfs/symlink.c
@@ -407,8 +415,9 @@ extern void nfs_release_automount_timer(void);
 /*
  * linux/fs/nfs/unlink.c
  */
-extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
-extern void nfs_complete_unlink(struct dentry *dentry, struct inode *);
+extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry,
+			     struct cred *);
+extern void nfs_complete_unlink(struct dentry *, struct inode *, struct cred *);
 
 /*
  * linux/fs/nfs/write.c
@@ -419,7 +428,7 @@ extern int  nfs_writepages(struct address_space *, struct writeback_control *);
 extern int  nfs_flush_incompatible(struct file *file, struct page *page);
 extern int  nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
 extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
-extern void nfs_writedata_release(void *);
+extern void nfs_writedata_release(struct cred *, void *);
 extern int nfs_set_page_dirty(struct page *);
 
 /*
@@ -436,7 +445,7 @@ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
 extern int  nfs_commit_inode(struct inode *, int);
 extern struct nfs_write_data *nfs_commit_alloc(void);
 extern void nfs_commit_free(struct nfs_write_data *wdata);
-extern void nfs_commit_release(void *wdata);
+extern void nfs_commit_release(struct cred *acred, void *wdata);
 #else
 static inline int
 nfs_commit_inode(struct inode *inode, int how)
@@ -463,7 +472,7 @@ extern int  nfs_readpage(struct file *, struct page *);
 extern int  nfs_readpages(struct file *, struct address_space *,
 		struct list_head *, unsigned);
 extern int  nfs_readpage_result(struct rpc_task *, struct nfs_read_data *);
-extern void nfs_readdata_release(void *data);
+extern void nfs_readdata_release(struct cred *acred, void *data);
 
 /*
  * Allocate nfs_read_data structures
@@ -474,11 +483,12 @@ extern struct nfs_read_data *nfs_readdata_alloc(unsigned int npages);
  * linux/fs/nfs3proc.c
  */
 #ifdef CONFIG_NFS_V3_ACL
-extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type);
+extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type,
+					  struct cred *acred);
 extern int nfs3_proc_setacl(struct inode *inode, int type,
-			    struct posix_acl *acl);
+			    struct posix_acl *acl, struct cred *acred);
 extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-		mode_t mode);
+		mode_t mode, struct cred *acred);
 extern void nfs3_forget_cached_acls(struct inode *inode);
 #else
 static inline int nfs3_proc_set_default_acl(struct inode *dir,
@@ -497,7 +507,7 @@ static inline void nfs3_forget_cached_acls(struct inode *inode)
  * linux/fs/mount_clnt.c
  */
 extern int  nfs_mount(struct sockaddr *, size_t, char *, char *,
-		      int, int, struct nfs_fh *);
+		      int, int, struct nfs_fh *, struct cred *);
 
 /*
  * inline functions
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index cf74a4d..e82a5db 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -775,48 +775,56 @@ struct nfs_rpc_ops {
 	const struct inode_operations *file_inode_ops;
 
 	int	(*getroot) (struct nfs_server *, struct nfs_fh *,
-			    struct nfs_fsinfo *);
+			    struct nfs_fsinfo *, struct cred *);
 	int	(*lookupfh)(struct nfs_server *, struct nfs_fh *,
 			    struct qstr *, struct nfs_fh *,
-			    struct nfs_fattr *);
+			    struct nfs_fattr *, struct cred *);
 	int	(*getattr) (struct nfs_server *, struct nfs_fh *,
-			    struct nfs_fattr *);
+			    struct nfs_fattr *, struct cred *);
 	int	(*setattr) (struct dentry *, struct nfs_fattr *,
-			    struct iattr *);
+			    struct iattr *, struct cred *);
 	int	(*lookup)  (struct inode *, struct qstr *,
-			    struct nfs_fh *, struct nfs_fattr *);
-	int	(*access)  (struct inode *, struct nfs_access_entry *);
+			    struct nfs_fh *, struct nfs_fattr *, struct cred *);
+	int	(*access)  (struct inode *, struct nfs_access_entry *,
+			    struct cred *);
 	int	(*readlink)(struct inode *, struct page *, unsigned int,
-			    unsigned int);
+			    unsigned int, struct cred *);
 	int	(*create)  (struct inode *, struct dentry *,
-			    struct iattr *, int, struct nameidata *);
-	int	(*remove)  (struct inode *, struct qstr *);
+			    struct iattr *, int, struct nameidata *,
+			    struct cred *);
+	int	(*remove)  (struct inode *, struct qstr *, struct cred *);
 	void	(*unlink_setup)  (struct rpc_message *, struct inode *dir);
 	int	(*unlink_done) (struct rpc_task *, struct inode *);
 	int	(*rename)  (struct inode *, struct qstr *,
-			    struct inode *, struct qstr *);
-	int	(*link)    (struct inode *, struct inode *, struct qstr *);
+			    struct inode *, struct qstr *, struct cred *);
+	int	(*link)    (struct inode *, struct inode *, struct qstr *,
+			    struct cred *);
 	int	(*symlink) (struct inode *, struct dentry *, struct page *,
-			    unsigned int, struct iattr *);
-	int	(*mkdir)   (struct inode *, struct dentry *, struct iattr *);
-	int	(*rmdir)   (struct inode *, struct qstr *);
+			    unsigned int, struct iattr *, struct cred *);
+	int	(*mkdir)   (struct inode *, struct dentry *, struct iattr *,
+			    struct cred *);
+	int	(*rmdir)   (struct inode *, struct qstr *, struct cred *);
 	int	(*readdir) (struct dentry *, struct rpc_cred *,
-			    u64, struct page *, unsigned int, int);
+			    u64, struct page *, unsigned int, int,
+			    struct cred *);
 	int	(*mknod)   (struct inode *, struct dentry *, struct iattr *,
-			    dev_t);
+			    dev_t, struct cred *);
 	int	(*statfs)  (struct nfs_server *, struct nfs_fh *,
-			    struct nfs_fsstat *);
+			    struct nfs_fsstat *, struct cred *);
 	int	(*fsinfo)  (struct nfs_server *, struct nfs_fh *,
-			    struct nfs_fsinfo *);
+			    struct nfs_fsinfo *, struct cred *);
 	int	(*pathconf) (struct nfs_server *, struct nfs_fh *,
-			     struct nfs_pathconf *);
-	int	(*set_capabilities)(struct nfs_server *, struct nfs_fh *);
+			     struct nfs_pathconf *, struct cred *);
+	int	(*set_capabilities)(struct nfs_server *, struct nfs_fh *,
+				    struct cred *);
 	__be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus);
-	void	(*read_setup)   (struct nfs_read_data *);
+	void	(*read_setup)   (struct nfs_read_data *, struct cred *);
 	int	(*read_done)  (struct rpc_task *, struct nfs_read_data *);
-	void	(*write_setup)  (struct nfs_write_data *, int how);
+	void	(*write_setup)  (struct nfs_write_data *, int how,
+				 struct cred *);
 	int	(*write_done)  (struct rpc_task *, struct nfs_write_data *);
-	void	(*commit_setup) (struct nfs_write_data *, int how);
+	void	(*commit_setup) (struct nfs_write_data *, int how,
+				 struct cred *);
 	int	(*commit_done) (struct rpc_task *, struct nfs_write_data *);
 	int	(*file_open)   (struct inode *, struct file *);
 	int	(*file_release) (struct inode *, struct file *);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index ae52668..3b68540 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -115,9 +115,9 @@ struct rpc_create_args {
 #define RPC_CLNT_CREATE_NOPING		(1UL << 4)
 #define RPC_CLNT_CREATE_DISCRTRY	(1UL << 5)
 
-struct rpc_clnt *rpc_create(struct rpc_create_args *args);
+struct rpc_clnt *rpc_create(struct rpc_create_args *args, struct cred *acred);
 struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
-				struct rpc_program *, int);
+				struct rpc_program *, int, struct cred *);
 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
 void		rpc_shutdown_client(struct rpc_clnt *);
 void		rpc_release_client(struct rpc_clnt *);
@@ -131,11 +131,11 @@ void		rpc_call_setup(struct rpc_task *, struct rpc_message *, int,
 
 int		rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
 			       int flags, const struct rpc_call_ops *tk_ops,
-			       void *calldata);
+			       void *calldata, struct cred *acred);
 int		rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
-			      int flags);
+			      int flags, struct cred *acred);
 struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
-			       int flags);
+			       int flags, struct cred *acred);
 void		rpc_restart_call(struct rpc_task *);
 void		rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void		rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index fed97e0..a7764bb 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -115,7 +115,7 @@ typedef void			(*rpc_action)(struct rpc_task *);
 struct rpc_call_ops {
 	void (*rpc_call_prepare)(struct rpc_task *, void *);
 	void (*rpc_call_done)(struct rpc_task *, void *);
-	void (*rpc_release)(void *);
+	void (*rpc_release)(struct cred *, void *);
 };
 
 
@@ -238,15 +238,18 @@ struct rpc_wait_queue {
  * Function prototypes
  */
 struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags,
-				const struct rpc_call_ops *ops, void *data);
+				const struct rpc_call_ops *ops, void *data,
+				struct cred *acred);
 struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
-				const struct rpc_call_ops *ops, void *data);
+				const struct rpc_call_ops *ops, void *data,
+			        struct cred *acred);
 void		rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt,
 				int flags, const struct rpc_call_ops *ops,
-				void *data);
+				void *data, struct cred *cred);
 void		rpc_put_task(struct rpc_task *);
 void		rpc_exit_task(struct rpc_task *);
-void		rpc_release_calldata(const struct rpc_call_ops *, void *);
+void		rpc_release_calldata(const struct rpc_call_ops *, void *,
+				     struct cred *);
 void		rpc_killall_tasks(struct rpc_clnt *);
 void		rpc_execute(struct rpc_task *);
 void		rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index bad2698..26c1913 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -720,7 +720,7 @@ gss_destroying_context(struct rpc_cred *cred)
 	 * by the RPC call or by the put_rpccred() below */
 	get_rpccred(cred);
 
-	task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
+	task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC, &init_cred);
 	if (!IS_ERR(task))
 		rpc_put_task(task);
 
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index a02a776..952e2eb 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -72,7 +72,7 @@ static void	call_connect_status(struct rpc_task *task);
 static __be32 *	call_header(struct rpc_task *task);
 static __be32 *	call_verify(struct rpc_task *task);
 
-static int	rpc_ping(struct rpc_clnt *clnt, int flags);
+static int	rpc_ping(struct rpc_clnt *clnt, int flags, struct cred *acred);
 
 static void rpc_register_client(struct rpc_clnt *clnt)
 {
@@ -223,6 +223,7 @@ out_no_rpciod:
 /*
  * rpc_create - create an RPC client and transport with one call
  * @args: rpc_clnt create argument structure
+ * @acred: the credentials to use
  *
  * Creates and initializes an RPC transport and an RPC client.
  *
@@ -230,7 +231,7 @@ out_no_rpciod:
  * it supports this program and version.  RPC_CLNT_CREATE_NOPING disables
  * this behavior so asynchronous tasks can also use rpc_create.
  */
-struct rpc_clnt *rpc_create(struct rpc_create_args *args)
+struct rpc_clnt *rpc_create(struct rpc_create_args *args, struct cred *acred)
 {
 	struct rpc_xprt *xprt;
 	struct rpc_clnt *clnt;
@@ -278,7 +279,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
 		return clnt;
 
 	if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
-		int err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR);
+		int err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR, acred);
 		if (err != 0) {
 			rpc_shutdown_client(clnt);
 			return ERR_PTR(err);
@@ -432,6 +433,7 @@ rpc_release_client(struct rpc_clnt *clnt)
  * @old - old rpc_client
  * @program - rpc program to set
  * @vers - rpc program version
+ * @acred - the credentials to use
  *
  * Clones the rpc client and sets up a new RPC program. This is mainly
  * of use for enabling different RPC programs to share the same transport.
@@ -439,7 +441,8 @@ rpc_release_client(struct rpc_clnt *clnt)
  */
 struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
 				      struct rpc_program *program,
-				      int vers)
+				      int vers,
+				      struct cred *acred)
 {
 	struct rpc_clnt *clnt;
 	struct rpc_version *version;
@@ -456,7 +459,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
 	clnt->cl_prog     = program->number;
 	clnt->cl_vers     = version->number;
 	clnt->cl_stats    = program->stats;
-	err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR);
+	err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR, acred);
 	if (err != 0) {
 		rpc_shutdown_client(clnt);
 		clnt = ERR_PTR(err);
@@ -520,21 +523,22 @@ struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
 		struct rpc_message *msg,
 		int flags,
 		const struct rpc_call_ops *ops,
-		void *data)
+		void *data,
+		struct cred *acred)
 {
 	struct rpc_task *task, *ret;
 	sigset_t oldset;
 
-	task = rpc_new_task(clnt, flags, ops, data);
+	task = rpc_new_task(clnt, flags, ops, data, acred);
 	if (task == NULL) {
-		rpc_release_calldata(ops, data);
+		rpc_release_calldata(ops, data, acred);
 		return ERR_PTR(-ENOMEM);
 	}
 
 	/* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
 	rpc_task_sigmask(task, &oldset);
 	if (msg != NULL) {
-		rpc_call_setup(task, msg, 0, current->cred);
+		rpc_call_setup(task, msg, 0, acred);
 		if (task->tk_status != 0) {
 			ret = ERR_PTR(task->tk_status);
 			rpc_put_task(task);
@@ -554,15 +558,17 @@ out:
  * @clnt: pointer to RPC client
  * @msg: RPC call parameters
  * @flags: RPC call flags
+ * @acred: the credentials to use
  */
-int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
+		  struct cred *acred)
 {
 	struct rpc_task	*task;
 	int status;
 
 	BUG_ON(flags & RPC_TASK_ASYNC);
 
-	task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL);
+	task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL, acred);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
 	status = task->tk_status;
@@ -577,14 +583,17 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
  * @flags: RPC call flags
  * @ops: RPC call ops
  * @data: user call data
+ * @acred: the credentials to use
  */
 int
 rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
-	       const struct rpc_call_ops *tk_ops, void *data)
+	       const struct rpc_call_ops *tk_ops, void *data,
+	       struct cred *acred)
 {
 	struct rpc_task	*task;
 
-	task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data);
+	task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data,
+			       acred);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
 	rpc_put_task(task);
@@ -597,12 +606,13 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
  * @flags: RPC flags
  * @ops: RPC call ops
  * @data: user call data
+ * @acred: the credentials to use
  */
 struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
 					const struct rpc_call_ops *tk_ops,
-					void *data)
+					void *data, struct cred *acred)
 {
-	return rpc_do_run_task(clnt, NULL, flags, tk_ops, data);
+	return rpc_do_run_task(clnt, NULL, flags, tk_ops, data, acred);
 }
 EXPORT_SYMBOL(rpc_run_task);
 
@@ -1485,25 +1495,27 @@ static struct rpc_procinfo rpcproc_null = {
 	.p_decode = rpcproc_decode_null,
 };
 
-static int rpc_ping(struct rpc_clnt *clnt, int flags)
+static int rpc_ping(struct rpc_clnt *clnt, int flags, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc = &rpcproc_null,
 	};
 	int err;
 	msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0);
-	err = rpc_call_sync(clnt, &msg, flags);
+	err = rpc_call_sync(clnt, &msg, flags, acred);
 	put_rpccred(msg.rpc_cred);
 	return err;
 }
 
-struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
+			       int flags, struct cred *acred)
 {
 	struct rpc_message msg = {
 		.rpc_proc = &rpcproc_null,
 		.rpc_cred = cred,
 	};
-	return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL);
+	return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL,
+			       acred);
 }
 EXPORT_SYMBOL(rpc_call_null);
 
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 82a863c..0a2404e 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -155,7 +155,7 @@ static void rpcb_getport_prepare(struct rpc_task *task, void *calldata)
 	rpc_call_setup(task, &msg, 0, task->tk_acred);
 }
 
-static void rpcb_map_release(void *data)
+static void rpcb_map_release(struct cred *acred, void *data)
 {
 	struct rpcbind_args *map = data;
 
@@ -193,7 +193,7 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
 	((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
 	if (!privileged)
 		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
-	return rpc_create(&args);
+	return rpc_create(&args, &init_cred);
 }
 
 /**
@@ -238,7 +238,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
 	if (IS_ERR(rpcb_clnt))
 		return PTR_ERR(rpcb_clnt);
 
-	error = rpc_call_sync(rpcb_clnt, &msg, 0);
+	error = rpc_call_sync(rpcb_clnt, &msg, 0, &init_cred);
 
 	rpc_shutdown_client(rpcb_clnt);
 	if (error < 0)
@@ -287,7 +287,7 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
 	if (IS_ERR(rpcb_clnt))
 		return PTR_ERR(rpcb_clnt);
 
-	status = rpc_call_sync(rpcb_clnt, &msg, 0);
+	status = rpc_call_sync(rpcb_clnt, &msg, 0, &init_cred);
 	rpc_shutdown_client(rpcb_clnt);
 
 	if (status >= 0) {
@@ -374,7 +374,8 @@ void rpcb_getport_async(struct rpc_task *task)
 	map->r_owner = RPCB_OWNER_STRING;	/* ignored for GETADDR */
 
 	rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
-	rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
+	rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot,
+				bind_version, 0);
 	if (IS_ERR(rpcb_clnt)) {
 		status = PTR_ERR(rpcb_clnt);
 		dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
@@ -382,7 +383,8 @@ void rpcb_getport_async(struct rpc_task *task)
 		goto bailout;
 	}
 
-	child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
+	child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map,
+			     &init_cred);
 	rpc_release_client(rpcb_clnt);
 	if (IS_ERR(child)) {
 		status = -EIO;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index d9d4219..510ac24 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -616,11 +616,12 @@ void rpc_exit_task(struct rpc_task *task)
 }
 EXPORT_SYMBOL(rpc_exit_task);
 
-void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata)
+void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata,
+			  struct cred *acred)
 {
 	if (ops->rpc_release != NULL) {
 		lock_kernel();
-		ops->rpc_release(calldata);
+		ops->rpc_release(acred, calldata);
 		unlock_kernel();
 	}
 }
@@ -806,10 +807,10 @@ void rpc_free(void *buffer)
 /*
  * Creation and deletion of RPC task structures
  */
-void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
+void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags,
+		   const struct rpc_call_ops *tk_ops, void *calldata,
+		   struct cred *acred)
 {
-	struct cred *acred = current->cred;
-
 	memset(task, 0, sizeof(*task));
 	init_timer(&task->tk_timer);
 	task->tk_timer.data     = (unsigned long) task;
@@ -867,7 +868,9 @@ static void rpc_free_task(struct rcu_head *rcu)
 /*
  * Create a new task for the specified client.
  */
-struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
+struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags,
+			      const struct rpc_call_ops *tk_ops, void *calldata,
+			      struct cred *acred)
 {
 	struct rpc_task	*task;
 
@@ -875,7 +878,7 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc
 	if (!task)
 		goto out;
 
-	rpc_init_task(task, clnt, flags, tk_ops, calldata);
+	rpc_init_task(task, clnt, flags, tk_ops, calldata, acred);
 
 	dprintk("RPC:       allocated task %p\n", task);
 	task->tk_flags |= RPC_TASK_DYNAMIC;
@@ -887,6 +890,7 @@ out:
 void rpc_put_task(struct rpc_task *task)
 {
 	const struct rpc_call_ops *tk_ops = task->tk_ops;
+	struct cred *acred = task->tk_acred;
 	void *calldata = task->tk_calldata;
 
 	if (!atomic_dec_and_test(&task->tk_count))
@@ -900,10 +904,10 @@ void rpc_put_task(struct rpc_task *task)
 		rpc_release_client(task->tk_client);
 		task->tk_client = NULL;
 	}
-	put_cred(task->tk_acred);
 	if (task->tk_flags & RPC_TASK_DYNAMIC)
 		call_rcu_bh(&task->u.tk_rcu, rpc_free_task);
-	rpc_release_calldata(tk_ops, calldata);
+	rpc_release_calldata(tk_ops, calldata, acred);
+	put_cred(acred);
 }
 EXPORT_SYMBOL(rpc_put_task);
 
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 55ea6df..b84573c 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -435,7 +435,7 @@ svc_create(struct svc_program *prog, unsigned int bufsize,
 
 struct svc_serv *
 svc_create_pooled(struct svc_program *prog, unsigned int bufsize,
-		void (*shutdown)(struct svc_serv *serv),
+		  void (*shutdown)(struct svc_serv *serv),
 		  svc_thread_fn func, int sig, struct module *mod)
 {
 	struct svc_serv *serv;
@@ -757,7 +757,8 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port)
 			if (progp->pg_vers[i]->vs_hidden)
 				continue;
 
-			error = rpcb_register(progp->pg_prog, i, proto, port, &dummy);
+			error = rpcb_register(progp->pg_prog, i, proto, port,
+					      &dummy);
 			if (error < 0)
 				break;
 			if (port && !dummy) {


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

* [PATCH 21/52] CRED: Pass credentials through the truncate() inode operation
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (19 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 20/52] CRED: Pass credentials into rpc_init_task() David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 22/52] CRED: Pass credentials to nfs_setattr_update_inode() David Howells
                   ` (32 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the truncate() inode operation.

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

 fs/attr.c                |    3 ++-
 fs/buffer.c              |    3 ++-
 fs/ext3/inode.c          |    6 +++---
 fs/ext3/super.c          |    3 ++-
 fs/fat/file.c            |    2 +-
 fs/fat/inode.c           |    4 +++-
 fs/nfs/inode.c           |    4 +++-
 fs/splice.c              |    2 +-
 include/linux/ext3_fs.h  |    2 +-
 include/linux/fs.h       |    2 +-
 include/linux/mm.h       |    3 ++-
 include/linux/msdos_fs.h |    2 +-
 mm/filemap.c             |    3 ++-
 mm/memory.c              |    5 +++--
 mm/shmem.c               |    4 ++--
 15 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/fs/attr.c b/fs/attr.c
index f0adb92..06a3145 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -68,11 +68,12 @@ EXPORT_SYMBOL(inode_change_ok);
 
 int inode_setattr(struct inode * inode, struct iattr * attr)
 {
+	struct cred *cred = current->cred;
 	unsigned int ia_valid = attr->ia_valid;
 
 	if (ia_valid & ATTR_SIZE &&
 	    attr->ia_size != i_size_read(inode)) {
-		int error = vmtruncate(inode, attr->ia_size);
+		int error = vmtruncate(inode, attr->ia_size, cred);
 		if (error)
 			return error;
 	}
diff --git a/fs/buffer.c b/fs/buffer.c
index 0c8444a..e7f59c3 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2013,6 +2013,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
 static int __generic_cont_expand(struct inode *inode, loff_t size,
 				 pgoff_t index, unsigned int offset)
 {
+	struct cred *cred = current->cred;
 	struct address_space *mapping = inode->i_mapping;
 	struct page *page;
 	unsigned long limit;
@@ -2039,7 +2040,7 @@ static int __generic_cont_expand(struct inode *inode, loff_t size,
 		 */
 		unlock_page(page);
 		page_cache_release(page);
-		vmtruncate(inode, inode->i_size);
+		vmtruncate(inode, inode->i_size, cred);
 		goto out;
 	}
 
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 4313d20..31e5b38 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -181,6 +181,7 @@ static int ext3_journal_test_restart(handle_t *handle, struct inode *inode)
  */
 void ext3_delete_inode (struct inode * inode)
 {
+	struct cred *cred = &writeback_cred;
 	handle_t *handle;
 
 	truncate_inode_pages(&inode->i_data, 0);
@@ -203,7 +204,7 @@ void ext3_delete_inode (struct inode * inode)
 		handle->h_sync = 1;
 	inode->i_size = 0;
 	if (inode->i_blocks)
-		ext3_truncate(inode);
+		ext3_truncate(inode, cred);
 	/*
 	 * Kill off the orphan record which ext3_truncate created.
 	 * AKPM: I think this can be inside the above `if'.
@@ -2227,9 +2228,8 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
  * that's fine - as long as they are linked from the inode, the post-crash
  * ext3_truncate() run will find them and release them.
  */
-void ext3_truncate(struct inode *inode)
+void ext3_truncate(struct inode *inode, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	__le32 *i_data = ei->i_data;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 14a558b..4bb76d3 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1259,6 +1259,7 @@ static int ext3_check_descriptors (struct super_block * sb)
 static void ext3_orphan_cleanup (struct super_block * sb,
 				 struct ext3_super_block * es)
 {
+	struct cred *cred = current->cred;
 	unsigned int s_flags = sb->s_flags;
 	int nr_orphans = 0, nr_truncates = 0;
 #ifdef CONFIG_QUOTA
@@ -1321,7 +1322,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
 				__FUNCTION__, inode->i_ino, inode->i_size);
 			jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
 				  inode->i_ino, inode->i_size);
-			ext3_truncate(inode);
+			ext3_truncate(inode, cred);
 			nr_truncates++;
 		} else {
 			printk(KERN_DEBUG
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 69a83b5..a871db8 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -282,7 +282,7 @@ static int fat_free(struct inode *inode, int skip)
 	return fat_free_clusters(inode, free_start);
 }
 
-void fat_truncate(struct inode *inode)
+void fat_truncate(struct inode *inode, struct cred *cred)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
 	const unsigned int cluster_size = sbi->cluster_size;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 955ccaf..045647d 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -430,11 +430,13 @@ EXPORT_SYMBOL_GPL(fat_build_inode);
 
 static void fat_delete_inode(struct inode *inode)
 {
+	struct cred *cred = &writeback_cred;
+
 	truncate_inode_pages(&inode->i_data, 0);
 
 	if (!is_bad_inode(inode)) {
 		inode->i_size = 0;
-		fat_truncate(inode);
+		fat_truncate(inode, cred);
 	}
 	clear_inode(inode);
 }
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 300560f..8b21608 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -368,6 +368,8 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
  */
 void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
 {
+	struct cred *acred = current->cred;
+
 	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
 		if ((attr->ia_valid & ATTR_MODE) != 0) {
 			int mode = attr->ia_mode & S_IALLUGO;
@@ -385,7 +387,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
 	if ((attr->ia_valid & ATTR_SIZE) != 0) {
 		nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
 		inode->i_size = attr->ia_size;
-		vmtruncate(inode, attr->ia_size);
+		vmtruncate(inode, attr->ia_size, acred);
 	}
 }
 
diff --git a/fs/splice.c b/fs/splice.c
index e95a362..52d4c96 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -612,7 +612,7 @@ find_page:
 		 * outside i_size.  Trim these off again.
 		 */
 		if (sd->pos + this_len > isize)
-			vmtruncate(mapping->host, isize);
+			vmtruncate(mapping->host, isize, file->f_cred);
 
 		goto out_ret;
 	}
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 23db760..a2b686d 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -827,7 +827,7 @@ extern void ext3_discard_reservation (struct inode *);
 extern void ext3_dirty_inode(struct inode *);
 extern int ext3_change_inode_journal_flag(struct inode *, int);
 extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *);
-extern void ext3_truncate (struct inode *);
+extern void ext3_truncate (struct inode *, struct cred *);
 extern void ext3_set_inode_flags(struct inode *);
 extern void ext3_get_inode_flags(struct ext3_inode_info *);
 extern void ext3_set_aops(struct inode *inode);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6d9bfc4..747fc5b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1148,7 +1148,7 @@ struct inode_operations {
 	int (*readlink) (struct dentry *, char __user *,int);
 	void * (*follow_link) (struct dentry *, struct nameidata *);
 	void (*put_link) (struct dentry *, struct nameidata *, void *);
-	void (*truncate) (struct inode *);
+	void (*truncate) (struct inode *, struct cred *);
 	int (*permission) (struct inode *, int, struct nameidata *);
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1692dd6..aae6d3c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -20,6 +20,7 @@ struct anon_vma;
 struct file_ra_state;
 struct user_struct;
 struct writeback_control;
+struct cred;
 
 #ifndef CONFIG_DISCONTIGMEM          /* Don't use mapnrs, do it properly */
 extern unsigned long max_mapnr;
@@ -790,7 +791,7 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
 	unmap_mapping_range(mapping, holebegin, holelen, 0);
 }
 
-extern int vmtruncate(struct inode * inode, loff_t offset);
+extern int vmtruncate(struct inode * inode, loff_t offset, struct cred *cred);
 extern int vmtruncate_range(struct inode * inode, loff_t offset, loff_t end);
 
 #ifdef CONFIG_MMU
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index f950921..ddd669c 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -402,7 +402,7 @@ extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
 extern const struct file_operations fat_file_operations;
 extern const struct inode_operations fat_file_inode_operations;
 extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
-extern void fat_truncate(struct inode *inode);
+extern void fat_truncate(struct inode *inode, struct cred *cred);
 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		       struct kstat *stat);
 
diff --git a/mm/filemap.c b/mm/filemap.c
index 15c8413..ab89eac 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1841,6 +1841,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
 		size_t count, ssize_t written)
 {
 	struct file *file = iocb->ki_filp;
+	struct cred *cred = file->f_cred;
 	struct address_space * mapping = file->f_mapping;
 	const struct address_space_operations *a_ops = mapping->a_ops;
 	struct inode 	*inode = mapping->host;
@@ -1924,7 +1925,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
 			 * outside i_size.  Trim these off again.
 			 */
 			if (pos + bytes > isize)
-				vmtruncate(inode, isize);
+				vmtruncate(inode, isize, cred);
 			break;
 		}
 		if (likely(nr_segs == 1))
diff --git a/mm/memory.c b/mm/memory.c
index f82b359..85dca9b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1999,12 +1999,13 @@ EXPORT_SYMBOL(unmap_mapping_range);
  * vmtruncate - unmap mappings "freed" by truncate() syscall
  * @inode: inode of the file used
  * @offset: file offset to start truncating
+ * @cred: the credentials to use
  *
  * NOTE! We have to be ready to update the memory sharing
  * between the file and the memory map for a potential last
  * incomplete page.  Ugly, but necessary.
  */
-int vmtruncate(struct inode * inode, loff_t offset)
+int vmtruncate(struct inode * inode, loff_t offset, struct cred *cred)
 {
 	struct address_space *mapping = inode->i_mapping;
 	unsigned long limit;
@@ -2042,7 +2043,7 @@ do_expand:
 
 out_truncate:
 	if (inode->i_op && inode->i_op->truncate)
-		inode->i_op->truncate(inode);
+		inode->i_op->truncate(inode, cred);
 	return 0;
 out_sig:
 	send_sig(SIGXFSZ, current, 0);
diff --git a/mm/shmem.c b/mm/shmem.c
index 49a4b40..accaa18 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -708,7 +708,7 @@ done2:
 	}
 }
 
-static void shmem_truncate(struct inode *inode)
+static void shmem_truncate(struct inode *inode, struct cred *cred)
 {
 	shmem_truncate_range(inode, inode->i_size, (loff_t)-1);
 }
@@ -770,7 +770,7 @@ static void shmem_delete_inode(struct inode *inode)
 		truncate_inode_pages(inode->i_mapping, 0);
 		shmem_unacct_size(info->flags, inode->i_size);
 		inode->i_size = 0;
-		shmem_truncate(inode);
+		shmem_truncate(inode, &writeback_cred);
 		if (!list_empty(&info->swaplist)) {
 			spin_lock(&shmem_swaplist_lock);
 			list_del_init(&info->swaplist);


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

* [PATCH 22/52] CRED: Pass credentials to nfs_setattr_update_inode()
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (20 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 21/52] CRED: Pass credentials through the truncate() inode operation David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 23/52] CRED: Pass credentials to the setattr() inode operation David Howells
                   ` (31 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials to nfs_setattr_update_inode().

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

 fs/nfs/inode.c         |    6 +++---
 fs/nfs/nfs3proc.c      |    2 +-
 fs/nfs/nfs4proc.c      |    4 ++--
 fs/nfs/proc.c          |    2 +-
 include/linux/nfs_fs.h |    3 ++-
 5 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 8b21608..f76a93c 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -362,14 +362,14 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
  * nfs_setattr_update_inode - Update inode metadata after a setattr call.
  * @inode: pointer to struct inode
  * @attr: pointer to struct iattr
+ * @acred: the credentials to use
  *
  * Note: we do this in the *proc.c in order to ensure that
  *       it works for things like exclusive creates too.
  */
-void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
+void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
+			      struct cred *acred)
 {
-	struct cred *acred = current->cred;
-
 	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
 		if ((attr->ia_valid & ATTR_MODE) != 0) {
 			int mode = attr->ia_mode & S_IALLUGO;
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 4d66cfd..627188e 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -138,7 +138,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	if (status == 0)
-		nfs_setattr_update_inode(inode, sattr);
+		nfs_setattr_update_inode(inode, sattr, acred);
 	dprintk("NFS reply setattr: %d\n", status);
 	return status;
 }
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 83c9b66..c10f3de 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1725,7 +1725,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 
 	status = nfs4_do_setattr(inode, fattr, sattr, state, acred);
 	if (status == 0)
-		nfs_setattr_update_inode(inode, sattr);
+		nfs_setattr_update_inode(inode, sattr, acred);
 	if (ctx != NULL)
 		put_nfs_open_context(ctx);
 	put_rpccred(cred);
@@ -1967,7 +1967,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		status = nfs4_do_setattr(state->inode, &fattr, sattr, state,
 					 acred);
 		if (status == 0)
-			nfs_setattr_update_inode(state->inode, sattr);
+			nfs_setattr_update_inode(state->inode, sattr, acred);
 		nfs_post_op_update_inode(state->inode, &fattr);
 	}
 	if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index aeb7e38..993d289 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -134,7 +134,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0, acred);
 	if (status == 0)
-		nfs_setattr_update_inode(inode, sattr);
+		nfs_setattr_update_inode(inode, sattr, acred);
 	dprintk("NFS reply setattr: %d\n", status);
 	return status;
 }
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index f7ab86c..fe3136e 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -307,7 +307,8 @@ extern int nfs_revalidate_mapping_nolock(struct inode *inode,
 					 struct address_space *mapping,
 					 struct cred *acred);
 extern int nfs_setattr(struct dentry *, struct iattr *);
-extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
+extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
+				     struct cred *acred);
 extern void nfs_begin_attr_update(struct inode *);
 extern void nfs_end_attr_update(struct inode *);
 extern void nfs_begin_data_update(struct inode *);


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

* [PATCH 23/52] CRED: Pass credentials to the setattr() inode operation
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (21 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 22/52] CRED: Pass credentials to nfs_setattr_update_inode() David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 24/52] CRED: Pass credentials through inode_setattr() David Howells
                   ` (30 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials to the setattr() inode operation.

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

 fs/afs/inode.c           |    2 +-
 fs/afs/internal.h        |    2 +-
 fs/attr.c                |    3 ++-
 fs/bad_inode.c           |    3 ++-
 fs/ext3/inode.c          |    3 +--
 fs/fat/file.c            |    3 ++-
 fs/nfs/inode.c           |    5 ++---
 fs/proc/base.c           |    3 ++-
 fs/proc/generic.c        |    3 ++-
 fs/proc/proc_net.c       |    5 +++--
 fs/proc/proc_sysctl.c    |    3 ++-
 fs/sysfs/inode.c         |    3 ++-
 fs/sysfs/sysfs.h         |    3 ++-
 include/linux/ext3_fs.h  |    2 +-
 include/linux/fs.h       |    2 +-
 include/linux/msdos_fs.h |    3 ++-
 include/linux/nfs_fs.h   |    2 +-
 mm/shmem.c               |    3 ++-
 18 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index ca9b02f..f6e4dc1 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -357,7 +357,7 @@ void afs_clear_inode(struct inode *inode)
 /*
  * set the attributes of an inode
  */
-int afs_setattr(struct dentry *dentry, struct iattr *attr)
+int afs_setattr(struct dentry *dentry, struct iattr *attr, struct cred *cred)
 {
 	struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
 	struct key *key;
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 6306438..cac5092 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -549,7 +549,7 @@ extern struct inode *afs_iget(struct super_block *, struct key *,
 extern void afs_zap_data(struct afs_vnode *);
 extern int afs_validate(struct afs_vnode *, struct key *);
 extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int afs_setattr(struct dentry *, struct iattr *);
+extern int afs_setattr(struct dentry *, struct iattr *, struct cred *);
 extern void afs_clear_inode(struct inode *);
 
 /*
diff --git a/fs/attr.c b/fs/attr.c
index 06a3145..1b2908c 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -107,6 +107,7 @@ EXPORT_SYMBOL(inode_setattr);
 
 int notify_change(struct dentry * dentry, struct iattr * attr)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	mode_t mode;
 	int error;
@@ -150,7 +151,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 	if (inode->i_op && inode->i_op->setattr) {
 		error = security_inode_setattr(dentry, attr);
 		if (!error)
-			error = inode->i_op->setattr(dentry, attr);
+			error = inode->i_op->setattr(dentry, attr, cred);
 	} else {
 		error = inode_change_ok(inode, attr);
 		if (!error)
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index f1c2ea8..dda2d52 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -255,7 +255,8 @@ static int bad_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	return -EIO;
 }
 
-static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
+static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs,
+			     struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 31e5b38..deb0d56 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2941,9 +2941,8 @@ int ext3_write_inode(struct inode *inode, int wait)
  *
  * Called with inode->sem down.
  */
-int ext3_setattr(struct dentry *dentry, struct iattr *attr)
+int ext3_setattr(struct dentry *dentry, struct iattr *attr, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int error, rc = 0;
 	const unsigned int ia_valid = attr->ia_valid;
diff --git a/fs/fat/file.c b/fs/fat/file.c
index a871db8..4c856c5 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -155,7 +155,8 @@ out:
 	return err;
 }
 
-int fat_notify_change(struct dentry *dentry, struct iattr *attr)
+int fat_notify_change(struct dentry *dentry, struct iattr *attr,
+		      struct cred *cred)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
 	struct inode *inode = dentry->d_inode;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f76a93c..178979c 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -319,9 +319,8 @@ out_no_inode:
 #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET)
 
 int
-nfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
-	struct cred *acred = current->cred;
+nfs_setattr(struct dentry *dentry, struct iattr *attr, struct cred *acred)
+{	
 	struct inode *inode = dentry->d_inode;
 	struct nfs_fattr fattr;
 	int error;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 19489b0..0612ea4 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -343,7 +343,8 @@ static int proc_fd_access_allowed(struct inode *inode)
 	return allowed;
 }
 
-static int proc_setattr(struct dentry *dentry, struct iattr *attr)
+static int proc_setattr(struct dentry *dentry, struct iattr *attr,
+			struct cred *cred)
 {
 	int error;
 	struct inode *inode = dentry->d_inode;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index b5e7155..706d373 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -233,7 +233,8 @@ proc_file_lseek(struct file *file, loff_t offset, int orig)
 	return retval;
 }
 
-static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
+static int proc_notify_change(struct dentry *dentry, struct iattr *iattr,
+			      struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct proc_dir_entry *de = PDE(inode);
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 2e91fb7..3011c08 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -116,7 +116,8 @@ static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry,
 	return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd);
 }
 
-static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
+static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr,
+			    struct cred *cred)
 {
 	struct net *net = current->nsproxy->net_ns;
 	struct dentry *shadow;
@@ -125,7 +126,7 @@ static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
 	shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net);
 	if (!shadow)
 		return -ENOENT;
-	ret = shadow->d_inode->i_op->setattr(shadow, iattr);
+	ret = shadow->d_inode->i_op->setattr(shadow, iattr, cred);
 	dput(shadow);
 	return ret;
 }
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index feaf4f5..a939a09 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -420,7 +420,8 @@ out:
 	return error;
 }
 
-static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
+static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr,
+			    struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index fc1934e..6b4fac5 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -44,7 +44,8 @@ void sysfs_delete_inode(struct inode *inode)
 	return generic_delete_inode(inode);
 }
 
-int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
+int sysfs_setattr(struct dentry * dentry, struct iattr * iattr,
+		  struct cred *cred)
 {
 	struct inode * inode = dentry->d_inode;
 	struct sysfs_dirent * sd = dentry->d_fsdata;
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 6b8c8d7..9b9d575 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -91,7 +91,8 @@ extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
 			       struct sysfs_dirent **p_sd);
 extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
 
-extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr,
+			 struct cred *cred);
 
 extern spinlock_t sysfs_assoc_lock;
 extern struct mutex sysfs_mutex;
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index a2b686d..1ec7712 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -820,7 +820,7 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 
 extern struct inode *ext3_iget (struct super_block *, unsigned long);
 extern int  ext3_write_inode (struct inode *, int);
-extern int  ext3_setattr (struct dentry *, struct iattr *);
+extern int  ext3_setattr (struct dentry *, struct iattr *, struct cred *);
 extern void ext3_delete_inode (struct inode *);
 extern int  ext3_sync_inode (handle_t *, struct inode *);
 extern void ext3_discard_reservation (struct inode *);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 747fc5b..ec9ed45 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1150,7 +1150,7 @@ struct inode_operations {
 	void (*put_link) (struct dentry *, struct nameidata *, void *);
 	void (*truncate) (struct inode *, struct cred *);
 	int (*permission) (struct inode *, int, struct nameidata *);
-	int (*setattr) (struct dentry *, struct iattr *);
+	int (*setattr) (struct dentry *, struct iattr *, struct cred *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index ddd669c..63a3efc 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -401,7 +401,8 @@ extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
 			     unsigned int cmd, unsigned long arg);
 extern const struct file_operations fat_file_operations;
 extern const struct inode_operations fat_file_inode_operations;
-extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
+extern int fat_notify_change(struct dentry * dentry, struct iattr * attr,
+			     struct cred *cred);
 extern void fat_truncate(struct inode *inode, struct cred *cred);
 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		       struct kstat *stat);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index fe3136e..670e734 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -306,7 +306,7 @@ extern int nfs_revalidate_mapping(struct inode *inode,
 extern int nfs_revalidate_mapping_nolock(struct inode *inode,
 					 struct address_space *mapping,
 					 struct cred *acred);
-extern int nfs_setattr(struct dentry *, struct iattr *);
+extern int nfs_setattr(struct dentry *, struct iattr *, struct cred *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
 				     struct cred *acred);
 extern void nfs_begin_attr_update(struct inode *);
diff --git a/mm/shmem.c b/mm/shmem.c
index accaa18..f6054e0 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -713,7 +713,8 @@ static void shmem_truncate(struct inode *inode, struct cred *cred)
 	shmem_truncate_range(inode, inode->i_size, (loff_t)-1);
 }
 
-static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
+static int shmem_notify_change(struct dentry *dentry, struct iattr *attr,
+			       struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct page *page = NULL;


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

* [PATCH 24/52] CRED: Pass credentials through inode_setattr()
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (22 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 23/52] CRED: Pass credentials to the setattr() inode operation David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 25/52] CRED: Give the mknod() inode op a credentials pointer David Howells
                   ` (29 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the inode_setattr() function.

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

 fs/attr.c             |    5 ++---
 fs/ext3/inode.c       |    2 +-
 fs/fat/file.c         |    2 +-
 fs/proc/base.c        |    2 +-
 fs/proc/generic.c     |    2 +-
 fs/proc/proc_sysctl.c |    2 +-
 fs/sysfs/inode.c      |    2 +-
 include/linux/fs.h    |    3 ++-
 mm/shmem.c            |    2 +-
 9 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/fs/attr.c b/fs/attr.c
index 1b2908c..f70bffc 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -66,9 +66,8 @@ error:
 
 EXPORT_SYMBOL(inode_change_ok);
 
-int inode_setattr(struct inode * inode, struct iattr * attr)
+int inode_setattr(struct inode * inode, struct iattr * attr, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	unsigned int ia_valid = attr->ia_valid;
 
 	if (ia_valid & ATTR_SIZE &&
@@ -161,7 +160,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 			    (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
 				error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
 			if (!error)
-				error = inode_setattr(inode, attr);
+				error = inode_setattr(inode, attr, cred);
 		}
 	}
 
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index deb0d56..8635acc 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2996,7 +2996,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr, struct cred *cred)
 		ext3_journal_stop(handle);
 	}
 
-	rc = inode_setattr(inode, attr);
+	rc = inode_setattr(inode, attr, cred);
 
 	/* If inode_setattr's call to ext3_truncate failed to get a
 	 * transaction handle at all, we need to clean up the in-core
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 4c856c5..f0b3faa 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -197,7 +197,7 @@ int fat_notify_change(struct dentry *dentry, struct iattr *attr,
 			error = 0;
 		goto out;
 	}
-	error = inode_setattr(inode, attr);
+	error = inode_setattr(inode, attr, cred);
 	if (error)
 		goto out;
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 0612ea4..c7f9940 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -354,7 +354,7 @@ static int proc_setattr(struct dentry *dentry, struct iattr *attr,
 
 	error = inode_change_ok(inode, attr);
 	if (!error)
-		error = inode_setattr(inode, attr);
+		error = inode_setattr(inode, attr, cred);
 	return error;
 }
 
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 706d373..00a2192 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -244,7 +244,7 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr,
 	if (error)
 		goto out;
 
-	error = inode_setattr(inode, iattr);
+	error = inode_setattr(inode, iattr, cred);
 	if (error)
 		goto out;
 	
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index a939a09..4db895c 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -431,7 +431,7 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr,
 
 	error = inode_change_ok(inode, attr);
 	if (!error)
-		error = inode_setattr(inode, attr);
+		error = inode_setattr(inode, attr, cred);
 
 	return error;
 }
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 6b4fac5..04fc15f 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -62,7 +62,7 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr,
 	if (error)
 		return error;
 
-	error = inode_setattr(inode, iattr);
+	error = inode_setattr(inode, iattr, cred);
 	if (error)
 		return error;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ec9ed45..10245c6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1825,7 +1825,8 @@ extern int buffer_migrate_page(struct address_space *,
 #endif
 
 extern int inode_change_ok(struct inode *, struct iattr *);
-extern int __must_check inode_setattr(struct inode *, struct iattr *);
+extern int __must_check inode_setattr(struct inode *, struct iattr *,
+				      struct cred *);
 
 extern void file_update_time(struct file *file);
 
diff --git a/mm/shmem.c b/mm/shmem.c
index f6054e0..ccab183 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -752,7 +752,7 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr,
 
 	error = inode_change_ok(inode, attr);
 	if (!error)
-		error = inode_setattr(inode, attr);
+		error = inode_setattr(inode, attr, cred);
 #ifdef CONFIG_TMPFS_POSIX_ACL
 	if (!error && (attr->ia_valid & ATTR_MODE))
 		error = generic_acl_chmod(inode, &shmem_acl_ops);


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

* [PATCH 25/52] CRED: Give the mknod() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (23 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 24/52] CRED: Pass credentials through inode_setattr() David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 26/52] CRED: Give the mkdir() " David Howells
                   ` (28 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the mknod() inode op a credentials pointer.

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

 fs/bad_inode.c     |    2 +-
 fs/ext2/namei.c    |    4 ++--
 fs/ext3/namei.c    |    3 +--
 fs/ext4/namei.c    |    3 +--
 fs/namei.c         |    3 ++-
 fs/nfs/dir.c       |    7 ++++---
 fs/ramfs/inode.c   |   10 ++++++----
 include/linux/fs.h |    2 +-
 mm/shmem.c         |   10 ++++++----
 9 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index dda2d52..7df0a7c 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -226,7 +226,7 @@ static int bad_inode_rmdir (struct inode *dir, struct dentry *dentry)
 }
 
 static int bad_inode_mknod (struct inode *dir, struct dentry *dentry,
-			int mode, dev_t rdev)
+			int mode, dev_t rdev, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 821a2c3..f539ee0 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -126,9 +126,9 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st
 	return err;
 }
 
-static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev)
+static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode,
+		       dev_t rdev, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode * inode;
 	int err;
 
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 4a6adaa..54f997d 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1752,9 +1752,8 @@ retry:
 }
 
 static int ext3_mknod (struct inode * dir, struct dentry *dentry,
-			int mode, dev_t rdev)
+			int mode, dev_t rdev, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode *inode;
 	int err, retries = 0;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index be28f73..54530e7 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1781,9 +1781,8 @@ retry:
 }
 
 static int ext4_mknod (struct inode * dir, struct dentry *dentry,
-			int mode, dev_t rdev)
+			int mode, dev_t rdev, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode *inode;
 	int err, retries = 0;
diff --git a/fs/namei.c b/fs/namei.c
index 3db9a41..5ff42f1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1889,6 +1889,7 @@ EXPORT_SYMBOL_GPL(lookup_create);
 
 int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
+	struct cred *cred = current->cred;
 	int error = may_create(dir, dentry, NULL);
 
 	if (error)
@@ -1905,7 +1906,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 		return error;
 
 	DQUOT_INIT(dir);
-	error = dir->i_op->mknod(dir, dentry, mode, dev);
+	error = dir->i_op->mknod(dir, dentry, mode, dev, cred);
 	if (!error)
 		fsnotify_create(dir, dentry);
 	return error;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 35a63cf..35bbaf6 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -50,7 +50,8 @@ static int nfs_rmdir(struct inode *, struct dentry *);
 static int nfs_unlink(struct inode *, struct dentry *);
 static int nfs_symlink(struct inode *, struct dentry *, const char *);
 static int nfs_link(struct dentry *, struct inode *, struct dentry *);
-static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
+static int nfs_mknod(struct inode *, struct dentry *, int, dev_t,
+		     struct cred *);
 static int nfs_rename(struct inode *, struct dentry *,
 		      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, struct dentry *, int);
@@ -1284,9 +1285,9 @@ out_err:
  * See comments for nfs_proc_create regarding failed operations.
  */
 static int
-nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev,
+	  struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct iattr attr;
 	int status;
 
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 29100e2..f9e6244 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -91,9 +91,9 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev,
  */
 /* SMP-safe */
 static int
-ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
+	    struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev, cred);
 	int error = -ENOSPC;
 
@@ -113,7 +113,8 @@ ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 
 static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
-	int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
+	struct cred *cred = current->cred;
+	int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0, cred);
 	if (!retval)
 		inc_nlink(dir);
 	return retval;
@@ -121,7 +122,8 @@ static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 
 static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
-	return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
+	struct cred *cred = current->cred;
+	return ramfs_mknod(dir, dentry, mode | S_IFREG, 0, cred);
 }
 
 static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 10245c6..a8d2d26 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1142,7 +1142,7 @@ struct inode_operations {
 	int (*symlink) (struct inode *,struct dentry *,const char *);
 	int (*mkdir) (struct inode *,struct dentry *,int);
 	int (*rmdir) (struct inode *,struct dentry *);
-	int (*mknod) (struct inode *,struct dentry *,int,dev_t);
+	int (*mknod) (struct inode *,struct dentry *,int,dev_t, struct cred *);
 	int (*rename) (struct inode *, struct dentry *,
 			struct inode *, struct dentry *);
 	int (*readlink) (struct dentry *, char __user *,int);
diff --git a/mm/shmem.c b/mm/shmem.c
index ccab183..62ae312 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1707,9 +1707,9 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
  * File creation. Allocate an inode, and we're done..
  */
 static int
-shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
+	    struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev, cred);
 	int error = -ENOSPC;
 
@@ -1742,9 +1742,10 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 
 static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
+	struct cred *cred = current->cred;
 	int error;
 
-	if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
+	if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0, cred)))
 		return error;
 	inc_nlink(dir);
 	return 0;
@@ -1753,7 +1754,8 @@ static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
 		struct nameidata *nd)
 {
-	return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
+	struct cred *cred = current->cred;
+	return shmem_mknod(dir, dentry, mode | S_IFREG, 0, cred);
 }
 
 /*


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

* [PATCH 26/52] CRED: Give the mkdir() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (24 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 25/52] CRED: Give the mknod() inode op a credentials pointer David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 27/52] CRED: Give the create() " David Howells
                   ` (27 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the mkdir() inode op a credentials pointer.

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

 fs/afs/dir.c       |    6 ++++--
 fs/autofs4/root.c  |    5 +++--
 fs/bad_inode.c     |    2 +-
 fs/ext2/namei.c    |    4 ++--
 fs/ext3/namei.c    |    4 ++--
 fs/ext4/namei.c    |    4 ++--
 fs/namei.c         |    3 ++-
 fs/nfs/dir.c       |    6 +++---
 fs/ramfs/inode.c   |    4 ++--
 fs/vfat/namei.c    |    3 ++-
 include/linux/fs.h |    2 +-
 mm/shmem.c         |    4 ++--
 12 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index f861d08..ccc09f1 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -30,7 +30,8 @@ static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
 				  loff_t fpos, u64 ino, unsigned dtype);
 static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
 		      struct nameidata *nd);
-static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
+		     struct cred *cred);
 static int afs_rmdir(struct inode *dir, struct dentry *dentry);
 static int afs_unlink(struct inode *dir, struct dentry *dentry);
 static int afs_link(struct dentry *from, struct inode *dir,
@@ -721,7 +722,8 @@ static void afs_d_release(struct dentry *dentry)
 /*
  * create a directory on an AFS filesystem
  */
-static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
+		     struct cred *cred)
 {
 	struct afs_file_status status;
 	struct afs_callback cb;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 45ff3d6..63c0b62 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -22,7 +22,7 @@
 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
 static int autofs4_dir_unlink(struct inode *,struct dentry *);
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
-static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
+static int autofs4_dir_mkdir(struct inode *,struct dentry *,int, struct cred *);
 static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
 static int autofs4_dir_open(struct inode *inode, struct file *file);
 static int autofs4_dir_close(struct inode *inode, struct file *file);
@@ -829,7 +829,8 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
 	return 0;
 }
 
-static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode,
+			     struct cred *cred)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 7df0a7c..4b7e6b1 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -215,7 +215,7 @@ static int bad_inode_symlink (struct inode *dir, struct dentry *dentry,
 }
 
 static int bad_inode_mkdir(struct inode *dir, struct dentry *dentry,
-			int mode)
+			int mode, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index f539ee0..333330d 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -208,9 +208,9 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
 	return ext2_add_nondir(dentry, inode);
 }
 
-static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode,
+		      struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode * inode;
 	int err = -EMLINK;
 
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 54f997d..f02cb17 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1787,9 +1787,9 @@ retry:
 	return err;
 }
 
-static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode,
+		      struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	struct buffer_head * dir_block;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 54530e7..539456c 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1816,9 +1816,9 @@ retry:
 	return err;
 }
 
-static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode,
+		      struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	struct buffer_head * dir_block;
diff --git a/fs/namei.c b/fs/namei.c
index 5ff42f1..ca2ccb1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1969,6 +1969,7 @@ asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev)
 
 int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
+	struct cred *cred = current->cred;
 	int error = may_create(dir, dentry, NULL);
 
 	if (error)
@@ -1983,7 +1984,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 		return error;
 
 	DQUOT_INIT(dir);
-	error = dir->i_op->mkdir(dir, dentry, mode);
+	error = dir->i_op->mkdir(dir, dentry, mode, cred);
 	if (!error)
 		fsnotify_mkdir(dir, dentry);
 	return error;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 35bbaf6..98fccc1 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -45,7 +45,7 @@ static int nfs_opendir(struct inode *, struct file *);
 static int nfs_readdir(struct file *, void *, filldir_t);
 static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
-static int nfs_mkdir(struct inode *, struct dentry *, int);
+static int nfs_mkdir(struct inode *, struct dentry *, int, struct cred *);
 static int nfs_rmdir(struct inode *, struct dentry *);
 static int nfs_unlink(struct inode *, struct dentry *);
 static int nfs_symlink(struct inode *, struct dentry *, const char *);
@@ -1319,9 +1319,9 @@ out_err:
 /*
  * See comments for nfs_proc_create regarding failed operations.
  */
-static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
+		     struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct iattr attr;
 	int error;
 
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index f9e6244..0e3142b 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -111,9 +111,9 @@ ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
 	return error;
 }
 
-static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode,
+		       struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0, cred);
 	if (!retval)
 		inc_nlink(dir);
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index cd450be..132601d 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -817,7 +817,8 @@ out:
 	return err;
 }
 
-static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode,
+		      struct cred *cred)
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a8d2d26..69d7fcc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1140,7 +1140,7 @@ struct inode_operations {
 	int (*link) (struct dentry *,struct inode *,struct dentry *);
 	int (*unlink) (struct inode *,struct dentry *);
 	int (*symlink) (struct inode *,struct dentry *,const char *);
-	int (*mkdir) (struct inode *,struct dentry *,int);
+	int (*mkdir) (struct inode *,struct dentry *,int, struct cred *);
 	int (*rmdir) (struct inode *,struct dentry *);
 	int (*mknod) (struct inode *,struct dentry *,int,dev_t, struct cred *);
 	int (*rename) (struct inode *, struct dentry *,
diff --git a/mm/shmem.c b/mm/shmem.c
index 62ae312..e69691a 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1740,9 +1740,9 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
 	return error;
 }
 
-static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode,
+		       struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	int error;
 
 	if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0, cred)))


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

* [PATCH 27/52] CRED: Give the create() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (25 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 26/52] CRED: Give the mkdir() " David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 28/52] CRED: Give the link() " David Howells
                   ` (26 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the create() inode op a credentials pointer.

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

 fs/afs/dir.c       |    4 ++--
 fs/bad_inode.c     |    2 +-
 fs/ext3/namei.c    |    3 +--
 fs/namei.c         |    3 ++-
 fs/nfs/dir.c       |    6 +++---
 fs/ramfs/inode.c   |    4 ++--
 fs/vfat/namei.c    |    2 +-
 include/linux/fs.h |    3 ++-
 mm/shmem.c         |    3 +--
 9 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index ccc09f1..e495269 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -29,7 +29,7 @@ static void afs_d_release(struct dentry *dentry);
 static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
 				  loff_t fpos, u64 ino, unsigned dtype);
 static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
-		      struct nameidata *nd);
+		      struct nameidata *nd, struct cred *cred);
 static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
 		     struct cred *cred);
 static int afs_rmdir(struct inode *dir, struct dentry *dentry);
@@ -908,7 +908,7 @@ error:
  * create a regular file on an AFS filesystem
  */
 static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
-		      struct nameidata *nd)
+		      struct nameidata *nd, struct cred *cred)
 {
 	struct afs_file_status status;
 	struct afs_callback cb;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 4b7e6b1..3895f7d 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -186,7 +186,7 @@ static const struct file_operations bad_file_ops =
 };
 
 static int bad_inode_create (struct inode *dir, struct dentry *dentry,
-		int mode, struct nameidata *nd)
+		int mode, struct nameidata *nd, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index f02cb17..c007ef2 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1720,9 +1720,8 @@ static int ext3_add_nondir(handle_t *handle,
  * with d_instantiate().
  */
 static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
-		struct nameidata *nd)
+		struct nameidata *nd, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	int err, retries = 0;
diff --git a/fs/namei.c b/fs/namei.c
index ca2ccb1..ef6041a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1545,6 +1545,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
 int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 		struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	int error = may_create(dir, dentry, nd);
 
 	if (error)
@@ -1558,7 +1559,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	if (error)
 		return error;
 	DQUOT_INIT(dir);
-	error = dir->i_op->create(dir, dentry, mode, nd);
+	error = dir->i_op->create(dir, dentry, mode, nd, cred);
 	if (!error)
 		fsnotify_create(dir, dentry);
 	return error;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 98fccc1..833351e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -44,7 +44,8 @@
 static int nfs_opendir(struct inode *, struct file *);
 static int nfs_readdir(struct file *, void *, filldir_t);
 static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
+static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *,
+		      struct cred *);
 static int nfs_mkdir(struct inode *, struct dentry *, int, struct cred *);
 static int nfs_rmdir(struct inode *, struct dentry *);
 static int nfs_unlink(struct inode *, struct dentry *);
@@ -1248,9 +1249,8 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
  * reply path made it appear to have failed.
  */
 static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
-		struct nameidata *nd)
+		struct nameidata *nd, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct iattr attr;
 	int error;
 	int open_flags = 0;
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 0e3142b..53e917c 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -120,9 +120,9 @@ static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode,
 	return retval;
 }
 
-static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
+static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode,
+			struct nameidata *nd, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	return ramfs_mknod(dir, dentry, mode | S_IFREG, 0, cred);
 }
 
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 132601d..8784b57 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -731,7 +731,7 @@ error:
 }
 
 static int vfat_create(struct inode *dir, struct dentry *dentry, int mode,
-		       struct nameidata *nd)
+		       struct nameidata *nd, struct cred *cred)
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 69d7fcc..cb09038 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1135,7 +1135,8 @@ struct file_operations {
 };
 
 struct inode_operations {
-	int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+	int (*create) (struct inode *,struct dentry *,int, struct nameidata *,
+		       struct cred *);
 	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
 	int (*link) (struct dentry *,struct inode *,struct dentry *);
 	int (*unlink) (struct inode *,struct dentry *);
diff --git a/mm/shmem.c b/mm/shmem.c
index e69691a..3fff09b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1752,9 +1752,8 @@ static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode,
 }
 
 static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
-		struct nameidata *nd)
+		struct nameidata *nd, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	return shmem_mknod(dir, dentry, mode | S_IFREG, 0, cred);
 }
 


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

* [PATCH 28/52] CRED: Give the link() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (26 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 27/52] CRED: Give the create() " David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 29/52] CRED: Give the unlink() " David Howells
                   ` (25 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the link() inode op a credentials pointer.

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

 fs/afs/dir.c       |    4 ++--
 fs/bad_inode.c     |    2 +-
 fs/ext3/namei.c    |    3 +--
 fs/libfs.c         |    3 ++-
 fs/namei.c         |    3 ++-
 fs/nfs/dir.c       |    7 ++++---
 include/linux/fs.h |    6 ++++--
 mm/shmem.c         |    3 ++-
 8 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index e495269..48f2759 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -35,7 +35,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
 static int afs_rmdir(struct inode *dir, struct dentry *dentry);
 static int afs_unlink(struct inode *dir, struct dentry *dentry);
 static int afs_link(struct dentry *from, struct inode *dir,
-		    struct dentry *dentry);
+		    struct dentry *dentry, struct cred *cred);
 static int afs_symlink(struct inode *dir, struct dentry *dentry,
 		       const char *content);
 static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -979,7 +979,7 @@ error:
  * create a hard link between files in an AFS filesystem
  */
 static int afs_link(struct dentry *from, struct inode *dir,
-		    struct dentry *dentry)
+		    struct dentry *dentry, struct cred *cred)
 {
 	struct afs_vnode *dvnode, *vnode;
 	struct key *key;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 3895f7d..a13970d 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -198,7 +198,7 @@ static struct dentry *bad_inode_lookup(struct inode *dir,
 }
 
 static int bad_inode_link (struct dentry *old_dentry, struct inode *dir,
-		struct dentry *dentry)
+		struct dentry *dentry, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index c007ef2..4c19acf 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2254,9 +2254,8 @@ out_stop:
 }
 
 static int ext3_link (struct dentry * old_dentry,
-		struct inode * dir, struct dentry *dentry)
+		struct inode * dir, struct dentry *dentry, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode *inode = old_dentry->d_inode;
 	int err, retries = 0;
diff --git a/fs/libfs.c b/fs/libfs.c
index 5294de1..d82eaaa 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -250,7 +250,8 @@ Enomem:
 	return -ENOMEM;
 }
 
-int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+int simple_link(struct dentry *old_dentry, struct inode *dir,
+		struct dentry *dentry, struct cred *cred)
 {
 	struct inode *inode = old_dentry->d_inode;
 
diff --git a/fs/namei.c b/fs/namei.c
index ef6041a..51e0322 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2300,6 +2300,7 @@ asmlinkage long sys_symlink(const char __user *oldname, const char __user *newna
 
 int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = old_dentry->d_inode;
 	int error;
 
@@ -2329,7 +2330,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
 
 	mutex_lock(&old_dentry->d_inode->i_mutex);
 	DQUOT_INIT(dir);
-	error = dir->i_op->link(old_dentry, dir, new_dentry);
+	error = dir->i_op->link(old_dentry, dir, new_dentry, cred);
 	mutex_unlock(&old_dentry->d_inode->i_mutex);
 	if (!error)
 		fsnotify_create(dir, new_dentry);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 833351e..4e12cf7 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -50,7 +50,8 @@ static int nfs_mkdir(struct inode *, struct dentry *, int, struct cred *);
 static int nfs_rmdir(struct inode *, struct dentry *);
 static int nfs_unlink(struct inode *, struct dentry *);
 static int nfs_symlink(struct inode *, struct dentry *, const char *);
-static int nfs_link(struct dentry *, struct inode *, struct dentry *);
+static int nfs_link(struct dentry *, struct inode *, struct dentry *,
+		    struct cred *);
 static int nfs_mknod(struct inode *, struct dentry *, int, dev_t,
 		     struct cred *);
 static int nfs_rename(struct inode *, struct dentry *,
@@ -1604,9 +1605,9 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
 }
 
 static int 
-nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry,
+	 struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *inode = old_dentry->d_inode;
 	int error;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cb09038..d8cecd4 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1138,7 +1138,8 @@ struct inode_operations {
 	int (*create) (struct inode *,struct dentry *,int, struct nameidata *,
 		       struct cred *);
 	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
-	int (*link) (struct dentry *,struct inode *,struct dentry *);
+	int (*link) (struct dentry *,struct inode *,struct dentry *,
+		     struct cred *);
 	int (*unlink) (struct inode *,struct dentry *);
 	int (*symlink) (struct inode *,struct dentry *,const char *);
 	int (*mkdir) (struct inode *,struct dentry *,int, struct cred *);
@@ -1794,7 +1795,8 @@ extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
 extern int dcache_readdir(struct file *, void *, filldir_t);
 extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int simple_statfs(struct dentry *, struct kstatfs *);
-extern int simple_link(struct dentry *, struct inode *, struct dentry *);
+extern int simple_link(struct dentry *, struct inode *, struct dentry *,
+		       struct cred *);
 extern int simple_unlink(struct inode *, struct dentry *);
 extern int simple_rmdir(struct inode *, struct dentry *);
 extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
diff --git a/mm/shmem.c b/mm/shmem.c
index 3fff09b..7358d14 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1760,7 +1760,8 @@ static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
 /*
  * Link a file..
  */
-static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+static int shmem_link(struct dentry *old_dentry, struct inode *dir,
+		      struct dentry *dentry, struct cred *cred)
 {
 	struct inode *inode = old_dentry->d_inode;
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);


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

* [PATCH 29/52] CRED: Give the unlink() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (27 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 28/52] CRED: Give the link() " David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 30/52] CRED: Give the rmdir() " David Howells
                   ` (24 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the unlink() inode op a credentials pointer.

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

 fs/afs/dir.c                 |    6 ++++--
 fs/autofs4/root.c            |    5 +++--
 fs/bad_inode.c               |    3 ++-
 fs/ext3/namei.c              |    4 ++--
 fs/libfs.c                   |   10 +++++++---
 fs/namei.c                   |    3 ++-
 fs/nfs/dir.c                 |    6 +++---
 fs/vfat/namei.c              |    3 ++-
 include/linux/fs.h           |    4 ++--
 mm/shmem.c                   |    9 ++++++---
 net/sunrpc/rpc_pipe.c        |    6 ++++--
 security/inode.c             |    3 ++-
 security/selinux/selinuxfs.c |    3 ++-
 13 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 48f2759..b6d5abb 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -33,7 +33,8 @@ static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
 static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
 		     struct cred *cred);
 static int afs_rmdir(struct inode *dir, struct dentry *dentry);
-static int afs_unlink(struct inode *dir, struct dentry *dentry);
+static int afs_unlink(struct inode *dir, struct dentry *dentry,
+		      struct cred *cred);
 static int afs_link(struct dentry *from, struct inode *dir,
 		    struct dentry *dentry, struct cred *cred);
 static int afs_symlink(struct inode *dir, struct dentry *dentry,
@@ -839,7 +840,8 @@ error:
 /*
  * remove a file from an AFS filesystem
  */
-static int afs_unlink(struct inode *dir, struct dentry *dentry)
+static int afs_unlink(struct inode *dir, struct dentry *dentry,
+		      struct cred *cred)
 {
 	struct afs_vnode *dvnode, *vnode;
 	struct key *key;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 63c0b62..747a51f 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -20,7 +20,7 @@
 #include "autofs_i.h"
 
 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
-static int autofs4_dir_unlink(struct inode *,struct dentry *);
+static int autofs4_dir_unlink(struct inode *,struct dentry *, struct cred *);
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int, struct cred *);
 static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
@@ -755,7 +755,8 @@ static int autofs4_dir_symlink(struct inode *dir,
  *
  * Also see autofs4_dir_rmdir()..
  */
-static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
+static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry,
+			      struct cred *cred)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index a13970d..0b0a787 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -203,7 +203,8 @@ static int bad_inode_link (struct dentry *old_dentry, struct inode *dir,
 	return -EIO;
 }
 
-static int bad_inode_unlink(struct inode *dir, struct dentry *dentry)
+static int bad_inode_unlink(struct inode *dir, struct dentry *dentry,
+			    struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 4c19acf..f0e3303 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2140,9 +2140,9 @@ end_rmdir:
 	return retval;
 }
 
-static int ext3_unlink(struct inode * dir, struct dentry *dentry)
+static int ext3_unlink(struct inode * dir, struct dentry *dentry,
+		       struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
diff --git a/fs/libfs.c b/fs/libfs.c
index d82eaaa..d4cab7a 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -8,6 +8,7 @@
 #include <linux/mount.h>
 #include <linux/vfs.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
 
 #include <asm/uaccess.h>
 
@@ -283,7 +284,7 @@ out:
 	return ret;
 }
 
-int simple_unlink(struct inode *dir, struct dentry *dentry)
+int simple_unlink(struct inode *dir, struct dentry *dentry, struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 
@@ -295,11 +296,13 @@ int simple_unlink(struct inode *dir, struct dentry *dentry)
 
 int simple_rmdir(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
+
 	if (!simple_empty(dentry))
 		return -ENOTEMPTY;
 
 	drop_nlink(dentry->d_inode);
-	simple_unlink(dir, dentry);
+	simple_unlink(dir, dentry, cred);
 	drop_nlink(dir);
 	return 0;
 }
@@ -307,6 +310,7 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
 int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
 		struct inode *new_dir, struct dentry *new_dentry)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = old_dentry->d_inode;
 	int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
 
@@ -314,7 +318,7 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
 		return -ENOTEMPTY;
 
 	if (new_dentry->d_inode) {
-		simple_unlink(new_dir, new_dentry);
+		simple_unlink(new_dir, new_dentry, cred);
 		if (they_are_dirs)
 			drop_nlink(old_dir);
 	} else if (they_are_dirs) {
diff --git a/fs/namei.c b/fs/namei.c
index 51e0322..fe94ef5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2138,6 +2138,7 @@ asmlinkage long sys_rmdir(const char __user *pathname)
 
 int vfs_unlink(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	int error = may_delete(dir, dentry, 0);
 
 	if (error)
@@ -2154,7 +2155,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
 	else {
 		error = security_inode_unlink(dir, dentry);
 		if (!error)
-			error = dir->i_op->unlink(dir, dentry);
+			error = dir->i_op->unlink(dir, dentry, cred);
 	}
 	mutex_unlock(&dentry->d_inode->i_mutex);
 
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 4e12cf7..5c1f1d4 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -48,7 +48,7 @@ static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *,
 		      struct cred *);
 static int nfs_mkdir(struct inode *, struct dentry *, int, struct cred *);
 static int nfs_rmdir(struct inode *, struct dentry *);
-static int nfs_unlink(struct inode *, struct dentry *);
+static int nfs_unlink(struct inode *, struct dentry *, struct cred *);
 static int nfs_symlink(struct inode *, struct dentry *, const char *);
 static int nfs_link(struct dentry *, struct inode *, struct dentry *,
 		    struct cred *);
@@ -1487,9 +1487,9 @@ out:
  *
  *  If sillyrename() returns 0, we do nothing, otherwise we unlink.
  */
-static int nfs_unlink(struct inode *dir, struct dentry *dentry)
+static int nfs_unlink(struct inode *dir, struct dentry *dentry,
+		      struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	int error;
 	int need_rehash = 0;
 
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 8784b57..434ffdf 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -793,7 +793,8 @@ out:
 	return err;
 }
 
-static int vfat_unlink(struct inode *dir, struct dentry *dentry)
+static int vfat_unlink(struct inode *dir, struct dentry *dentry,
+		       struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct fat_slot_info sinfo;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d8cecd4..62df85a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1140,7 +1140,7 @@ struct inode_operations {
 	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
 	int (*link) (struct dentry *,struct inode *,struct dentry *,
 		     struct cred *);
-	int (*unlink) (struct inode *,struct dentry *);
+	int (*unlink) (struct inode *,struct dentry *, struct cred *);
 	int (*symlink) (struct inode *,struct dentry *,const char *);
 	int (*mkdir) (struct inode *,struct dentry *,int, struct cred *);
 	int (*rmdir) (struct inode *,struct dentry *);
@@ -1797,7 +1797,7 @@ extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int simple_statfs(struct dentry *, struct kstatfs *);
 extern int simple_link(struct dentry *, struct inode *, struct dentry *,
 		       struct cred *);
-extern int simple_unlink(struct inode *, struct dentry *);
+extern int simple_unlink(struct inode *, struct dentry *, struct cred *);
 extern int simple_rmdir(struct inode *, struct dentry *);
 extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 extern int simple_sync_file(struct file *, struct dentry *, int);
diff --git a/mm/shmem.c b/mm/shmem.c
index 7358d14..1e3c4e7 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1790,7 +1790,8 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir,
 	return 0;
 }
 
-static int shmem_unlink(struct inode *dir, struct dentry *dentry)
+static int shmem_unlink(struct inode *dir, struct dentry *dentry,
+			struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 
@@ -1812,12 +1813,13 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
 
 static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	if (!simple_empty(dentry))
 		return -ENOTEMPTY;
 
 	drop_nlink(dentry->d_inode);
 	drop_nlink(dir);
-	return shmem_unlink(dir, dentry);
+	return shmem_unlink(dir, dentry, cred);
 }
 
 /*
@@ -1828,6 +1830,7 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
  */
 static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = old_dentry->d_inode;
 	int they_are_dirs = S_ISDIR(inode->i_mode);
 
@@ -1835,7 +1838,7 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct
 		return -ENOTEMPTY;
 
 	if (new_dentry->d_inode) {
-		(void) shmem_unlink(new_dir, new_dentry);
+		(void) shmem_unlink(new_dir, new_dentry, cred);
 		if (they_are_dirs)
 			drop_nlink(old_dir);
 	} else if (they_are_dirs) {
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 669e12a..1906ee1 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -514,6 +514,7 @@ rpc_get_inode(struct super_block *sb, int mode)
 static void
 rpc_depopulate(struct dentry *parent, int start, int eof)
 {
+	struct cred *cred = current->cred;
 	struct inode *dir = parent->d_inode;
 	struct list_head *pos, *next;
 	struct dentry *dentry, *dvec[10];
@@ -544,7 +545,7 @@ repeat:
 		do {
 			dentry = dvec[--n];
 			if (S_ISREG(dentry->d_inode->i_mode))
-				simple_unlink(dir, dentry);
+				simple_unlink(dir, dentry, cred);
 			else if (S_ISDIR(dentry->d_inode->i_mode))
 				simple_rmdir(dir, dentry);
 			d_delete(dentry);
@@ -765,6 +766,7 @@ err_dput:
 int
 rpc_unlink(struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	struct dentry *parent;
 	struct inode *dir;
 	int error = 0;
@@ -774,7 +776,7 @@ rpc_unlink(struct dentry *dentry)
 	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
 	if (--RPC_I(dentry->d_inode)->nkern_readwriters == 0) {
 		rpc_close_pipes(dentry->d_inode);
-		error = simple_unlink(dir, dentry);
+		error = simple_unlink(dir, dentry, cred);
 		if (!error)
 			d_delete(dentry);
 	}
diff --git a/security/inode.c b/security/inode.c
index 307211a..1eaaf3d 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -292,6 +292,7 @@ EXPORT_SYMBOL_GPL(securityfs_create_dir);
 void securityfs_remove(struct dentry *dentry)
 {
 	struct dentry *parent;
+	struct cred *cred = current->cred;
 
 	if (!dentry)
 		return;
@@ -306,7 +307,7 @@ void securityfs_remove(struct dentry *dentry)
 			if (S_ISDIR(dentry->d_inode->i_mode))
 				simple_rmdir(parent->d_inode, dentry);
 			else
-				simple_unlink(parent->d_inode, dentry);
+				simple_unlink(parent->d_inode, dentry, cred);
 			dput(dentry);
 		}
 	}
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c9e92da..728b631 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -963,6 +963,7 @@ static void sel_remove_entries(struct dentry *de)
 {
 	struct list_head *p, *node;
 	struct super_block *sb = de->d_sb;
+	struct cred *cred = current->cred;
 
 	spin_lock(&dcache_lock);
 	node = de->d_subdirs.next;
@@ -974,7 +975,7 @@ static void sel_remove_entries(struct dentry *de)
 			d = dget_locked(d);
 			spin_unlock(&dcache_lock);
 			d_delete(d);
-			simple_unlink(de->d_inode, d);
+			simple_unlink(de->d_inode, d, cred);
 			dput(d);
 			spin_lock(&dcache_lock);
 		}


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

* [PATCH 30/52] CRED: Give the rmdir() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (28 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 29/52] CRED: Give the unlink() " David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:07 ` [PATCH 31/52] CRED: Give the rename() " David Howells
                   ` (23 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the rmdir() inode op a credentials pointer.

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

 fs/afs/dir.c          |    6 ++++--
 fs/autofs4/root.c     |    5 +++--
 fs/bad_inode.c        |    3 ++-
 fs/ext3/namei.c       |    4 ++--
 fs/libfs.c            |    4 +---
 fs/namei.c            |    3 ++-
 fs/nfs/dir.c          |    6 +++---
 fs/vfat/namei.c       |    3 ++-
 include/linux/fs.h    |    4 ++--
 mm/shmem.c            |    4 ++--
 net/sunrpc/rpc_pipe.c |    6 ++++--
 security/inode.c      |    2 +-
 12 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index b6d5abb..9f2c214 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -32,7 +32,8 @@ static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
 		      struct nameidata *nd, struct cred *cred);
 static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
 		     struct cred *cred);
-static int afs_rmdir(struct inode *dir, struct dentry *dentry);
+static int afs_rmdir(struct inode *dir, struct dentry *dentry,
+		     struct cred *cred);
 static int afs_unlink(struct inode *dir, struct dentry *dentry,
 		      struct cred *cred);
 static int afs_link(struct dentry *from, struct inode *dir,
@@ -794,7 +795,8 @@ error:
 /*
  * remove a directory from an AFS filesystem
  */
-static int afs_rmdir(struct inode *dir, struct dentry *dentry)
+static int afs_rmdir(struct inode *dir, struct dentry *dentry,
+		     struct cred *cred)
 {
 	struct afs_vnode *dvnode, *vnode;
 	struct key *key;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 747a51f..1743d38 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -21,7 +21,7 @@
 
 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
 static int autofs4_dir_unlink(struct inode *,struct dentry *, struct cred *);
-static int autofs4_dir_rmdir(struct inode *,struct dentry *);
+static int autofs4_dir_rmdir(struct inode *,struct dentry *, struct cred *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int, struct cred *);
 static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
 static int autofs4_dir_open(struct inode *inode, struct file *file);
@@ -790,7 +790,8 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry,
 	return 0;
 }
 
-static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
+static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry,
+			     struct cred *cred)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 0b0a787..79d8856 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -221,7 +221,8 @@ static int bad_inode_mkdir(struct inode *dir, struct dentry *dentry,
 	return -EIO;
 }
 
-static int bad_inode_rmdir (struct inode *dir, struct dentry *dentry)
+static int bad_inode_rmdir (struct inode *dir, struct dentry *dentry,
+			    struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index f0e3303..b54b60a 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2080,9 +2080,9 @@ out_brelse:
 	goto out_err;
 }
 
-static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
+static int ext3_rmdir (struct inode * dir, struct dentry *dentry,
+		       struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	int retval;
 	struct inode * inode;
 	struct buffer_head * bh;
diff --git a/fs/libfs.c b/fs/libfs.c
index d4cab7a..f237ef3 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -294,10 +294,8 @@ int simple_unlink(struct inode *dir, struct dentry *dentry, struct cred *cred)
 	return 0;
 }
 
-int simple_rmdir(struct inode *dir, struct dentry *dentry)
+int simple_rmdir(struct inode *dir, struct dentry *dentry, struct cred *cred)
 {
-	struct cred *cred = current->cred;
-
 	if (!simple_empty(dentry))
 		return -ENOTEMPTY;
 
diff --git a/fs/namei.c b/fs/namei.c
index fe94ef5..b991b32 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2058,6 +2058,7 @@ void dentry_unhash(struct dentry *dentry)
 
 int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	int error = may_delete(dir, dentry, 1);
 
 	if (error)
@@ -2075,7 +2076,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 	else {
 		error = security_inode_rmdir(dir, dentry);
 		if (!error) {
-			error = dir->i_op->rmdir(dir, dentry);
+			error = dir->i_op->rmdir(dir, dentry, cred);
 			if (!error)
 				dentry->d_inode->i_flags |= S_DEAD;
 		}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 5c1f1d4..447a364 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -47,7 +47,7 @@ static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameida
 static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *,
 		      struct cred *);
 static int nfs_mkdir(struct inode *, struct dentry *, int, struct cred *);
-static int nfs_rmdir(struct inode *, struct dentry *);
+static int nfs_rmdir(struct inode *, struct dentry *, struct cred *);
 static int nfs_unlink(struct inode *, struct dentry *, struct cred *);
 static int nfs_symlink(struct inode *, struct dentry *, const char *);
 static int nfs_link(struct dentry *, struct inode *, struct dentry *,
@@ -1348,9 +1348,9 @@ out_err:
 	return error;
 }
 
-static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
+static int nfs_rmdir(struct inode *dir, struct dentry *dentry,
+		     struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	int error;
 
 	dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 434ffdf..f4bab9d 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -764,7 +764,8 @@ out:
 	return err;
 }
 
-static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
+static int vfat_rmdir(struct inode *dir, struct dentry *dentry,
+		      struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct fat_slot_info sinfo;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 62df85a..f7838e9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1143,7 +1143,7 @@ struct inode_operations {
 	int (*unlink) (struct inode *,struct dentry *, struct cred *);
 	int (*symlink) (struct inode *,struct dentry *,const char *);
 	int (*mkdir) (struct inode *,struct dentry *,int, struct cred *);
-	int (*rmdir) (struct inode *,struct dentry *);
+	int (*rmdir) (struct inode *,struct dentry *, struct cred *);
 	int (*mknod) (struct inode *,struct dentry *,int,dev_t, struct cred *);
 	int (*rename) (struct inode *, struct dentry *,
 			struct inode *, struct dentry *);
@@ -1798,7 +1798,7 @@ extern int simple_statfs(struct dentry *, struct kstatfs *);
 extern int simple_link(struct dentry *, struct inode *, struct dentry *,
 		       struct cred *);
 extern int simple_unlink(struct inode *, struct dentry *, struct cred *);
-extern int simple_rmdir(struct inode *, struct dentry *);
+extern int simple_rmdir(struct inode *, struct dentry *, struct cred *);
 extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 extern int simple_sync_file(struct file *, struct dentry *, int);
 extern int simple_empty(struct dentry *);
diff --git a/mm/shmem.c b/mm/shmem.c
index 1e3c4e7..d0e2db8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1811,9 +1811,9 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry,
 	return 0;
 }
 
-static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
+static int shmem_rmdir(struct inode *dir, struct dentry *dentry,
+		       struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	if (!simple_empty(dentry))
 		return -ENOTEMPTY;
 
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 1906ee1..c38cc0d 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -547,7 +547,7 @@ repeat:
 			if (S_ISREG(dentry->d_inode->i_mode))
 				simple_unlink(dir, dentry, cred);
 			else if (S_ISDIR(dentry->d_inode->i_mode))
-				simple_rmdir(dir, dentry);
+				simple_rmdir(dir, dentry, cred);
 			d_delete(dentry);
 			dput(dentry);
 		} while (n);
@@ -618,8 +618,10 @@ out_err:
 static int
 __rpc_rmdir(struct inode *dir, struct dentry *dentry)
 {
+	struct cred *cred = current->cred;
 	int error;
-	error = simple_rmdir(dir, dentry);
+
+	error = simple_rmdir(dir, dentry, cred);
 	if (!error)
 		d_delete(dentry);
 	return error;
diff --git a/security/inode.c b/security/inode.c
index 1eaaf3d..0ea9f41 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -305,7 +305,7 @@ void securityfs_remove(struct dentry *dentry)
 	if (positive(dentry)) {
 		if (dentry->d_inode) {
 			if (S_ISDIR(dentry->d_inode->i_mode))
-				simple_rmdir(parent->d_inode, dentry);
+				simple_rmdir(parent->d_inode, dentry, cred);
 			else
 				simple_unlink(parent->d_inode, dentry, cred);
 			dput(dentry);


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

* [PATCH 31/52] CRED: Give the rename() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (29 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 30/52] CRED: Give the rmdir() " David Howells
@ 2007-10-12 16:07 ` David Howells
  2007-10-12 16:08 ` [PATCH 32/52] CRED: Give the symlink() " David Howells
                   ` (22 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:07 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the rename() inode op a credentials pointer.

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

 fs/afs/dir.c       |    6 ++++--
 fs/bad_inode.c     |    3 ++-
 fs/ext3/namei.c    |    4 ++--
 fs/libfs.c         |    5 ++---
 fs/namei.c         |    8 ++++++--
 fs/nfs/dir.c       |    6 +++---
 fs/vfat/namei.c    |    3 ++-
 include/linux/fs.h |    6 ++++--
 mm/shmem.c         |    5 +++--
 9 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 9f2c214..5f4ac2e 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -41,7 +41,8 @@ static int afs_link(struct dentry *from, struct inode *dir,
 static int afs_symlink(struct inode *dir, struct dentry *dentry,
 		       const char *content);
 static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
-		      struct inode *new_dir, struct dentry *new_dentry);
+		      struct inode *new_dir, struct dentry *new_dentry,
+		      struct cred *cred);
 
 const struct file_operations afs_dir_file_operations = {
 	.open		= afs_dir_open,
@@ -1103,7 +1104,8 @@ error:
  * rename a file in an AFS filesystem and/or move it between directories
  */
 static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
-		      struct inode *new_dir, struct dentry *new_dentry)
+		      struct inode *new_dir, struct dentry *new_dentry,
+		      struct cred *cred)
 {
 	struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
 	struct key *key;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 79d8856..2511f29 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -234,7 +234,8 @@ static int bad_inode_mknod (struct inode *dir, struct dentry *dentry,
 }
 
 static int bad_inode_rename (struct inode *old_dir, struct dentry *old_dentry,
-		struct inode *new_dir, struct dentry *new_dentry)
+			     struct inode *new_dir, struct dentry *new_dentry,
+			     struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index b54b60a..d682786 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2299,9 +2299,9 @@ retry:
  * higher-level routines.
  */
 static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
-			   struct inode * new_dir,struct dentry *new_dentry)
+			struct inode * new_dir, struct dentry *new_dentry,
+			struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * old_inode, * new_inode;
 	struct buffer_head * old_bh, * new_bh, * dir_bh;
diff --git a/fs/libfs.c b/fs/libfs.c
index f237ef3..6b41090 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -8,7 +8,6 @@
 #include <linux/mount.h>
 #include <linux/vfs.h>
 #include <linux/mutex.h>
-#include <linux/sched.h>
 
 #include <asm/uaccess.h>
 
@@ -306,9 +305,9 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry, struct cred *cred)
 }
 
 int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
-		struct inode *new_dir, struct dentry *new_dentry)
+		  struct inode *new_dir, struct dentry *new_dentry,
+		  struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = old_dentry->d_inode;
 	int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
 
diff --git a/fs/namei.c b/fs/namei.c
index b991b32..4af97fd 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2433,6 +2433,7 @@ asmlinkage long sys_link(const char __user *oldname, const char __user *newname)
 static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 			  struct inode *new_dir, struct dentry *new_dentry)
 {
+	struct cred *cred = current->cred;
 	int error = 0;
 	struct inode *target;
 
@@ -2458,7 +2459,8 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
 		error = -EBUSY;
 	else 
-		error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+		error = old_dir->i_op->rename(old_dir, old_dentry,
+					      new_dir, new_dentry, cred);
 	if (target) {
 		if (!error)
 			target->i_flags |= S_DEAD;
@@ -2476,6 +2478,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
 			    struct inode *new_dir, struct dentry *new_dentry)
 {
+	struct cred *cred = current->cred;
 	struct inode *target;
 	int error;
 
@@ -2490,7 +2493,8 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
 	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
 		error = -EBUSY;
 	else
-		error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+		error = old_dir->i_op->rename(old_dir, old_dentry,
+					      new_dir, new_dentry, cred);
 	if (!error) {
 		if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
 			d_move(old_dentry, new_dentry);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 447a364..18cea2c 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -55,7 +55,7 @@ static int nfs_link(struct dentry *, struct inode *, struct dentry *,
 static int nfs_mknod(struct inode *, struct dentry *, int, dev_t,
 		     struct cred *);
 static int nfs_rename(struct inode *, struct dentry *,
-		      struct inode *, struct dentry *);
+		      struct inode *, struct dentry *, struct cred *);
 static int nfs_fsync_dir(struct file *, struct dentry *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
 
@@ -1654,9 +1654,9 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry,
  * the rename.
  */
 static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-		      struct inode *new_dir, struct dentry *new_dentry)
+		      struct inode *new_dir, struct dentry *new_dentry,
+		      struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	struct dentry *dentry = NULL, *rehash = NULL;
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index f4bab9d..0502bb3 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -868,7 +868,8 @@ out:
 }
 
 static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
-		       struct inode *new_dir, struct dentry *new_dentry)
+		       struct inode *new_dir, struct dentry *new_dentry,
+		       struct cred *cred)
 {
 	struct buffer_head *dotdot_bh;
 	struct msdos_dir_entry *dotdot_de;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f7838e9..7fe8921 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1146,7 +1146,8 @@ struct inode_operations {
 	int (*rmdir) (struct inode *,struct dentry *, struct cred *);
 	int (*mknod) (struct inode *,struct dentry *,int,dev_t, struct cred *);
 	int (*rename) (struct inode *, struct dentry *,
-			struct inode *, struct dentry *);
+		       struct inode *, struct dentry *,
+		       struct cred *);
 	int (*readlink) (struct dentry *, char __user *,int);
 	void * (*follow_link) (struct dentry *, struct nameidata *);
 	void (*put_link) (struct dentry *, struct nameidata *, void *);
@@ -1799,7 +1800,8 @@ extern int simple_link(struct dentry *, struct inode *, struct dentry *,
 		       struct cred *);
 extern int simple_unlink(struct inode *, struct dentry *, struct cred *);
 extern int simple_rmdir(struct inode *, struct dentry *, struct cred *);
-extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+extern int simple_rename(struct inode *, struct dentry *,
+			 struct inode *, struct dentry *, struct cred *);
 extern int simple_sync_file(struct file *, struct dentry *, int);
 extern int simple_empty(struct dentry *);
 extern int simple_readpage(struct file *file, struct page *page);
diff --git a/mm/shmem.c b/mm/shmem.c
index d0e2db8..9d2ebe2 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1828,9 +1828,10 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry,
  * it exists so that the VFS layer correctly free's it when it
  * gets overwritten.
  */
-static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
+static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry,
+			struct inode *new_dir, struct dentry *new_dentry,
+			struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = old_dentry->d_inode;
 	int they_are_dirs = S_ISDIR(inode->i_mode);
 


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

* [PATCH 32/52] CRED: Give the symlink() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (30 preceding siblings ...)
  2007-10-12 16:07 ` [PATCH 31/52] CRED: Give the rename() " David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 33/52] CRED: Make the get_parent() export op take a credential pointer David Howells
                   ` (21 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the symlink() inode op a credentials pointer.

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

 fs/afs/dir.c       |    4 ++--
 fs/autofs4/root.c  |    6 ++++--
 fs/bad_inode.c     |    2 +-
 fs/ext3/namei.c    |    3 +--
 fs/namei.c         |    3 ++-
 fs/nfs/dir.c       |    7 ++++---
 fs/ramfs/inode.c   |    4 ++--
 include/linux/fs.h |    3 ++-
 mm/shmem.c         |    4 ++--
 9 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 5f4ac2e..745c8cb 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -39,7 +39,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry,
 static int afs_link(struct dentry *from, struct inode *dir,
 		    struct dentry *dentry, struct cred *cred);
 static int afs_symlink(struct inode *dir, struct dentry *dentry,
-		       const char *content);
+		       const char *content, struct cred *cred);
 static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		      struct inode *new_dir, struct dentry *new_dentry,
 		      struct cred *cred);
@@ -1030,7 +1030,7 @@ error:
  * create a symlink in an AFS filesystem
  */
 static int afs_symlink(struct inode *dir, struct dentry *dentry,
-		       const char *content)
+		       const char *content, struct cred *cred)
 {
 	struct afs_file_status status;
 	struct afs_server *server;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 1743d38..50c0ec7 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -19,7 +19,8 @@
 #include <linux/time.h>
 #include "autofs_i.h"
 
-static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
+static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *,
+			       struct cred *);
 static int autofs4_dir_unlink(struct inode *,struct dentry *, struct cred *);
 static int autofs4_dir_rmdir(struct inode *,struct dentry *, struct cred *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int, struct cred *);
@@ -690,7 +691,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
 
 static int autofs4_dir_symlink(struct inode *dir, 
 			       struct dentry *dentry,
-			       const char *symname)
+			       const char *symname,
+			       struct cred *cred)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 2511f29..2e25bfe 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -210,7 +210,7 @@ static int bad_inode_unlink(struct inode *dir, struct dentry *dentry,
 }
 
 static int bad_inode_symlink (struct inode *dir, struct dentry *dentry,
-		const char *symname)
+		const char *symname, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index d682786..cd0fcde 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2196,9 +2196,8 @@ end_unlink:
 }
 
 static int ext3_symlink (struct inode * dir,
-		struct dentry *dentry, const char * symname)
+		struct dentry *dentry, const char * symname, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct inode * inode;
 	int l, err, retries = 0;
diff --git a/fs/namei.c b/fs/namei.c
index 4af97fd..9439e6e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2239,6 +2239,7 @@ asmlinkage long sys_unlink(const char __user *pathname)
 
 int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
 {
+	struct cred *cred = current->cred;
 	int error = may_create(dir, dentry, NULL);
 
 	if (error)
@@ -2252,7 +2253,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i
 		return error;
 
 	DQUOT_INIT(dir);
-	error = dir->i_op->symlink(dir, dentry, oldname);
+	error = dir->i_op->symlink(dir, dentry, oldname, cred);
 	if (!error)
 		fsnotify_create(dir, dentry);
 	return error;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 18cea2c..0dda7bb 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -49,7 +49,8 @@ static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *,
 static int nfs_mkdir(struct inode *, struct dentry *, int, struct cred *);
 static int nfs_rmdir(struct inode *, struct dentry *, struct cred *);
 static int nfs_unlink(struct inode *, struct dentry *, struct cred *);
-static int nfs_symlink(struct inode *, struct dentry *, const char *);
+static int nfs_symlink(struct inode *, struct dentry *, const char *,
+		       struct cred *);
 static int nfs_link(struct dentry *, struct inode *, struct dentry *,
 		    struct cred *);
 static int nfs_mknod(struct inode *, struct dentry *, int, dev_t,
@@ -1539,9 +1540,9 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry,
  * now have a new file handle and can instantiate an in-core NFS inode
  * and move the raw page into its mapping.
  */
-static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+static int nfs_symlink(struct inode *dir, struct dentry *dentry,
+		       const char *symname, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct pagevec lru_pvec;
 	struct page *page;
 	char *kaddr;
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 53e917c..9903253 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -126,9 +126,9 @@ static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	return ramfs_mknod(dir, dentry, mode | S_IFREG, 0, cred);
 }
 
-static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
+static int ramfs_symlink(struct inode * dir, struct dentry *dentry,
+			 const char * symname, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode;
 	int error = -ENOSPC;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7fe8921..e321a7c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1141,7 +1141,8 @@ struct inode_operations {
 	int (*link) (struct dentry *,struct inode *,struct dentry *,
 		     struct cred *);
 	int (*unlink) (struct inode *,struct dentry *, struct cred *);
-	int (*symlink) (struct inode *,struct dentry *,const char *);
+	int (*symlink) (struct inode *,struct dentry *,const char *,
+			struct cred *);
 	int (*mkdir) (struct inode *,struct dentry *,int, struct cred *);
 	int (*rmdir) (struct inode *,struct dentry *, struct cred *);
 	int (*mknod) (struct inode *,struct dentry *,int,dev_t, struct cred *);
diff --git a/mm/shmem.c b/mm/shmem.c
index 9d2ebe2..fc834e7 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1855,9 +1855,9 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry,
 	return 0;
 }
 
-static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+static int shmem_symlink(struct inode *dir, struct dentry *dentry,
+			 const char *symname, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	int error;
 	int len;
 	struct inode *inode;


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

* [PATCH 33/52] CRED: Make the get_parent() export op take a credential pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (31 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 32/52] CRED: Give the symlink() " David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 34/52] CRED: Make Ext3 ACL set handlers pass credentials down David Howells
                   ` (20 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make the get_parent() export op take a credential pointer.

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

 fs/ext3/namei.c          |    3 +--
 fs/ext3/namei.h          |    2 +-
 fs/fat/inode.c           |    2 +-
 include/linux/exportfs.h |    5 +++--
 mm/shmem.c               |    2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index cd0fcde..aa741bb 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1072,9 +1072,8 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
 }
 
 
-struct dentry *ext3_get_parent(struct dentry *child)
+struct dentry *ext3_get_parent(struct dentry *child, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	unsigned long ino;
 	struct dentry *parent;
 	struct inode *inode;
diff --git a/fs/ext3/namei.h b/fs/ext3/namei.h
index f2ce2b0..53d7c59 100644
--- a/fs/ext3/namei.h
+++ b/fs/ext3/namei.h
@@ -5,4 +5,4 @@
  *
 */
 
-extern struct dentry *ext3_get_parent(struct dentry *child);
+extern struct dentry *ext3_get_parent(struct dentry *child, struct cred *cred);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 045647d..519e1b4 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -748,7 +748,7 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
 	return 3;
 }
 
-static struct dentry *fat_get_parent(struct dentry *child)
+static struct dentry *fat_get_parent(struct dentry *child, struct cred *cred)
 {
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 8872fe8..895fd2d 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -73,7 +73,8 @@ struct vfsmount;
  * get_parent:
  *    @get_parent should find the parent directory for the given @child which
  *    is also a directory.  In the event that it cannot be found, or storage
- *    space cannot be allocated, a %ERR_PTR should be returned.
+ *    space cannot be allocated, a %ERR_PTR should be returned.  @cred indicates
+ *    the credentials to be used for the lookup.
  *
  * get_dentry:
  *    Given a &super_block (@sb) and a pointer to a file-system specific inode
@@ -103,7 +104,7 @@ struct export_operations {
 			int connectable);
 	int (*get_name)(struct dentry *parent, char *name,
 			struct dentry *child);
-	struct dentry * (*get_parent)(struct dentry *child);
+	struct dentry * (*get_parent)(struct dentry *child, struct cred *cred);
 	struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
 
 	/* This is set by the exporting module to a standard helper */
diff --git a/mm/shmem.c b/mm/shmem.c
index fc834e7..ee0b20a 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1994,7 +1994,7 @@ static struct xattr_handler *shmem_xattr_handlers[] = {
 };
 #endif
 
-static struct dentry *shmem_get_parent(struct dentry *child)
+static struct dentry *shmem_get_parent(struct dentry *child, struct cred *cred)
 {
 	return ERR_PTR(-ESTALE);
 }


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

* [PATCH 34/52] CRED: Make Ext3 ACL set handlers pass credentials down
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (32 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 33/52] CRED: Make the get_parent() export op take a credential pointer David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 35/52] CRED: Make the ACL set() handler take a credentials pointer David Howells
                   ` (19 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make Ext3 ACL set handlers pass credentials down to lower functions.

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

 fs/ext3/acl.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 1db810a..239efa9 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -483,9 +483,8 @@ ext3_xattr_get_acl_default(struct inode *inode, const char *name,
 
 static int
 ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
-		   size_t size)
+		   size_t size, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	handle_t *handle;
 	struct posix_acl *acl;
 	int error, retries = 0;
@@ -526,18 +525,20 @@ static int
 ext3_xattr_set_acl_access(struct inode *inode, const char *name,
 			  const void *value, size_t size, int flags)
 {
+	struct cred *cred = current->cred;
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
-	return ext3_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
+	return ext3_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size, cred);
 }
 
 static int
 ext3_xattr_set_acl_default(struct inode *inode, const char *name,
 			   const void *value, size_t size, int flags)
 {
+	struct cred *cred = current->cred;
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
-	return ext3_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
+	return ext3_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size, cred);
 }
 
 struct xattr_handler ext3_xattr_acl_access_handler = {


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

* [PATCH 35/52] CRED: Make the ACL set() handler take a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (33 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 34/52] CRED: Make Ext3 ACL set handlers pass credentials down David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 36/52] CRED: Make ext3_fill_super() pass credentials down David Howells
                   ` (18 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make the ACL set() handler take a credentials pointer.

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

 fs/ext3/acl.c            |    8 ++++----
 fs/ext3/xattr_security.c |    5 ++---
 fs/ext3/xattr_trusted.c  |    5 ++---
 fs/ext3/xattr_user.c     |    5 ++---
 fs/xattr.c               |    6 ++++--
 include/linux/xattr.h    |    2 +-
 mm/shmem.c               |    3 ++-
 mm/shmem_acl.c           |    4 ++--
 8 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 239efa9..3122db9 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -523,9 +523,9 @@ release_and_out:
 
 static int
 ext3_xattr_set_acl_access(struct inode *inode, const char *name,
-			  const void *value, size_t size, int flags)
+			  const void *value, size_t size, int flags,
+			  struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 	return ext3_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size, cred);
@@ -533,9 +533,9 @@ ext3_xattr_set_acl_access(struct inode *inode, const char *name,
 
 static int
 ext3_xattr_set_acl_default(struct inode *inode, const char *name,
-			   const void *value, size_t size, int flags)
+			   const void *value, size_t size, int flags,
+			   struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 	return ext3_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size, cred);
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index 9a949e3..351bbb8 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -39,10 +39,9 @@ ext3_xattr_security_get(struct inode *inode, const char *name,
 
 static int
 ext3_xattr_security_set(struct inode *inode, const char *name,
-		       const void *value, size_t size, int flags)
+			const void *value, size_t size, int flags,
+			struct cred *cred)
 {
-	struct cred *cred = current->cred;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY, name,
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index eead225..d086115 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -45,10 +45,9 @@ ext3_xattr_trusted_get(struct inode *inode, const char *name,
 
 static int
 ext3_xattr_trusted_set(struct inode *inode, const char *name,
-		       const void *value, size_t size, int flags)
+		       const void *value, size_t size, int flags,
+		       struct cred *cred)
 {
-	struct cred *cred = current->cred;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index 1aa87ae..afbfc4d 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -45,10 +45,9 @@ ext3_xattr_user_get(struct inode *inode, const char *name,
 
 static int
 ext3_xattr_user_set(struct inode *inode, const char *name,
-		    const void *value, size_t size, int flags)
+		    const void *value, size_t size, int flags,
+		    struct cred *cred)
 {
-	struct cred *cred = current->cred;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
diff --git a/fs/xattr.c b/fs/xattr.c
index a44fd92..7917579 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -587,6 +587,7 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 int
 generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
 {
+	struct cred *cred = current->cred;
 	struct xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
 
@@ -595,7 +596,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
 	handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(inode, name, value, size, flags);
+	return handler->set(inode, name, value, size, flags, cred);
 }
 
 /*
@@ -605,13 +606,14 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
 int
 generic_removexattr(struct dentry *dentry, const char *name)
 {
+	struct cred *cred = current->cred;
 	struct xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
 
 	handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
+	return handler->set(inode, name, NULL, 0, XATTR_REPLACE, cred);
 }
 
 EXPORT_SYMBOL(generic_getxattr);
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index def131a..50c35d9 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -43,7 +43,7 @@ struct xattr_handler {
 	int (*get)(struct inode *inode, const char *name, void *buffer,
 		   size_t size);
 	int (*set)(struct inode *inode, const char *name, const void *buffer,
-		   size_t size, int flags);
+		   size_t size, int flags, struct cred *cred);
 };
 
 ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
diff --git a/mm/shmem.c b/mm/shmem.c
index ee0b20a..ab44c06 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1972,7 +1972,8 @@ static int shmem_xattr_security_get(struct inode *inode, const char *name,
 }
 
 static int shmem_xattr_security_set(struct inode *inode, const char *name,
-				    const void *value, size_t size, int flags)
+				    const void *value, size_t size, int flags,
+				    struct cred *cred)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
index f5664c5..0c7f1f2 100644
--- a/mm/shmem_acl.c
+++ b/mm/shmem_acl.c
@@ -89,7 +89,7 @@ shmem_get_acl_access(struct inode *inode, const char *name, void *buffer,
 
 static int
 shmem_set_acl_access(struct inode *inode, const char *name, const void *value,
-		     size_t size, int flags)
+		     size_t size, int flags, struct cred *cred)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
@@ -130,7 +130,7 @@ shmem_get_acl_default(struct inode *inode, const char *name, void *buffer,
 
 static int
 shmem_set_acl_default(struct inode *inode, const char *name, const void *value,
-		      size_t size, int flags)
+		      size_t size, int flags, struct cred *cred)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;


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

* [PATCH 36/52] CRED: Make ext3_fill_super() pass credentials down
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (34 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 35/52] CRED: Make the ACL set() handler take a credentials pointer David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 37/52] CRED: Pass credentials to the get_sb() op and various fill_super() ops David Howells
                   ` (17 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Make ext3_fill_super() pass credentials down to the functions that it calls.

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

 fs/ext3/super.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 4bb76d3..2be33c1 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1257,9 +1257,9 @@ static int ext3_check_descriptors (struct super_block * sb)
  * inode cleanup for us, so we can safely abort without any further action.
  */
 static void ext3_orphan_cleanup (struct super_block * sb,
-				 struct ext3_super_block * es)
+				 struct ext3_super_block * es,
+				 struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	unsigned int s_flags = sb->s_flags;
 	int nr_orphans = 0, nr_truncates = 0;
 #ifdef CONFIG_QUOTA
@@ -1398,6 +1398,7 @@ static ext3_fsblk_t descriptor_loc(struct super_block *sb,
 
 static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 {
+	struct cred *cred = current->cred;
 	struct buffer_head * bh;
 	struct ext3_super_block *es = NULL;
 	struct ext3_sb_info *sbi;
@@ -1799,7 +1800,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 	 * superblock lock.
 	 */
 	EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;
-	ext3_orphan_cleanup(sb, es);
+	ext3_orphan_cleanup(sb, es, cred);
 	EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;
 	if (needs_recovery)
 		printk (KERN_INFO "EXT3-fs: recovery complete.\n");


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

* [PATCH 37/52] CRED: Pass credentials to the get_sb() op and various fill_super() ops
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (35 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 36/52] CRED: Make ext3_fill_super() pass credentials down David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 38/52] CRED: Pass credentials through the quota_read() op David Howells
                   ` (16 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials to the get_sb() filesystem operation and various fill_super()
operations required by get_sb_*() helpers.

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

 fs/afs/super.c               |    3 ++-
 fs/anon_inodes.c             |    2 +-
 fs/autofs4/autofs_i.h        |    2 +-
 fs/autofs4/init.c            |    6 ++++--
 fs/autofs4/inode.c           |    3 ++-
 fs/binfmt_misc.c             |    8 +++++---
 fs/block_dev.c               |    3 ++-
 fs/devpts/inode.c            |    7 ++++---
 fs/ext3/super.c              |   10 ++++++----
 fs/inotify_user.c            |    3 ++-
 fs/nfs/super.c               |   32 +++++++++++++++++---------------
 fs/pipe.c                    |    2 +-
 fs/proc/inode.c              |    3 ++-
 fs/proc/root.c               |    5 +++--
 fs/ramfs/inode.c             |   14 ++++++++------
 fs/super.c                   |   15 ++++++++-------
 fs/sysfs/mount.c             |    8 +++++---
 fs/vfat/namei.c              |    7 ++++---
 include/linux/fs.h           |    9 +++++----
 include/linux/proc_fs.h      |    2 +-
 include/linux/ramfs.h        |    3 ++-
 kernel/futex.c               |    2 +-
 mm/shmem.c                   |    9 +++++----
 net/socket.c                 |    2 +-
 net/sunrpc/rpc_pipe.c        |    8 +++++---
 security/inode.c             |    7 ++++---
 security/selinux/selinuxfs.c |    7 ++++---
 27 files changed, 105 insertions(+), 77 deletions(-)

diff --git a/fs/afs/super.c b/fs/afs/super.c
index b8808b4..82ccd94 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -31,7 +31,7 @@ static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
 			    unsigned long flags);
 static int afs_get_sb(struct file_system_type *fs_type,
 		      int flags, const char *dev_name,
-		      void *data, struct vfsmount *mnt);
+		      void *data, struct cred *cred, struct vfsmount *mnt);
 static struct inode *afs_alloc_inode(struct super_block *sb);
 static void afs_put_super(struct super_block *sb);
 static void afs_destroy_inode(struct inode *inode);
@@ -352,6 +352,7 @@ static int afs_get_sb(struct file_system_type *fs_type,
 		      int flags,
 		      const char *dev_name,
 		      void *options,
+		      struct cred *cred,
 		      struct vfsmount *mnt)
 {
 	struct afs_mount_params params;
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index de05856..4ee735a 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -27,7 +27,7 @@ static const struct file_operations anon_inode_fops;
 
 static int anon_inodefs_get_sb(struct file_system_type *fs_type, int flags,
 			       const char *dev_name, void *data,
-			       struct vfsmount *mnt)
+			       struct cred *cred, struct vfsmount *mnt)
 {
 	return get_sb_pseudo(fs_type, "anon_inode:", NULL, ANON_INODE_FS_MAGIC,
 			     mnt);
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index d85f42f..41c15fe 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -182,7 +182,7 @@ extern const struct file_operations autofs4_root_operations;
 
 /* Initializing function */
 
-int autofs4_fill_super(struct super_block *, void *, int);
+int autofs4_fill_super(struct super_block *, void *, int, struct cred *);
 struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info *sbi, mode_t mode);
 
 /* Queue management functions */
diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c
index 723a1c5..74a601a 100644
--- a/fs/autofs4/init.c
+++ b/fs/autofs4/init.c
@@ -15,9 +15,11 @@
 #include "autofs_i.h"
 
 static int autofs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt);
+	return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, cred,
+			    mnt);
 }
 
 static struct file_system_type autofs_fs_type = {
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 692364e..437c5c8 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -303,7 +303,8 @@ static struct dentry_operations autofs4_sb_dentry_operations = {
 	.d_release      = autofs4_dentry_release,
 };
 
-int autofs4_fill_super(struct super_block *s, void *data, int silent)
+int autofs4_fill_super(struct super_block *s, void *data, int silent,
+		       struct cred *cred)
 {
 	struct inode * root_inode;
 	struct dentry * root;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 42e94b3..c202450 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -715,7 +715,8 @@ static const struct super_operations s_ops = {
 	.clear_inode	= bm_clear_inode,
 };
 
-static int bm_fill_super(struct super_block * sb, void * data, int silent)
+static int bm_fill_super(struct super_block * sb, void * data, int silent,
+			 struct cred *cred)
 {
 	static struct tree_descr bm_files[] = {
 		[2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
@@ -729,9 +730,10 @@ static int bm_fill_super(struct super_block * sb, void * data, int silent)
 }
 
 static int bm_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, bm_fill_super, mnt);
+	return get_sb_single(fs_type, flags, data, bm_fill_super, cred, mnt);
 }
 
 static struct linux_binfmt misc_format = {
diff --git a/fs/block_dev.c b/fs/block_dev.c
index ef70bba..170c3ea 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -499,7 +499,8 @@ static const struct super_operations bdev_sops = {
 };
 
 static int bd_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
 	return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576, mnt);
 }
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index b6829ab..58c2c99 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -98,7 +98,7 @@ static const struct super_operations devpts_sops = {
 };
 
 static int
-devpts_fill_super(struct super_block *s, void *data, int silent)
+devpts_fill_super(struct super_block *s, void *data, int silent, struct cred *cred)
 {
 	struct inode * inode;
 
@@ -131,9 +131,10 @@ fail:
 }
 
 static int devpts_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
+	return get_sb_single(fs_type, flags, data, devpts_fill_super, cred, mnt);
 }
 
 static struct file_system_type devpts_fs_type = {
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 2be33c1..3b89509 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1396,9 +1396,9 @@ static ext3_fsblk_t descriptor_loc(struct super_block *sb,
 }
 
 
-static int ext3_fill_super (struct super_block *sb, void *data, int silent)
+static int ext3_fill_super (struct super_block *sb, void *data, int silent,
+			    struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct buffer_head * bh;
 	struct ext3_super_block *es = NULL;
 	struct ext3_sb_info *sbi;
@@ -2779,9 +2779,11 @@ out:
 #endif
 
 static int ext3_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super, mnt);
+	return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super,
+			   cred, mnt);
 }
 
 static struct file_system_type ext3_fs_type = {
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 9bf2f6c..0e42196 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -682,7 +682,8 @@ out:
 
 static int
 inotify_get_sb(struct file_system_type *fs_type, int flags,
-	       const char *dev_name, void *data, struct vfsmount *mnt)
+	       const char *dev_name, void *data, struct cred *cred,
+	       struct vfsmount *mnt)
 {
 	return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt);
 }
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 0988df4..44e2583 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -223,9 +223,11 @@ static void nfs_umount_begin(struct vfsmount *, int);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
 static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
-static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
+static int nfs_get_sb(struct file_system_type *, int, const char *, void *,
+		      struct cred *, struct vfsmount *);
 static int nfs_xdev_get_sb(struct file_system_type *fs_type,
-		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+		int flags, const char *dev_name, void *raw_data,
+		struct cred *acred, struct vfsmount *mnt);
 static void nfs_kill_super(struct super_block *);
 
 static struct file_system_type nfs_fs_type = {
@@ -257,11 +259,14 @@ static const struct super_operations nfs_sops = {
 
 #ifdef CONFIG_NFS_V4
 static int nfs4_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+	int flags, const char *dev_name, void *raw_data, struct cred *acred,
+	struct vfsmount *mnt);
 static int nfs4_xdev_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+	int flags, const char *dev_name, void *raw_data, struct cred *acred,
+	struct vfsmount *mnt);
 static int nfs4_referral_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+	int flags, const char *dev_name, void *raw_data, struct cred *acred,
+	struct vfsmount *mnt);
 static void nfs4_kill_super(struct super_block *sb);
 
 static struct file_system_type nfs4_fs_type = {
@@ -1377,9 +1382,9 @@ static int nfs_compare_super(struct super_block *sb, void *data)
 }
 
 static int nfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *raw_data, struct cred *acred,
+	struct vfsmount *mnt)
 {
-	struct cred *acred = current->cred;
 	struct nfs_server *server = NULL;
 	struct super_block *s;
 	struct nfs_fh mntfh;
@@ -1466,9 +1471,8 @@ static void nfs_kill_super(struct super_block *s)
  */
 static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
 			   const char *dev_name, void *raw_data,
-			   struct vfsmount *mnt)
+			   struct cred *acred, struct vfsmount *mnt)
 {
-	struct cred *acred = current->cred;
 	struct nfs_clone_mount *data = raw_data;
 	struct super_block *s;
 	struct nfs_server *server;
@@ -1732,9 +1736,9 @@ out_no_client_address:
  * Get the superblock for an NFS4 mountpoint
  */
 static int nfs4_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *raw_data, struct cred *acred,
+	struct vfsmount *mnt)
 {
-	struct cred *acred = current->cred;
 	struct nfs4_mount_data *data = raw_data;
 	struct super_block *s;
 	struct nfs_server *server;
@@ -1827,9 +1831,8 @@ static void nfs4_kill_super(struct super_block *sb)
  */
 static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
 			    const char *dev_name, void *raw_data,
-			    struct vfsmount *mnt)
+			    struct cred *acred, struct vfsmount *mnt)
 {
-	struct cred *acred = current->cred;
 	struct nfs_clone_mount *data = raw_data;
 	struct super_block *s;
 	struct nfs_server *server;
@@ -1902,9 +1905,8 @@ error_splat_super:
  */
 static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
 				const char *dev_name, void *raw_data,
-				struct vfsmount *mnt)
+				struct cred *acred, struct vfsmount *mnt)
 {
-	struct cred *acred = current->cred;
 	struct nfs_clone_mount *data = raw_data;
 	struct super_block *s;
 	struct nfs_server *server;
diff --git a/fs/pipe.c b/fs/pipe.c
index 5143262..47e7dcf 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1084,7 +1084,7 @@ int do_pipe(int *fd)
  */
 static int pipefs_get_sb(struct file_system_type *fs_type,
 			 int flags, const char *dev_name, void *data,
-			 struct vfsmount *mnt)
+			 struct cred *cred, struct vfsmount *mnt)
 {
 	return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC, mnt);
 }
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 7a563c5..6b56b70 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -446,7 +446,8 @@ out_mod:
 	return NULL;
 }			
 
-int proc_fill_super(struct super_block *s, void *data, int silent)
+int proc_fill_super(struct super_block *s, void *data, int silent,
+		    struct cred *cred)
 {
 	struct inode * root_inode;
 
diff --git a/fs/proc/root.c b/fs/proc/root.c
index cf30466..03bfde1 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -24,7 +24,8 @@
 struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver;
 
 static int proc_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
 	if (proc_mnt) {
 		/* Seed the root directory with a pid so it doesn't need
@@ -37,7 +38,7 @@ static int proc_get_sb(struct file_system_type *fs_type,
 		if (!ei->pid)
 			ei->pid = find_get_pid(1);
 	}
-	return get_sb_single(fs_type, flags, data, proc_fill_super, mnt);
+	return get_sb_single(fs_type, flags, data, proc_fill_super, cred, mnt);
 }
 
 static struct file_system_type proc_fs_type = {
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 9903253..0b8d868 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -165,9 +165,9 @@ static const struct super_operations ramfs_ops = {
 	.drop_inode	= generic_delete_inode,
 };
 
-static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
+static int ramfs_fill_super(struct super_block * sb, void * data, int silent,
+			    struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode * inode;
 	struct dentry * root;
 
@@ -191,16 +191,18 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
 }
 
 int ramfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, ramfs_fill_super, mnt);
+	return get_sb_nodev(fs_type, flags, data, ramfs_fill_super, cred, mnt);
 }
 
 static int rootfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
 	return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,
-			    mnt);
+			    cred, mnt);
 }
 
 static struct file_system_type ramfs_fs_type = {
diff --git a/fs/super.c b/fs/super.c
index fc8ebed..2a90d66 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -728,7 +728,7 @@ static int test_bdev_super(struct super_block *s, void *data)
 
 int get_sb_bdev(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
+	fill_super_t fill_super, struct cred *cred,
 	struct vfsmount *mnt)
 {
 	struct block_device *bdev;
@@ -765,7 +765,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
 		s->s_flags = flags;
 		strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
 		sb_set_blocksize(s, block_size(bdev));
-		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0, cred);
 		if (error) {
 			up_write(&s->s_umount);
 			deactivate_super(s);
@@ -801,7 +801,7 @@ EXPORT_SYMBOL(kill_block_super);
 
 int get_sb_nodev(struct file_system_type *fs_type,
 	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
+	fill_super_t fill_super, struct cred *cred,
 	struct vfsmount *mnt)
 {
 	int error;
@@ -812,7 +812,7 @@ int get_sb_nodev(struct file_system_type *fs_type,
 
 	s->s_flags = flags;
 
-	error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+	error = fill_super(s, data, flags & MS_SILENT ? 1 : 0, cred);
 	if (error) {
 		up_write(&s->s_umount);
 		deactivate_super(s);
@@ -831,7 +831,7 @@ static int compare_single(struct super_block *s, void *p)
 
 int get_sb_single(struct file_system_type *fs_type,
 	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
+	fill_super_t fill_super, struct cred *cred,
 	struct vfsmount *mnt)
 {
 	struct super_block *s;
@@ -842,7 +842,7 @@ int get_sb_single(struct file_system_type *fs_type,
 		return PTR_ERR(s);
 	if (!s->s_root) {
 		s->s_flags = flags;
-		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0, cred);
 		if (error) {
 			up_write(&s->s_umount);
 			deactivate_super(s);
@@ -859,6 +859,7 @@ EXPORT_SYMBOL(get_sb_single);
 struct vfsmount *
 vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
 {
+	struct cred *cred = current->cred;
 	struct vfsmount *mnt;
 	char *secdata = NULL;
 	int error;
@@ -881,7 +882,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
 			goto out_free_secdata;
 	}
 
-	error = type->get_sb(type, flags, name, data, mnt);
+	error = type->get_sb(type, flags, name, data, cred, mnt);
 	if (error < 0)
 		goto out_free_secdata;
 	BUG_ON(!mnt->mnt_sb);
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index fbc7b65..d382ced 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -31,7 +31,8 @@ struct sysfs_dirent sysfs_root = {
 	.s_ino		= 1,
 };
 
-static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
+static int sysfs_fill_super(struct super_block *sb, void *data, int silent,
+			    struct cred *cred)
 {
 	struct inode *inode;
 	struct dentry *root;
@@ -69,9 +70,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
 }
 
 static int sysfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
+	return get_sb_single(fs_type, flags, data, sysfs_fill_super, cred, mnt);
 }
 
 static struct file_system_type sysfs_fs_type = {
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 0502bb3..78a6854 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -1011,7 +1011,8 @@ static const struct inode_operations vfat_dir_inode_operations = {
 	.getattr	= fat_getattr,
 };
 
-static int vfat_fill_super(struct super_block *sb, void *data, int silent)
+static int vfat_fill_super(struct super_block *sb, void *data, int silent,
+			   struct cred *cred)
 {
 	int res;
 
@@ -1029,10 +1030,10 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent)
 
 static int vfat_get_sb(struct file_system_type *fs_type,
 		       int flags, const char *dev_name,
-		       void *data, struct vfsmount *mnt)
+		       void *data, struct cred *cred, struct vfsmount *mnt)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super,
-			   mnt);
+			   cred, mnt);
 }
 
 static struct file_system_type vfat_fs_type = {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e321a7c..53130df 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1301,7 +1301,7 @@ struct file_system_type {
 	const char *name;
 	int fs_flags;
 	int (*get_sb) (struct file_system_type *, int,
-		       const char *, void *, struct vfsmount *);
+		       const char *, void *, struct cred *, struct vfsmount *);
 	void (*kill_sb) (struct super_block *);
 	struct module *owner;
 	struct file_system_type * next;
@@ -1310,17 +1310,18 @@ struct file_system_type {
 	struct lock_class_key s_umount_key;
 };
 
+typedef int (*fill_super_t)(struct super_block *, void *, int, struct cred *);
 extern int get_sb_bdev(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
+	fill_super_t fill_super, struct cred *cred,
 	struct vfsmount *mnt);
 extern int get_sb_single(struct file_system_type *fs_type,
 	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
+	fill_super_t fill_super, struct cred *cred,
 	struct vfsmount *mnt);
 extern int get_sb_nodev(struct file_system_type *fs_type,
 	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
+	fill_super_t fill_super, struct cred *cred,
 	struct vfsmount *mnt);
 void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 20741f6..a297a65 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -125,7 +125,7 @@ extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
 
 extern struct vfsmount *proc_mnt;
-extern int proc_fill_super(struct super_block *,void *,int);
+extern int proc_fill_super(struct super_block *,void *,int, struct cred *);
 extern struct inode *proc_get_inode(struct super_block *, unsigned int, struct proc_dir_entry *);
 
 /*
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index 124b0c3..aaf7c0f 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -4,7 +4,8 @@
 struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev,
 			      struct cred *cred);
 extern int ramfs_get_sb(struct file_system_type *fs_type,
-	 int flags, const char *dev_name, void *data, struct vfsmount *mnt);
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt);
 
 #ifndef CONFIG_MMU
 extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
diff --git a/kernel/futex.c b/kernel/futex.c
index fcc94e7..a69a44d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -2078,7 +2078,7 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
 
 static int futexfs_get_sb(struct file_system_type *fs_type,
 			  int flags, const char *dev_name, void *data,
-			  struct vfsmount *mnt)
+			  struct cred *cred, struct vfsmount *mnt)
 {
 	return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA, mnt);
 }
diff --git a/mm/shmem.c b/mm/shmem.c
index ab44c06..4bcfdb8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2217,9 +2217,9 @@ static void shmem_put_super(struct super_block *sb)
 }
 
 static int shmem_fill_super(struct super_block *sb,
-			    void *data, int silent)
+			    void *data, int silent,
+			    struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode;
 	struct dentry *root;
 	int mode   = S_IRWXUGO | S_ISVTX;
@@ -2436,9 +2436,10 @@ static struct vm_operations_struct shmem_vm_ops = {
 
 
 static int shmem_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+	int flags, const char *dev_name, void *data, struct cred *cred,
+	struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt);
+	return get_sb_nodev(fs_type, flags, data, shmem_fill_super, cred, mnt);
 }
 
 static struct file_system_type tmpfs_fs_type = {
diff --git a/net/socket.c b/net/socket.c
index dc40a5e..c19bd71 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -287,7 +287,7 @@ static struct super_operations sockfs_ops = {
 
 static int sockfs_get_sb(struct file_system_type *fs_type,
 			 int flags, const char *dev_name, void *data,
-			 struct vfsmount *mnt)
+			 struct cred *cred, struct vfsmount *mnt)
 {
 	return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,
 			     mnt);
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index c38cc0d..2f6e630 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -800,7 +800,8 @@ static struct super_operations s_ops = {
 #define RPCAUTH_GSSMAGIC 0x67596969
 
 static int
-rpc_fill_super(struct super_block *sb, void *data, int silent)
+rpc_fill_super(struct super_block *sb, void *data, int silent,
+	       struct cred *cred)
 {
 	struct inode *inode;
 	struct dentry *root;
@@ -831,9 +832,10 @@ out:
 
 static int
 rpc_get_sb(struct file_system_type *fs_type,
-		int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+		int flags, const char *dev_name, void *data, struct cred *cred,
+		struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, rpc_fill_super, mnt);
+	return get_sb_single(fs_type, flags, data, rpc_fill_super, cred, mnt);
 }
 
 static struct file_system_type rpc_pipe_fs_type = {
diff --git a/security/inode.c b/security/inode.c
index 0ea9f41..37cfb40 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -126,7 +126,8 @@ static inline int positive(struct dentry *dentry)
 	return dentry->d_inode && !d_unhashed(dentry);
 }
 
-static int fill_super(struct super_block *sb, void *data, int silent)
+static int fill_super(struct super_block *sb, void *data, int silent,
+		      struct cred *cred)
 {
 	static struct tree_descr files[] = {{""}};
 
@@ -135,9 +136,9 @@ static int fill_super(struct super_block *sb, void *data, int silent)
 
 static int get_sb(struct file_system_type *fs_type,
 		  int flags, const char *dev_name,
-		  void *data, struct vfsmount *mnt)
+		  void *data, struct cred *cred, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, fill_super, mnt);
+	return get_sb_single(fs_type, flags, data, fill_super, cred, mnt);
 }
 
 static struct file_system_type fs_type = {
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 728b631..655bc2d 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1554,7 +1554,8 @@ out:
 	return ret;
 }
 
-static int sel_fill_super(struct super_block * sb, void * data, int silent)
+static int sel_fill_super(struct super_block * sb, void * data, int silent,
+			  struct cred *cred)
 {
 	int ret;
 	struct dentry *dentry;
@@ -1666,9 +1667,9 @@ err:
 
 static int sel_get_sb(struct file_system_type *fs_type,
 		      int flags, const char *dev_name, void *data,
-		      struct vfsmount *mnt)
+		      struct cred *cred, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, sel_fill_super, mnt);
+	return get_sb_single(fs_type, flags, data, sel_fill_super, cred, mnt);
 }
 
 static struct file_system_type sel_fs_type = {


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

* [PATCH 38/52] CRED: Pass credentials through the quota_read() op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (36 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 37/52] CRED: Pass credentials to the get_sb() op and various fill_super() ops David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 39/52] CRED: Pass credentials through the quota_write() op David Howells
                   ` (15 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the quota_read() op.

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

 fs/ext3/super.c    |    5 ++---
 fs/quota_v2.c      |   13 +++++++++----
 include/linux/fs.h |    3 ++-
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 3b89509..208065a 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -615,7 +615,7 @@ static int ext3_write_info(struct super_block *sb, int type);
 static int ext3_quota_on(struct super_block *sb, int type, int format_id, char *path);
 static int ext3_quota_on_mount(struct super_block *sb, int type);
 static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
-			       size_t len, loff_t off);
+			       size_t len, loff_t off, struct cred *cred);
 static ssize_t ext3_quota_write(struct super_block *sb, int type,
 				const char *data, size_t len, loff_t off);
 
@@ -2671,9 +2671,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
  * itself serializes the operations (and noone else should touch the files)
  * we don't have to be afraid of races */
 static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
-			       size_t len, loff_t off)
+			       size_t len, loff_t off, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = sb_dqopt(sb)->files[type];
 	sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
 	int err = 0;
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index c519a58..d4c5ba8 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -28,12 +28,14 @@ typedef char *dqbuf_t;
 /* Check whether given file is really vfsv0 quotafile */
 static int v2_check_quota_file(struct super_block *sb, int type)
 {
+	struct cred *cred = &init_cred;
 	struct v2_disk_dqheader dqhead;
 	ssize_t size;
 	static const uint quota_magics[] = V2_INITQMAGICS;
 	static const uint quota_versions[] = V2_INITQVERSIONS;
  
-	size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
+	size = sb->s_op->quota_read(sb, type, (char *)&dqhead,
+				    sizeof(struct v2_disk_dqheader), 0, cred);
 	if (size != sizeof(struct v2_disk_dqheader)) {
 		printk("quota_v2: failed read expected=%zd got=%zd\n",
 			sizeof(struct v2_disk_dqheader), size);
@@ -48,12 +50,13 @@ static int v2_check_quota_file(struct super_block *sb, int type)
 /* Read information header from quota file */
 static int v2_read_file_info(struct super_block *sb, int type)
 {
+	struct cred *cred = &init_cred;
 	struct v2_disk_dqinfo dinfo;
 	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
 	ssize_t size;
 
 	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
-	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
+	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF, cred);
 	if (size != sizeof(struct v2_disk_dqinfo)) {
 		printk(KERN_WARNING "Can't read info structure on device %s.\n",
 			sb->s_id);
@@ -134,9 +137,10 @@ static inline void freedqbuf(dqbuf_t buf)
 
 static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
 {
+	struct cred *cred = &init_cred;
 	memset(buf, 0, V2_DQBLKSIZE);
 	return sb->s_op->quota_read(sb, type, (char *)buf,
-	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
+	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS, cred);
 }
 
 static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
@@ -603,6 +607,7 @@ static inline loff_t find_dqentry(struct dquot *dquot)
 
 static int v2_read_dquot(struct dquot *dquot)
 {
+	struct cred *cred = &init_cred;
 	int type = dquot->dq_type;
 	loff_t offset;
 	struct v2_disk_dqblk ddquot, empty;
@@ -628,7 +633,7 @@ static int v2_read_dquot(struct dquot *dquot)
 	else {
 		dquot->dq_off = offset;
 		if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
-		    (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
+		    (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset, cred))
 		    != sizeof(struct v2_disk_dqblk)) {
 			if (ret >= 0)
 				ret = -EIO;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 53130df..6d52f69 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1205,7 +1205,8 @@ struct super_operations {
 	int (*show_options)(struct seq_file *, struct vfsmount *);
 	int (*show_stats)(struct seq_file *, struct vfsmount *);
 #ifdef CONFIG_QUOTA
-	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
+	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t,
+			      struct cred *);
 	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
 #endif
 };


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

* [PATCH 39/52] CRED: Pass credentials through the quota_write() op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (37 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 38/52] CRED: Pass credentials through the quota_read() op David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 40/52] CRED: Give the lookup() inode op a credentials pointer David Howells
                   ` (14 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the quota_write() op.

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

 fs/ext3/super.c    |    7 ++++---
 fs/quota_v2.c      |    9 ++++++---
 include/linux/fs.h |    3 ++-
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 208065a..348bb6b 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -617,7 +617,8 @@ static int ext3_quota_on_mount(struct super_block *sb, int type);
 static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
 			       size_t len, loff_t off, struct cred *cred);
 static ssize_t ext3_quota_write(struct super_block *sb, int type,
-				const char *data, size_t len, loff_t off);
+				const char *data, size_t len, loff_t off,
+				struct cred *cred);
 
 static struct dquot_operations ext3_quota_operations = {
 	.initialize	= ext3_dquot_initialize,
@@ -2709,9 +2710,9 @@ static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
 /* Write to quotafile (we know the transaction is already started and has
  * enough credits) */
 static ssize_t ext3_quota_write(struct super_block *sb, int type,
-				const char *data, size_t len, loff_t off)
+				const char *data, size_t len, loff_t off,
+				struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = sb_dqopt(sb)->files[type];
 	sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
 	int err = 0;
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index d4c5ba8..c259bc4 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -74,6 +74,7 @@ static int v2_read_file_info(struct super_block *sb, int type)
 /* Write information header to quota file */
 static int v2_write_file_info(struct super_block *sb, int type)
 {
+	struct cred *cred = &init_cred;
 	struct v2_disk_dqinfo dinfo;
 	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
 	ssize_t size;
@@ -88,7 +89,7 @@ static int v2_write_file_info(struct super_block *sb, int type)
 	dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
 	dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
 	size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
-	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
+	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF, cred);
 	if (size != sizeof(struct v2_disk_dqinfo)) {
 		printk(KERN_WARNING "Can't write info structure on device %s.\n",
 			sb->s_id);
@@ -145,8 +146,9 @@ static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf
 
 static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
 {
+	struct cred *cred = &init_cred;
 	return sb->s_op->quota_write(sb, type, (char *)buf,
-	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
+	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS, cred);
 }
 
 /* Remove empty block from list and return it */
@@ -394,6 +396,7 @@ static inline int dq_insert_tree(struct dquot *dquot)
  */
 static int v2_write_dquot(struct dquot *dquot)
 {
+	struct cred *cred = &init_cred;
 	int type = dquot->dq_type;
 	ssize_t ret;
 	struct v2_disk_dqblk ddquot, empty;
@@ -414,7 +417,7 @@ static int v2_write_dquot(struct dquot *dquot)
 		ddquot.dqb_itime = cpu_to_le64(1);
 	spin_unlock(&dq_data_lock);
 	ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
-	      (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
+	      (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off, cred);
 	if (ret != sizeof(struct v2_disk_dqblk)) {
 		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
 		if (ret >= 0)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6d52f69..88f9e49 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1207,7 +1207,8 @@ struct super_operations {
 #ifdef CONFIG_QUOTA
 	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t,
 			      struct cred *);
-	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t,
+			       loff_t, struct cred *);
 #endif
 };
 


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

* [PATCH 40/52] CRED: Give the lookup() inode op a credentials pointer
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (38 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 39/52] CRED: Pass credentials through the quota_write() op David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 41/52] CRED: Pass credentials through d_revalidate() David Howells
                   ` (13 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Give the lookup() inode op a credentials pointer.

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

 fs/afs/dir.c            |    4 ++--
 fs/afs/mntpt.c          |    6 ++++--
 fs/autofs4/root.c       |    6 ++++--
 fs/bad_inode.c          |    3 ++-
 fs/ext3/namei.c         |    4 ++--
 fs/libfs.c              |    3 ++-
 fs/namei.c              |    6 ++++--
 fs/nfs/dir.c            |   18 +++++++++++-------
 fs/proc/base.c          |   23 +++++++++++++++++------
 fs/proc/generic.c       |    3 ++-
 fs/proc/proc_net.c      |    4 ++--
 fs/proc/proc_sysctl.c   |    2 +-
 fs/proc/root.c          |    6 +++---
 fs/sysfs/dir.c          |    2 +-
 fs/vfat/namei.c         |    2 +-
 include/linux/fs.h      |    6 ++++--
 include/linux/proc_fs.h |    3 ++-
 17 files changed, 64 insertions(+), 37 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 745c8cb..b7bd368 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -20,7 +20,7 @@
 #include "internal.h"
 
 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
-				 struct nameidata *nd);
+				 struct nameidata *nd, struct cred *cred);
 static int afs_dir_open(struct inode *inode, struct file *file);
 static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
 static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
@@ -488,7 +488,7 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
  * look up an entry in a directory
  */
 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
-				 struct nameidata *nd)
+				 struct nameidata *nd, struct cred *cred)
 {
 	struct afs_vnode *vnode;
 	struct afs_fid fid;
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 6f8c96f..21a04c0 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -23,7 +23,8 @@
 
 static struct dentry *afs_mntpt_lookup(struct inode *dir,
 				       struct dentry *dentry,
-				       struct nameidata *nd);
+				       struct nameidata *nd,
+				       struct cred *cred);
 static int afs_mntpt_open(struct inode *inode, struct file *file);
 static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd);
 static void afs_mntpt_expiry_timed_out(struct work_struct *work);
@@ -103,7 +104,8 @@ out:
  */
 static struct dentry *afs_mntpt_lookup(struct inode *dir,
 				       struct dentry *dentry,
-				       struct nameidata *nd)
+				       struct nameidata *nd,
+				       struct cred *cred)
 {
 	_enter("%p,%p{%p{%s},%s}",
 	       dir,
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 50c0ec7..bef0396 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -29,7 +29,8 @@ static int autofs4_dir_open(struct inode *inode, struct file *file);
 static int autofs4_dir_close(struct inode *inode, struct file *file);
 static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
 static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
-static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
+static struct dentry *autofs4_lookup(struct inode *,struct dentry *,
+				     struct nameidata *, struct cred *);
 static void *autofs4_follow_link(struct dentry *, struct nameidata *);
 
 const struct file_operations autofs4_root_operations = {
@@ -566,7 +567,8 @@ next:
 }
 
 /* Lookups in the root directory */
-static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry,
+				     struct nameidata *nd, struct cred *cred)
 {
 	struct autofs_sb_info *sbi;
 	struct dentry *unhashed;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 2e25bfe..e77a80d 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -192,7 +192,8 @@ static int bad_inode_create (struct inode *dir, struct dentry *dentry,
 }
 
 static struct dentry *bad_inode_lookup(struct inode *dir,
-			struct dentry *dentry, struct nameidata *nd)
+			struct dentry *dentry, struct nameidata *nd,
+			struct cred *cred)
 {
 	return ERR_PTR(-EIO);
 }
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index aa741bb..3b17b59 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1044,9 +1044,9 @@ errout:
 }
 #endif
 
-static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry,
+				  struct nameidata *nd, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode * inode;
 	struct ext3_dir_entry_2 * de;
 	struct buffer_head * bh;
diff --git a/fs/libfs.c b/fs/libfs.c
index 6b41090..107412e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -41,7 +41,8 @@ static int simple_delete_dentry(struct dentry *dentry)
  * Lookup the data. This is trivial - if the dentry didn't already
  * exist, we know it is negative.  Set d_op to delete negative dentries.
  */
-struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry,
+			     struct nameidata *nd, struct cred *cred)
 {
 	static struct dentry_operations simple_dentry_operations = {
 		.d_delete = simple_delete_dentry,
diff --git a/fs/namei.c b/fs/namei.c
index 9439e6e..cac57e2 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -469,6 +469,7 @@ ok:
  */
 static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	struct dentry * result;
 	struct inode *dir = parent->d_inode;
 
@@ -492,7 +493,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
 		struct dentry * dentry = d_alloc(parent, name);
 		result = ERR_PTR(-ENOMEM);
 		if (dentry) {
-			result = dir->i_op->lookup(dir, dentry, nd);
+			result = dir->i_op->lookup(dir, dentry, nd, cred);
 			if (result)
 				dput(dentry);
 			else
@@ -1275,6 +1276,7 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
 
 static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	struct dentry *dentry;
 	struct inode *inode;
 	int err;
@@ -1298,7 +1300,7 @@ static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry
 		dentry = ERR_PTR(-ENOMEM);
 		if (!new)
 			goto out;
-		dentry = inode->i_op->lookup(inode, new, nd);
+		dentry = inode->i_op->lookup(inode, new, nd, cred);
 		if (!dentry)
 			dentry = new;
 		else
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 0dda7bb..11dae6d 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -43,7 +43,8 @@
 
 static int nfs_opendir(struct inode *, struct file *);
 static int nfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry *nfs_lookup(struct inode *, struct dentry *,
+				 struct nameidata *, struct cred *);
 static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *,
 		      struct cred *);
 static int nfs_mkdir(struct inode *, struct dentry *, int, struct cred *);
@@ -107,7 +108,8 @@ const struct inode_operations nfs3_dir_inode_operations = {
 
 #ifdef CONFIG_NFS_V4
 
-static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *,
+					struct nameidata *, struct cred *);
 const struct inode_operations nfs4_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_atomic_lookup,
@@ -919,9 +921,9 @@ static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fatt
 	return 0;
 }
 
-static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry,
+				 struct nameidata *nd, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct dentry *res;
 	struct inode *inode = NULL;
 	int error;
@@ -1016,9 +1018,11 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd)
 	return 1;
 }
 
-static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *nfs_atomic_lookup(struct inode *dir,
+					struct dentry *dentry,
+					struct nameidata *nd,
+					struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct dentry *res = NULL;
 	int error;
 
@@ -1083,7 +1087,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 out:
 	return res;
 no_open:
-	return nfs_lookup(dir, dentry, nd);
+	return nfs_lookup(dir, dentry, nd, acred);
 }
 
 static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index c7f9940..26f27e5 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1445,7 +1445,7 @@ out_no_task:
 }
 
 static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
-				    struct nameidata *nd)
+				    struct nameidata *nd, struct cred *cred)
 {
 	return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
 }
@@ -1528,7 +1528,8 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
 
 static struct dentry *proc_lookupfdinfo(struct inode *dir,
 					struct dentry *dentry,
-					struct nameidata *nd)
+					struct nameidata *nd,
+					struct cred *cred)
 {
 	return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
 }
@@ -1773,7 +1774,8 @@ static const struct file_operations proc_attr_dir_operations = {
 };
 
 static struct dentry *proc_attr_dir_lookup(struct inode *dir,
-				struct dentry *dentry, struct nameidata *nd)
+				struct dentry *dentry, struct nameidata *nd,
+				struct cred *cred)
 {
 	return proc_pident_lookup(dir, dentry,
 				  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
@@ -2112,7 +2114,11 @@ static const struct file_operations proc_tgid_base_operations = {
 	.readdir	= proc_tgid_base_readdir,
 };
 
-static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
+static struct dentry *proc_tgid_base_lookup(struct inode *dir,
+					    struct dentry *dentry,
+					    struct nameidata *nd,
+					    struct cred *cred)
+{
 	return proc_pident_lookup(dir, dentry,
 				  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
 }
@@ -2387,7 +2393,11 @@ static int proc_tid_base_readdir(struct file * filp,
 				   tid_base_stuff,ARRAY_SIZE(tid_base_stuff));
 }
 
-static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
+static struct dentry *proc_tid_base_lookup(struct inode *dir,
+					   struct dentry *dentry,
+					   struct nameidata *nd,
+					   struct cred *cred)
+{
 	return proc_pident_lookup(dir, dentry,
 				  tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
 }
@@ -2431,7 +2441,8 @@ out:
 	return error;
 }
 
-static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *proc_task_lookup(struct inode *dir, struct dentry *dentry,
+				       struct nameidata *nd, struct cred *cred)
 {
 	struct dentry *result = ERR_PTR(-ENOENT);
 	struct task_struct *task;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 00a2192..ef5fb3a 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -384,7 +384,8 @@ static struct dentry_operations proc_dentry_operations =
  * Don't create negative dentries here, return -ENOENT by hand
  * instead.
  */
-struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry,
+			   struct nameidata *nd, struct cred *cred)
 {
 	struct inode *inode = NULL;
 	struct proc_dir_entry * de;
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 3011c08..a1a2fa9 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -101,7 +101,7 @@ static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd)
 }
 
 static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry,
-				      struct nameidata *nd)
+				      struct nameidata *nd, struct cred *cred)
 {
 	struct net *net = current->nsproxy->net_ns;
 	struct dentry *shadow;
@@ -113,7 +113,7 @@ static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry,
 	dput(nd->dentry);
 	nd->dentry = shadow;
 
-	return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd);
+	return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd, cred);
 }
 
 static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr,
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 4db895c..b1507e0 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -139,7 +139,7 @@ static struct ctl_table *do_proc_sys_lookup(struct dentry *parent,
 }
 
 static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
-					struct nameidata *nd)
+				      struct nameidata *nd, struct cred *cred)
 {
 	struct ctl_table_header *head;
 	struct inode *inode;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 03bfde1..1693a60 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -91,11 +91,11 @@ static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct
 	return 0;
 }
 
-static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry,
+				       struct nameidata *nd, struct cred *cred)
 {
-	if (!proc_lookup(dir, dentry, nd)) {
+	if (!proc_lookup(dir, dentry, nd, cred))
 		return NULL;
-	}
 	
 	return proc_pid_lookup(dir, dentry, nd);
 }
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 83e76b3..6a4bfb0 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -760,7 +760,7 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd)
 }
 
 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
-				struct nameidata *nd)
+				struct nameidata *nd, struct cred *cred)
 {
 	struct dentry *ret = NULL;
 	struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 78a6854..2fb53fa 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -684,7 +684,7 @@ static int vfat_find(struct inode *dir, struct qstr *qname,
 }
 
 static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
-				  struct nameidata *nd)
+				  struct nameidata *nd, struct cred *cred)
 {
 	struct super_block *sb = dir->i_sb;
 	struct fat_slot_info sinfo;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 88f9e49..8d64b1e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1137,7 +1137,8 @@ struct file_operations {
 struct inode_operations {
 	int (*create) (struct inode *,struct dentry *,int, struct nameidata *,
 		       struct cred *);
-	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+	struct dentry * (*lookup) (struct inode *,struct dentry *,
+				   struct nameidata *, struct cred *);
 	int (*link) (struct dentry *,struct inode *,struct dentry *,
 		     struct cred *);
 	int (*unlink) (struct inode *,struct dentry *, struct cred *);
@@ -1814,7 +1815,8 @@ extern int simple_prepare_write(struct file *file, struct page *page,
 extern int simple_commit_write(struct file *file, struct page *page,
 				unsigned offset, unsigned to);
 
-extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *simple_lookup(struct inode *, struct dentry *,
+				    struct nameidata *, struct cred *);
 extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
 extern const struct file_operations simple_dir_operations;
 extern const struct inode_operations simple_dir_inode_operations;
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index a297a65..906c416 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -136,7 +136,8 @@ extern struct inode *proc_get_inode(struct super_block *, unsigned int, struct p
  * of the /proc/<pid> subdirectories.
  */
 extern int proc_readdir(struct file *, void *, filldir_t);
-extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *proc_lookup(struct inode *, struct dentry *,
+				  struct nameidata *, struct cred *);
 
 extern const struct file_operations proc_kcore_operations;
 extern const struct file_operations proc_kmsg_operations;


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

* [PATCH 41/52] CRED: Pass credentials through d_revalidate()
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (39 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 40/52] CRED: Give the lookup() inode op a credentials pointer David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 42/52] CRED: Pass credentials through the permission() inode op David Howells
                   ` (12 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through d_revalidate().

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

 fs/afs/dir.c            |    6 ++-
 fs/autofs4/root.c       |    8 +++-
 fs/namei.c              |    7 +++-
 fs/nfs/dir.c            |   13 ++++---
 fs/proc/base.c          |   88 +++++++++++++++++++++++++++++------------------
 fs/proc/proc_sysctl.c   |    3 +-
 fs/proc/root.c          |    2 +
 fs/vfat/namei.c         |    3 +-
 include/linux/dcache.h  |    3 +-
 include/linux/proc_fs.h |    3 +-
 10 files changed, 84 insertions(+), 52 deletions(-)

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index b7bd368..d998075 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -23,7 +23,8 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
 				 struct nameidata *nd, struct cred *cred);
 static int afs_dir_open(struct inode *inode, struct file *file);
 static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
-static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
+static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd,
+			    struct cred *cred);
 static int afs_d_delete(struct dentry *dentry);
 static void afs_d_release(struct dentry *dentry);
 static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
@@ -564,7 +565,8 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
  * - NOTE! the hit can be a negative hit too, so we can't assume we have an
  *   inode
  */
-static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd,
+			    struct cred *cred)
 {
 	struct afs_vnode *vnode, *dir;
 	struct afs_fid fid;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index bef0396..fd22c05 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -98,6 +98,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
 {
 	struct dentry *dentry = file->f_path.dentry;
 	struct vfsmount *mnt = file->f_path.mnt;
+	struct cred *cred = file->f_cred;
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 	struct dentry *cursor;
 	int status;
@@ -136,7 +137,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
 			d_invalidate(dentry);
 
 		nd.flags = LOOKUP_DIRECTORY;
-		ret = (dentry->d_op->d_revalidate)(dentry, &nd);
+		ret = (dentry->d_op->d_revalidate)(dentry, &nd, cred);
 
 		if (ret <= 0) {
 			if (ret < 0)
@@ -394,7 +395,8 @@ out_error:
  * yet completely filled in, and revalidate has to delay such
  * lookups..
  */
-static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd,
+			      struct cred *cred)
 {
 	struct inode *dir = dentry->d_parent->d_inode;
 	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
@@ -633,7 +635,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry,
 
 	if (dentry->d_op && dentry->d_op->d_revalidate) {
 		mutex_unlock(&dir->i_mutex);
-		(dentry->d_op->d_revalidate)(dentry, nd);
+		(dentry->d_op->d_revalidate)(dentry, nd, cred);
 		mutex_lock(&dir->i_mutex);
 	}
 
diff --git a/fs/namei.c b/fs/namei.c
index cac57e2..e9e45ac 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -378,7 +378,8 @@ void release_open_intent(struct nameidata *nd)
 static inline struct dentry *
 do_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	int status = dentry->d_op->d_revalidate(dentry, nd);
+	struct cred *cred = current->cred;
+	int status = dentry->d_op->d_revalidate(dentry, nd, cred);
 	if (unlikely(status <= 0)) {
 		/*
 		 * The dentry failed validation.
@@ -811,6 +812,7 @@ fail:
  */
 static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	struct path next;
 	struct inode *inode;
 	int err;
@@ -980,7 +982,8 @@ return_reval:
 		    (nd->dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) {
 			err = -ESTALE;
 			/* Note: we do not d_invalidate() */
-			if (!nd->dentry->d_op->d_revalidate(nd->dentry, nd))
+			if (!nd->dentry->d_op->d_revalidate(nd->dentry, nd,
+							    cred))
 				break;
 		}
 return_base:
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 11dae6d..48a8935 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -762,9 +762,9 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
  * If the parent directory is seen to have changed, we throw out the
  * cached dentry and do a new lookup.
  */
-static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
+static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd,
+				 struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *dir;
 	struct inode *inode;
 	struct dentry *parent;
@@ -993,7 +993,8 @@ out:
 }
 
 #ifdef CONFIG_NFS_V4
-static int nfs_open_revalidate(struct dentry *, struct nameidata *);
+static int nfs_open_revalidate(struct dentry *, struct nameidata *,
+			       struct cred *);
 
 struct dentry_operations nfs4_dentry_operations = {
 	.d_revalidate	= nfs_open_revalidate,
@@ -1090,9 +1091,9 @@ no_open:
 	return nfs_lookup(dir, dentry, nd, acred);
 }
 
-static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd,
+			       struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct dentry *parent = NULL;
 	struct inode *inode = dentry->d_inode;
 	struct inode *dir;
@@ -1138,7 +1139,7 @@ no_open:
 	dput(parent);
 	if (inode != NULL && nfs_have_delegation(inode, FMODE_READ))
 		return 1;
-	return nfs_lookup_revalidate(dentry, nd);
+	return nfs_lookup_revalidate(dentry, nd, acred);
 }
 #endif /* CONFIG_NFSV4 */
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 26f27e5..3034e02 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1101,7 +1101,8 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
  * made this apply to all per process world readable and executable
  * directories.
  */
-static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int pid_revalidate(struct dentry *dentry, struct nameidata *nd,
+			  struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct task_struct *task = get_proc_task(inode);
@@ -1141,7 +1142,8 @@ static struct dentry_operations pid_dentry_operations =
 /* Lookups */
 
 typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
-				struct task_struct *, const void *);
+				struct task_struct *, const void *,
+				struct cred *);
 
 /*
  * Fill a directory entry.
@@ -1174,7 +1176,8 @@ static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
 		struct dentry *new;
 		new = d_alloc(dir, &qname);
 		if (new) {
-			child = instantiate(dir->d_inode, new, task, ptr);
+			child = instantiate(dir->d_inode, new, task, ptr,
+					    filp->f_cred);
 			if (child)
 				dput(new);
 			else
@@ -1267,7 +1270,8 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry,
 	return proc_fd_info(inode, dentry, mnt, NULL);
 }
 
-static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd,
+			     struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct task_struct *task = get_proc_task(inode);
@@ -1309,7 +1313,8 @@ static struct dentry_operations tid_fd_dentry_operations =
 };
 
 static struct dentry *proc_fd_instantiate(struct inode *dir,
-	struct dentry *dentry, struct task_struct *task, const void *ptr)
+	struct dentry *dentry, struct task_struct *task, const void *ptr,
+	struct cred *cred)
 {
 	unsigned fd = *(const unsigned *)ptr;
 	struct file *file;
@@ -1349,7 +1354,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
 	dentry->d_op = &tid_fd_dentry_operations;
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
-	if (tid_fd_revalidate(dentry, NULL))
+	if (tid_fd_revalidate(dentry, NULL, cred))
 		error = NULL;
 
  out:
@@ -1364,7 +1369,8 @@ out_iput:
 
 static struct dentry *proc_lookupfd_common(struct inode *dir,
 					   struct dentry *dentry,
-					   instantiate_t instantiate)
+					   instantiate_t instantiate,
+					   struct cred *cred)
 {
 	struct task_struct *task = get_proc_task(dir);
 	unsigned fd = name_to_int(dentry);
@@ -1375,7 +1381,7 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
 	if (fd == ~0U)
 		goto out;
 
-	result = instantiate(dir, dentry, task, &fd);
+	result = instantiate(dir, dentry, task, &fd, cred);
 out:
 	put_task_struct(task);
 out_no_task:
@@ -1447,7 +1453,7 @@ out_no_task:
 static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
 				    struct nameidata *nd, struct cred *cred)
 {
-	return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
+	return proc_lookupfd_common(dir, dentry, proc_fd_instantiate, cred);
 }
 
 static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir)
@@ -1502,7 +1508,8 @@ static const struct inode_operations proc_fd_inode_operations = {
 };
 
 static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
-	struct dentry *dentry, struct task_struct *task, const void *ptr)
+	struct dentry *dentry, struct task_struct *task, const void *ptr,
+	struct cred *cred)
 {
 	unsigned fd = *(unsigned *)ptr;
  	struct inode *inode;
@@ -1519,7 +1526,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
 	dentry->d_op = &tid_fd_dentry_operations;
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
-	if (tid_fd_revalidate(dentry, NULL))
+	if (tid_fd_revalidate(dentry, NULL, cred))
 		error = NULL;
 
  out:
@@ -1531,7 +1538,7 @@ static struct dentry *proc_lookupfdinfo(struct inode *dir,
 					struct nameidata *nd,
 					struct cred *cred)
 {
-	return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
+	return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate, cred);
 }
 
 static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
@@ -1555,7 +1562,8 @@ static const struct inode_operations proc_fdinfo_inode_operations = {
 
 
 static struct dentry *proc_pident_instantiate(struct inode *dir,
-	struct dentry *dentry, struct task_struct *task, const void *ptr)
+	struct dentry *dentry, struct task_struct *task, const void *ptr,
+	struct cred *cred)
 {
 	const struct pid_entry *p = ptr;
 	struct inode *inode;
@@ -1578,7 +1586,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir,
 	dentry->d_op = &pid_dentry_operations;
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
-	if (pid_revalidate(dentry, NULL))
+	if (pid_revalidate(dentry, NULL, cred))
 		error = NULL;
 out:
 	return error;
@@ -1587,7 +1595,8 @@ out:
 static struct dentry *proc_pident_lookup(struct inode *dir, 
 					 struct dentry *dentry,
 					 const struct pid_entry *ents,
-					 unsigned int nents)
+					 unsigned int nents,
+					 struct cred *cred)
 {
 	struct inode *inode;
 	struct dentry *error;
@@ -1614,7 +1623,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
 	if (p > last)
 		goto out;
 
-	error = proc_pident_instantiate(dir, dentry, task, p);
+	error = proc_pident_instantiate(dir, dentry, task, p, cred);
 out:
 	put_task_struct(task);
 out_no_task:
@@ -1672,7 +1681,8 @@ static int proc_pident_readdir(struct file *filp,
 		p = ents + i;
 		last = &ents[nents - 1];
 		while (p <= last) {
-			if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0)
+			if (proc_pident_fill_cache(filp, dirent, filldir, task,
+						   p) < 0)
 				goto out;
 			filp->f_pos++;
 			p++;
@@ -1762,7 +1772,7 @@ static const struct pid_entry attr_dir_stuff[] = {
 };
 
 static int proc_attr_dir_readdir(struct file * filp,
-			     void * dirent, filldir_t filldir)
+			    void * dirent, filldir_t filldir)
 {
 	return proc_pident_readdir(filp,dirent,filldir,
 				   attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff));
@@ -1778,7 +1788,8 @@ static struct dentry *proc_attr_dir_lookup(struct inode *dir,
 				struct cred *cred)
 {
 	return proc_pident_lookup(dir, dentry,
-				  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
+				  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff),
+				  cred);
 }
 
 static const struct inode_operations proc_attr_dir_inode_operations = {
@@ -1914,7 +1925,8 @@ static const struct pid_entry proc_base_stuff[] = {
  * directory. In this case, however, we can do it - no aliasing problems
  * due to the way we treat inodes.
  */
-static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd,
+				struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct task_struct *task = get_proc_task(inode);
@@ -1933,7 +1945,8 @@ static struct dentry_operations proc_base_dentry_operations =
 };
 
 static struct dentry *proc_base_instantiate(struct inode *dir,
-	struct dentry *dentry, struct task_struct *task, const void *ptr)
+	struct dentry *dentry, struct task_struct *task, const void *ptr,
+	struct cred *cred)
 {
 	const struct pid_entry *p = ptr;
 	struct inode *inode;
@@ -1979,7 +1992,8 @@ out_iput:
 	goto out;
 }
 
-static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry,
+				       struct cred *cred)
 {
 	struct dentry *error;
 	struct task_struct *task = get_proc_task(dir);
@@ -2001,7 +2015,7 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
 	if (p > last)
 		goto out;
 
-	error = proc_base_instantiate(dir, dentry, task, p);
+	error = proc_base_instantiate(dir, dentry, task, p, cred);
 
 out:
 	put_task_struct(task);
@@ -2103,7 +2117,7 @@ static const struct pid_entry tgid_base_stuff[] = {
 };
 
 static int proc_tgid_base_readdir(struct file * filp,
-			     void * dirent, filldir_t filldir)
+			    void * dirent, filldir_t filldir)
 {
 	return proc_pident_readdir(filp,dirent,filldir,
 				   tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
@@ -2120,7 +2134,8 @@ static struct dentry *proc_tgid_base_lookup(struct inode *dir,
 					    struct cred *cred)
 {
 	return proc_pident_lookup(dir, dentry,
-				  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
+				  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff),
+				  cred);
 }
 
 static const struct inode_operations proc_tgid_base_inode_operations = {
@@ -2198,7 +2213,9 @@ out:
 
 static struct dentry *proc_pid_instantiate(struct inode *dir,
 					   struct dentry * dentry,
-					   struct task_struct *task, const void *ptr)
+					   struct task_struct *task,
+					   const void *ptr,
+					   struct cred *cred)
 {
 	struct dentry *error = ERR_PTR(-ENOENT);
 	struct inode *inode;
@@ -2220,19 +2237,20 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
 
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
-	if (pid_revalidate(dentry, NULL))
+	if (pid_revalidate(dentry, NULL, cred))
 		error = NULL;
 out:
 	return error;
 }
 
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry,
+			       struct nameidata *nd, struct cred *cred)
 {
 	struct dentry *result = ERR_PTR(-ENOENT);
 	struct task_struct *task;
 	unsigned tgid;
 
-	result = proc_base_lookup(dir, dentry);
+	result = proc_base_lookup(dir, dentry, cred);
 	if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT)
 		goto out;
 
@@ -2248,7 +2266,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
 	if (!task)
 		goto out;
 
-	result = proc_pid_instantiate(dir, dentry, task, NULL);
+	result = proc_pid_instantiate(dir, dentry, task, NULL, cred);
 	put_task_struct(task);
 out:
 	return result;
@@ -2399,7 +2417,8 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir,
 					   struct cred *cred)
 {
 	return proc_pident_lookup(dir, dentry,
-				  tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
+				  tid_base_stuff, ARRAY_SIZE(tid_base_stuff),
+				  cred);
 }
 
 static const struct file_operations proc_tid_base_operations = {
@@ -2414,7 +2433,8 @@ static const struct inode_operations proc_tid_base_inode_operations = {
 };
 
 static struct dentry *proc_task_instantiate(struct inode *dir,
-	struct dentry *dentry, struct task_struct *task, const void *ptr)
+	struct dentry *dentry, struct task_struct *task, const void *ptr,
+	struct cred *cred)
 {
 	struct dentry *error = ERR_PTR(-ENOENT);
 	struct inode *inode;
@@ -2435,7 +2455,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
 
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
-	if (pid_revalidate(dentry, NULL))
+	if (pid_revalidate(dentry, NULL, cred))
 		error = NULL;
 out:
 	return error;
@@ -2466,7 +2486,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry *dentry,
 	if (leader->tgid != task->tgid)
 		goto out_drop_task;
 
-	result = proc_task_instantiate(dir, dentry, task, NULL);
+	result = proc_task_instantiate(dir, dentry, task, NULL, cred);
 out_drop_task:
 	put_task_struct(task);
 out:
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index b1507e0..e1de8ae 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -451,7 +451,8 @@ static struct inode_operations proc_sys_inode_operations = {
 	.setattr	= proc_sys_setattr,
 };
 
-static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd,
+			       struct cred *cred)
 {
 	struct ctl_table_header *head;
 	struct ctl_table *table;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 1693a60..4e3a6c7 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -97,7 +97,7 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
 	if (!proc_lookup(dir, dentry, nd, cred))
 		return NULL;
 	
-	return proc_pid_lookup(dir, dentry, nd);
+	return proc_pid_lookup(dir, dentry, nd, cred);
 }
 
 static int proc_root_readdir(struct file * filp,
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 2fb53fa..c26c94f 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -25,7 +25,8 @@
 #include <linux/buffer_head.h>
 #include <linux/namei.h>
 
-static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd,
+			   struct cred *cred)
 {
 	int ret = 1;
 
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index aab53df..804c662 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -11,6 +11,7 @@
 
 struct nameidata;
 struct vfsmount;
+struct cred;
 
 /*
  * linux/include/linux/dcache.h
@@ -127,7 +128,7 @@ enum dentry_d_lock_class
 };
 
 struct dentry_operations {
-	int (*d_revalidate)(struct dentry *, struct nameidata *);
+	int (*d_revalidate)(struct dentry *, struct nameidata *, struct cred *);
 	int (*d_hash) (struct dentry *, struct qstr *);
 	int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
 	int (*d_delete)(struct dentry *);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 906c416..d15dd5e 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -110,7 +110,8 @@ extern void proc_misc_init(void);
 struct mm_struct;
 
 void proc_flush_task(struct task_struct *task);
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
+struct dentry *proc_pid_lookup(struct inode *, struct dentry *,
+			       struct nameidata *, struct cred *);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
 unsigned long task_vsize(struct mm_struct *);
 int task_statm(struct mm_struct *, int *, int *, int *, int *);


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

* [PATCH 42/52] CRED: Pass credentials through the permission() inode op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (40 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 41/52] CRED: Pass credentials through d_revalidate() David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:08 ` [PATCH 43/52] CRED: Pass credentials through the statfs() superblock op David Howells
                   ` (11 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the permission() inode operation.

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

 fs/afs/internal.h        |    5 ++---
 fs/afs/security.c        |    5 +++--
 fs/bad_inode.c           |    2 +-
 fs/ext3/acl.c            |    5 +++--
 fs/ext3/acl.h            |    3 ++-
 fs/namei.c               |   14 ++++++++------
 fs/nfs/dir.c             |    6 +++---
 fs/proc/base.c           |    4 ++--
 fs/proc/proc_sysctl.c    |    5 +++--
 include/linux/fs.h       |    7 ++++---
 include/linux/nfs_fs.h   |    3 ++-
 include/linux/shmem_fs.h |    2 +-
 mm/shmem_acl.c           |    5 +++--
 13 files changed, 37 insertions(+), 29 deletions(-)

diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index cac5092..09b440e 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -469,8 +469,6 @@ extern bool afs_cm_incoming_call(struct afs_call *);
 extern const struct inode_operations afs_dir_inode_operations;
 extern const struct file_operations afs_dir_file_operations;
 
-extern int afs_permission(struct inode *, int, struct nameidata *);
-
 /*
  * file.c
  */
@@ -607,7 +605,8 @@ extern void afs_clear_permits(struct afs_vnode *);
 extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
 extern void afs_zap_permits(struct rcu_head *);
 extern struct key *afs_request_key(struct afs_cell *);
-extern int afs_permission(struct inode *, int, struct nameidata *);
+extern int afs_permission(struct inode *, int, struct nameidata *,
+			  struct cred *);
 
 /*
  * server.c
diff --git a/fs/afs/security.c b/fs/afs/security.c
index 9446a1f..ad217c5 100644
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -284,7 +284,8 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key,
  * - AFS ACLs are attached to directories only, and a file is controlled by its
  *   parent directory's ACL
  */
-int afs_permission(struct inode *inode, int mask, struct nameidata *nd)
+int afs_permission(struct inode *inode, int mask, struct nameidata *nd,
+		   struct cred *cred)
 {
 	struct afs_vnode *vnode = AFS_FS_I(inode);
 	afs_access_t access;
@@ -346,7 +347,7 @@ int afs_permission(struct inode *inode, int mask, struct nameidata *nd)
 	}
 
 	key_put(key);
-	ret = generic_permission(inode, mask, NULL);
+	ret = generic_permission(inode, mask, NULL, cred);
 	_leave(" = %d", ret);
 	return ret;
 
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index e77a80d..93c6283 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -248,7 +248,7 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
 }
 
 static int bad_inode_permission(struct inode *inode, int mask,
-			struct nameidata *nd)
+			struct nameidata *nd, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 3122db9..0f7fd74 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -299,9 +299,10 @@ ext3_check_acl(struct inode *inode, int mask)
 }
 
 int
-ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
+ext3_permission(struct inode *inode, int mask, struct nameidata *nd,
+		struct cred *cred)
 {
-	return generic_permission(inode, mask, ext3_check_acl);
+	return generic_permission(inode, mask, ext3_check_acl, cred);
 }
 
 /*
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index f35ccac..72168ee 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -58,7 +58,8 @@ static inline int ext3_acl_count(size_t size)
 #define EXT3_ACL_NOT_CACHED ((void *)-1)
 
 /* acl.c */
-extern int ext3_permission (struct inode *, int, struct nameidata *);
+extern int ext3_permission (struct inode *, int, struct nameidata *,
+			    struct cred *);
 extern int ext3_acl_chmod (struct inode *, struct cred *);
 extern int ext3_init_acl (handle_t *, struct inode *, struct inode *,
 			  struct cred *);
diff --git a/fs/namei.c b/fs/namei.c
index e9e45ac..1703fd0 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -174,18 +174,19 @@ EXPORT_SYMBOL(putname);
  * @inode:	inode to check access rights for
  * @mask:	right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
  * @check_acl:	optional callback to check for Posix ACLs
+ * @cred:	the credentials to use
  *
  * Used to check for read/write/execute permissions on a file.
  * We use "fsuid" for this, letting us set arbitrary permissions
  * for filesystem access without changing the "normal" uids which
  * are used for other things..
  */
-int generic_permission(struct inode *inode, int mask,
-		int (*check_acl)(struct inode *inode, int mask))
+int generic_permission(struct inode *inode, int mask, check_acl_t check_acl,
+		       struct cred *cred)
 {
 	umode_t			mode = inode->i_mode;
 
-	if (current->cred->uid == inode->i_uid)
+	if (cred->uid == inode->i_uid)
 		mode >>= 6;
 	else {
 		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
@@ -196,7 +197,7 @@ int generic_permission(struct inode *inode, int mask,
 				return error;
 		}
 
-		if (in_group_p(current->cred, inode->i_gid))
+		if (in_group_p(cred, inode->i_gid))
 			mode >>= 3;
 	}
 
@@ -228,6 +229,7 @@ int generic_permission(struct inode *inode, int mask,
 
 int permission(struct inode *inode, int mask, struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	umode_t mode = inode->i_mode;
 	int retval, submask;
 
@@ -260,9 +262,9 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
 	/* Ordinary permission routines do not understand MAY_APPEND. */
 	submask = mask & ~MAY_APPEND;
 	if (inode->i_op && inode->i_op->permission)
-		retval = inode->i_op->permission(inode, submask, nd);
+		retval = inode->i_op->permission(inode, submask, nd, cred);
 	else
-		retval = generic_permission(inode, submask, NULL);
+		retval = generic_permission(inode, submask, NULL, cred);
 	if (retval)
 		return retval;
 
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 48a8935..680249e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1992,9 +1992,9 @@ out:
 	return -EACCES;
 }
 
-int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+int nfs_permission(struct inode *inode, int mask, struct nameidata *nd,
+		   struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct rpc_cred *cred;
 	int res = 0;
 
@@ -2045,7 +2045,7 @@ out:
 out_notsup:
 	res = nfs_revalidate_inode(NFS_SERVER(inode), inode, acred);
 	if (res == 0)
-		res = generic_permission(inode, mask, NULL);
+		res = generic_permission(inode, mask, NULL, acred);
 	unlock_kernel();
 	goto out;
 }
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 3034e02..9262681 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1486,11 +1486,11 @@ static const struct file_operations proc_fd_operations = {
  * access /proc/self/fd after it has executed a setuid().
  */
 static int proc_fd_permission(struct inode *inode, int mask,
-				struct nameidata *nd)
+				struct nameidata *nd, struct cred *cred)
 {
 	int rv;
 
-	rv = generic_permission(inode, mask, NULL);
+	rv = generic_permission(inode, mask, NULL, cred);
 	if (rv == 0)
 		return 0;
 	if (task_pid(current) == proc_pid(inode))
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index e1de8ae..3b8cea8 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -369,7 +369,8 @@ out:
 	return ret;
 }
 
-static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *nd)
+static int proc_sys_permission(struct inode *inode, int mask,
+			       struct nameidata *nd, struct cred *cred)
 {
 	/*
 	 * sysctl entries that are not writeable,
@@ -393,7 +394,7 @@ static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *
 
 	if (current->euid == 0)
 		mode >>= 6;
-	else if (in_group_p(current->cred, 0))
+	else if (in_group_p(cred, 0))
 		mode >>= 3;
 
 	if ((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8d64b1e..658bdc8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1154,7 +1154,8 @@ struct inode_operations {
 	void * (*follow_link) (struct dentry *, struct nameidata *);
 	void (*put_link) (struct dentry *, struct nameidata *, void *);
 	void (*truncate) (struct inode *, struct cred *);
-	int (*permission) (struct inode *, int, struct nameidata *);
+	int (*permission) (struct inode *, int, struct nameidata *,
+			   struct cred *);
 	int (*setattr) (struct dentry *, struct iattr *, struct cred *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -1571,8 +1572,8 @@ extern sector_t bmap(struct inode *, sector_t);
 #endif
 extern int notify_change(struct dentry *, struct iattr *);
 extern int permission(struct inode *, int, struct nameidata *);
-extern int generic_permission(struct inode *, int,
-		int (*check_acl)(struct inode *, int));
+typedef int (*check_acl_t)(struct inode *, int);
+extern int generic_permission(struct inode *, int, check_acl_t, struct cred *);
 
 extern int get_write_access(struct inode *);
 extern int deny_write_access(struct file *);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 670e734..333abc5 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -289,7 +289,8 @@ extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int nfs_permission(struct inode *, int, struct nameidata *);
+extern int nfs_permission(struct inode *, int, struct nameidata *,
+			  struct cred *);
 extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *);
 extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
 extern void nfs_access_zap_cache(struct inode *inode);
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index f3c5189..5db1f0b 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -41,7 +41,7 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
 }
 
 #ifdef CONFIG_TMPFS_POSIX_ACL
-int shmem_permission(struct inode *, int, struct nameidata *);
+int shmem_permission(struct inode *, int, struct nameidata *, struct cred *);
 int shmem_acl_init(struct inode *, struct inode *);
 void shmem_acl_destroy_inode(struct inode *);
 
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
index 0c7f1f2..f78720f 100644
--- a/mm/shmem_acl.c
+++ b/mm/shmem_acl.c
@@ -191,7 +191,8 @@ shmem_check_acl(struct inode *inode, int mask)
  * shmem_permission  -  permission() inode operation
  */
 int
-shmem_permission(struct inode *inode, int mask, struct nameidata *nd)
+shmem_permission(struct inode *inode, int mask, struct nameidata *nd,
+		 struct cred *cred)
 {
-	return generic_permission(inode, mask, shmem_check_acl);
+	return generic_permission(inode, mask, shmem_check_acl, cred);
 }


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

* [PATCH 43/52] CRED: Pass credentials through the statfs() superblock op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (41 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 42/52] CRED: Pass credentials through the permission() inode op David Howells
@ 2007-10-12 16:08 ` David Howells
  2007-10-12 16:09 ` [PATCH 44/52] CRED: Pass credentials through the follow_link() inode op David Howells
                   ` (10 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:08 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the statfs() superblock operation.

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

 fs/afs/super.c     |    6 ++++--
 fs/ext3/super.c    |    6 ++++--
 fs/fat/inode.c     |    3 ++-
 fs/libfs.c         |    2 +-
 fs/nfs/super.c     |    6 +++---
 fs/open.c          |    3 ++-
 include/linux/fs.h |    4 ++--
 mm/shmem.c         |    3 ++-
 8 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/fs/afs/super.c b/fs/afs/super.c
index 82ccd94..c7d7c1c 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -35,7 +35,8 @@ static int afs_get_sb(struct file_system_type *fs_type,
 static struct inode *afs_alloc_inode(struct super_block *sb);
 static void afs_put_super(struct super_block *sb);
 static void afs_destroy_inode(struct inode *inode);
-static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
+static int afs_statfs(struct dentry *dentry, struct kstatfs *buf,
+		      struct cred *cred);
 
 struct file_system_type afs_fs_type = {
 	.owner		= THIS_MODULE,
@@ -511,7 +512,8 @@ static void afs_destroy_inode(struct inode *inode)
 /*
  * return information about an AFS volume
  */
-static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
+static int afs_statfs(struct dentry *dentry, struct kstatfs *buf,
+		      struct cred *cred)
 {
 	struct afs_volume_status vs;
 	struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 348bb6b..29a41cc 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -59,7 +59,8 @@ static int ext3_sync_fs(struct super_block *sb, int wait);
 static const char *ext3_decode_error(struct super_block * sb, int errno,
 				     char nbuf[16]);
 static int ext3_remount (struct super_block * sb, int * flags, char * data);
-static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf);
+static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf,
+			struct cred *cred);
 static void ext3_unlockfs(struct super_block *sb);
 static void ext3_write_super (struct super_block * sb);
 static void ext3_write_super_lockfs(struct super_block *sb);
@@ -2429,7 +2430,8 @@ restore_opts:
 	return err;
 }
 
-static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
+static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf,
+			struct cred *cred)
 {
 	struct super_block *sb = dentry->d_sb;
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 519e1b4..a224325 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -537,7 +537,8 @@ static int fat_remount(struct super_block *sb, int *flags, char *data)
 	return 0;
 }
 
-static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
+static int fat_statfs(struct dentry *dentry, struct kstatfs *buf,
+		      struct cred *cred)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
 
diff --git a/fs/libfs.c b/fs/libfs.c
index 107412e..e214329 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -20,7 +20,7 @@ int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	return 0;
 }
 
-int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
+int simple_statfs(struct dentry *dentry, struct kstatfs *buf, struct cred *cred)
 {
 	buf->f_type = dentry->d_sb->s_magic;
 	buf->f_bsize = PAGE_CACHE_SIZE;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 44e2583..524e8a1 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -220,7 +220,7 @@ static match_table_t nfs_secflavor_tokens = {
 
 
 static void nfs_umount_begin(struct vfsmount *, int);
-static int  nfs_statfs(struct dentry *, struct kstatfs *);
+static int  nfs_statfs(struct dentry *, struct kstatfs *, struct cred *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
 static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
 static int nfs_get_sb(struct file_system_type *, int, const char *, void *,
@@ -358,9 +358,9 @@ void __exit unregister_nfs_fs(void)
 /*
  * Deliver file system statistics to userspace
  */
-static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf,
+		      struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct nfs_server *server = NFS_SB(dentry->d_sb);
 	unsigned char blockbits;
 	unsigned long blockres;
diff --git a/fs/open.c b/fs/open.c
index c383efe..291f875 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -30,6 +30,7 @@
 
 int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct cred *cred = current->cred;
 	int retval = -ENODEV;
 
 	if (dentry) {
@@ -39,7 +40,7 @@ int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 			retval = security_sb_statfs(dentry);
 			if (retval)
 				return retval;
-			retval = dentry->d_sb->s_op->statfs(dentry, buf);
+			retval = dentry->d_sb->s_op->statfs(dentry, buf, cred);
 			if (retval == 0 && buf->f_frsize == 0)
 				buf->f_frsize = buf->f_bsize;
 		}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 658bdc8..2fec09a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1199,7 +1199,7 @@ struct super_operations {
 	int (*sync_fs)(struct super_block *sb, int wait);
 	void (*write_super_lockfs) (struct super_block *);
 	void (*unlockfs) (struct super_block *);
-	int (*statfs) (struct dentry *, struct kstatfs *);
+	int (*statfs) (struct dentry *, struct kstatfs *, struct cred *);
 	int (*remount_fs) (struct super_block *, int *, char *);
 	void (*clear_inode) (struct inode *);
 	void (*umount_begin) (struct vfsmount *, int);
@@ -1801,7 +1801,7 @@ extern int dcache_dir_close(struct inode *, struct file *);
 extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
 extern int dcache_readdir(struct file *, void *, filldir_t);
 extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int simple_statfs(struct dentry *, struct kstatfs *);
+extern int simple_statfs(struct dentry *, struct kstatfs *, struct cred *);
 extern int simple_link(struct dentry *, struct inode *, struct dentry *,
 		       struct cred *);
 extern int simple_unlink(struct inode *, struct dentry *, struct cred *);
diff --git a/mm/shmem.c b/mm/shmem.c
index 4bcfdb8..432f023 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1682,7 +1682,8 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count
 	return desc.error;
 }
 
-static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
+static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf,
+			struct cred *cred)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
 


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

* [PATCH 44/52] CRED: Pass credentials through the follow_link() inode op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (42 preceding siblings ...)
  2007-10-12 16:08 ` [PATCH 43/52] CRED: Pass credentials through the statfs() superblock op David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-12 16:09 ` [PATCH 45/52] CRED: Pass credentials through the getattr() " David Howells
                   ` (9 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the follow_link() inode operation.

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

 fs/afs/mntpt.c        |    6 ++++--
 fs/autofs4/root.c     |    6 ++++--
 fs/autofs4/symlink.c  |    3 ++-
 fs/ext3/symlink.c     |    3 ++-
 fs/namei.c            |    9 ++++++---
 fs/nfs/namespace.c    |    5 +++--
 fs/nfs/symlink.c      |    4 ++--
 fs/proc/base.c        |    6 ++++--
 fs/proc/generic.c     |    3 ++-
 fs/proc/proc_net.c    |    3 ++-
 fs/sysfs/dir.c        |    2 +-
 fs/sysfs/symlink.c    |    3 ++-
 include/linux/fs.h    |    6 ++++--
 include/linux/sysfs.h |    6 ++++--
 mm/shmem.c            |    7 +++++--
 15 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 21a04c0..864255e 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -26,7 +26,8 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir,
 				       struct nameidata *nd,
 				       struct cred *cred);
 static int afs_mntpt_open(struct inode *inode, struct file *file);
-static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd);
+static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd,
+				   struct cred *cred);
 static void afs_mntpt_expiry_timed_out(struct work_struct *work);
 
 const struct file_operations afs_mntpt_file_operations = {
@@ -212,7 +213,8 @@ error:
 /*
  * follow a link from a mountpoint directory, thus causing it to be mounted
  */
-static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd,
+				   struct cred *cred)
 {
 	struct vfsmount *newmnt;
 	int err;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index fd22c05..5ee7e2d 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -31,7 +31,8 @@ static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t fill
 static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
 static struct dentry *autofs4_lookup(struct inode *,struct dentry *,
 				     struct nameidata *, struct cred *);
-static void *autofs4_follow_link(struct dentry *, struct nameidata *);
+static void *autofs4_follow_link(struct dentry *, struct nameidata *,
+				 struct cred *);
 
 const struct file_operations autofs4_root_operations = {
 	.open		= dcache_dir_open,
@@ -325,7 +326,8 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
 }
 
 /* For autofs direct mounts the follow link triggers the mount */
-static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd,
+				 struct cred *cred)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c
index b4ea829..767d760 100644
--- a/fs/autofs4/symlink.c
+++ b/fs/autofs4/symlink.c
@@ -12,7 +12,8 @@
 
 #include "autofs_i.h"
 
-static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd,
+				 struct cred *cred)
 {
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
 	nd_set_link(nd, (char *)ino->u.symlink);
diff --git a/fs/ext3/symlink.c b/fs/ext3/symlink.c
index ff7b4cc..b56a509 100644
--- a/fs/ext3/symlink.c
+++ b/fs/ext3/symlink.c
@@ -23,7 +23,8 @@
 #include <linux/namei.h>
 #include "xattr.h"
 
-static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd,
+			       struct cred *cred)
 {
 	struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
 	nd_set_link(nd, (char*)ei->i_data);
diff --git a/fs/namei.c b/fs/namei.c
index 1703fd0..d77e045 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -595,6 +595,7 @@ static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
 
 static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
 {
+	struct cred *cred = current->cred;
 	int error;
 	void *cookie;
 	struct dentry *dentry = path->dentry;
@@ -607,7 +608,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
 		dget(dentry);
 	}
 	mntget(path->mnt);
-	cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
+	cookie = dentry->d_inode->i_op->follow_link(dentry, nd, cred);
 	error = PTR_ERR(cookie);
 	if (!IS_ERR(cookie)) {
 		char *s = nd_get_link(nd);
@@ -2682,11 +2683,12 @@ out:
  */
 int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
+	struct cred *cred = current->cred;
 	struct nameidata nd;
 	void *cookie;
 
 	nd.depth = 0;
-	cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
+	cookie = dentry->d_inode->i_op->follow_link(dentry, &nd, cred);
 	if (!IS_ERR(cookie)) {
 		int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
 		if (dentry->d_inode->i_op->put_link)
@@ -2725,7 +2727,8 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 	return res;
 }
 
-void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
+void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd,
+			     struct cred *cred)
 {
 	struct page *page = NULL;
 	nd_set_link(nd, page_getlink(dentry, &page));
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index b8d3576..72f305f 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -85,6 +85,7 @@ Elong:
  * nfs_follow_mountpoint - handle crossing a mountpoint on the server
  * @dentry - dentry of mountpoint
  * @nd - nameidata info
+ * @acred - the credentials to use
  *
  * When we encounter a mountpoint on the server, we want to set up
  * a mountpoint on the client too, to prevent inode numbers from
@@ -94,9 +95,9 @@ Elong:
  * situation, and that different filesystems may want to use
  * different security flavours.
  */
-static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
+static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd,
+				    struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct vfsmount *mnt;
 	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
 	struct dentry *parent;
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index cd1df31..1186339 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -53,10 +53,10 @@ error:
 	return -EIO;
 }
 
-static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd,
+			     struct cred *acred)
 {
 	struct inode *inode = dentry->d_inode;
-	struct cred *acred = current->cred;
 	struct page *page;
 	void *err;
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9262681..d26cf33 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -933,7 +933,8 @@ static const struct file_operations proc_pid_sched_operations = {
 
 #endif
 
-static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd,
+				  struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	int error = -EACCES;
@@ -1896,7 +1897,8 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
 	return vfs_readlink(dentry,buffer,buflen,tmp);
 }
 
-static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd,
+				   struct cred *cred)
 {
 	char tmp[PROC_NUMBUF];
 	sprintf(tmp, "%d", current->tgid);
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index ef5fb3a..ea67aac 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -353,7 +353,8 @@ static void release_inode_number(unsigned int inum)
 	spin_unlock(&proc_inum_lock);
 }
 
-static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd,
+			      struct cred *cred)
 {
 	nd_set_link(nd, PDE(dentry->d_inode)->data);
 	return NULL;
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index a1a2fa9..7062644 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -84,7 +84,8 @@ out_de_put:
 	goto out;
 }
 
-static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd)
+static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd,
+				  struct cred *cred)
 {
 	struct net *net = current->nsproxy->net_ns;
 	struct dentry *shadow;
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 6a4bfb0..96e2fd8 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -1199,7 +1199,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
  */
 
 int sysfs_make_shadowed_dir(struct kobject *kobj,
-	void * (*follow_link)(struct dentry *, struct nameidata *))
+			    sysfs_follow_link_t follow_link)
 {
 	struct dentry *dentry;
 	struct inode *inode;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 4ce687f..34e0e08 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -158,7 +158,8 @@ static int sysfs_getlink(struct dentry *dentry, char * path)
 	return error;
 }
 
-static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd,
+			       struct cred *cred)
 {
 	int error = -ENOMEM;
 	unsigned long page = get_zeroed_page(GFP_KERNEL);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2fec09a..9e7ac7c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1151,7 +1151,8 @@ struct inode_operations {
 		       struct inode *, struct dentry *,
 		       struct cred *);
 	int (*readlink) (struct dentry *, char __user *,int);
-	void * (*follow_link) (struct dentry *, struct nameidata *);
+	void * (*follow_link) (struct dentry *, struct nameidata *,
+			       struct cred *);
 	void (*put_link) (struct dentry *, struct nameidata *, void *);
 	void (*truncate) (struct inode *, struct cred *);
 	int (*permission) (struct inode *, int, struct nameidata *,
@@ -1767,7 +1768,8 @@ extern const struct file_operations generic_ro_fops;
 extern int vfs_readlink(struct dentry *, char __user *, int, const char *);
 extern int vfs_follow_link(struct nameidata *, const char *);
 extern int page_readlink(struct dentry *, char __user *, int);
-extern void *page_follow_link_light(struct dentry *, struct nameidata *);
+extern void *page_follow_link_light(struct dentry *, struct nameidata *,
+				    struct cred *);
 extern void page_put_link(struct dentry *, struct nameidata *, void *);
 extern int __page_symlink(struct inode *inode, const char *symname, int len,
 		gfp_t gfp_mask);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index be8228e..d84c82b 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -20,6 +20,7 @@ struct module;
 struct nameidata;
 struct dentry;
 struct sysfs_dirent;
+struct cred;
 
 /* FIXME
  * The *owner field is no longer used, but leave around
@@ -138,9 +139,10 @@ void sysfs_remove_file_from_group(struct kobject *kobj,
 
 void sysfs_notify(struct kobject * k, char *dir, char *attr);
 
-
+typedef void *(*sysfs_follow_link_t)(struct dentry *, struct nameidata *,
+				     struct cred *);
 extern int sysfs_make_shadowed_dir(struct kobject *kobj,
-	void * (*follow_link)(struct dentry *, struct nameidata *));
+				   sysfs_follow_link_t follow_link);
 extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj);
 extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd);
 
diff --git a/mm/shmem.c b/mm/shmem.c
index 432f023..a3c2007 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1912,13 +1912,16 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry,
 	return 0;
 }
 
-static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
+static void *shmem_follow_link_inline(struct dentry *dentry,
+				      struct nameidata *nd,
+				      struct cred *cred)
 {
 	nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode));
 	return NULL;
 }
 
-static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd,
+			       struct cred *cred)
 {
 	struct page *page = NULL;
 	int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);


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

* [PATCH 45/52] CRED: Pass credentials through the getattr() inode op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (43 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 44/52] CRED: Pass credentials through the follow_link() inode op David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-12 16:09 ` [PATCH 46/52] CRED: Pass credentials through the setxattr() " David Howells
                   ` (8 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the getattr() inode operation.

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

 fs/afs/inode.c           |    2 +-
 fs/afs/internal.h        |    3 ++-
 fs/bad_inode.c           |    2 +-
 fs/fat/file.c            |    3 ++-
 fs/libfs.c               |    2 +-
 fs/nfs/inode.c           |    4 ++--
 fs/proc/base.c           |    6 ++++--
 fs/proc/generic.c        |    2 +-
 fs/proc/root.c           |    4 ++--
 fs/stat.c                |    3 ++-
 include/linux/fs.h       |    6 ++++--
 include/linux/msdos_fs.h |    2 +-
 include/linux/nfs_fs.h   |    3 ++-
 13 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index f6e4dc1..75f8a8f 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -292,7 +292,7 @@ error_unlock:
  * read the attributes of an inode
  */
 int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
-		      struct kstat *stat)
+		struct kstat *stat, struct cred *cred)
 {
 	struct inode *inode;
 
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 09b440e..1b2eeef 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -546,7 +546,8 @@ extern struct inode *afs_iget(struct super_block *, struct key *,
 			      struct afs_callback *);
 extern void afs_zap_data(struct afs_vnode *);
 extern int afs_validate(struct afs_vnode *, struct key *);
-extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+		       struct cred *);
 extern int afs_setattr(struct dentry *, struct iattr *, struct cred *);
 extern void afs_clear_inode(struct inode *);
 
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 93c6283..a891eaa 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -254,7 +254,7 @@ static int bad_inode_permission(struct inode *inode, int mask,
 }
 
 static int bad_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
-			struct kstat *stat)
+			struct kstat *stat, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/fat/file.c b/fs/fat/file.c
index f0b3faa..6e62dd6 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -304,7 +304,8 @@ void fat_truncate(struct inode *inode, struct cred *cred)
 	fat_flush_inodes(inode->i_sb, inode, NULL);
 }
 
-int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat,
+		struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	generic_fillattr(inode, stat);
diff --git a/fs/libfs.c b/fs/libfs.c
index e214329..1699b79 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -12,7 +12,7 @@
 #include <asm/uaccess.h>
 
 int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
-		   struct kstat *stat)
+		   struct kstat *stat, struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	generic_fillattr(inode, stat);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 178979c..b55f803 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -425,9 +425,9 @@ static void nfs_wake_up_inode(struct inode *inode)
 	wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING);
 }
 
-int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat,
+		struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
 	int err;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index d26cf33..3a53ceb 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1064,7 +1064,8 @@ out_unlock:
 	return NULL;
 }
 
-static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		       struct kstat *stat, struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct task_struct *task;
@@ -2640,7 +2641,8 @@ out_no_task:
 	return retval;
 }
 
-static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry,
+			     struct kstat *stat, struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct task_struct *p = get_proc_task(inode);
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index ea67aac..afbba93 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -256,7 +256,7 @@ out:
 }
 
 static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
-			struct kstat *stat)
+			struct kstat *stat, struct cred *cred)
 {
 	struct inode *inode = dentry->d_inode;
 	struct proc_dir_entry *de = PROC_I(inode)->pde;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 4e3a6c7..6025b9d 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -83,8 +83,8 @@ void __init proc_root_init(void)
 	proc_sys_init();
 }
 
-static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
-)
+static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry,
+			     struct kstat *stat, struct cred *cred)
 {
 	generic_fillattr(dentry->d_inode, stat);
 	stat->nlink = proc_root.nlink + nr_processes();
diff --git a/fs/stat.c b/fs/stat.c
index 6851006..0d71257 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -39,6 +39,7 @@ EXPORT_SYMBOL(generic_fillattr);
 
 int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int retval;
 
@@ -47,7 +48,7 @@ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 		return retval;
 
 	if (inode->i_op->getattr)
-		return inode->i_op->getattr(mnt, dentry, stat);
+		return inode->i_op->getattr(mnt, dentry, stat, cred);
 
 	generic_fillattr(inode, stat);
 	return 0;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9e7ac7c..395b272 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1158,7 +1158,8 @@ struct inode_operations {
 	int (*permission) (struct inode *, int, struct nameidata *,
 			   struct cred *);
 	int (*setattr) (struct dentry *, struct iattr *, struct cred *);
-	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+	int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *,
+			struct cred *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
@@ -1802,7 +1803,8 @@ extern int dcache_dir_open(struct inode *, struct file *);
 extern int dcache_dir_close(struct inode *, struct file *);
 extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
 extern int dcache_readdir(struct file *, void *, filldir_t);
-extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+			  struct cred *);
 extern int simple_statfs(struct dentry *, struct kstatfs *, struct cred *);
 extern int simple_link(struct dentry *, struct inode *, struct dentry *,
 		       struct cred *);
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 63a3efc..2276346 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -405,7 +405,7 @@ extern int fat_notify_change(struct dentry * dentry, struct iattr * attr,
 			     struct cred *cred);
 extern void fat_truncate(struct inode *inode, struct cred *cred);
 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
-		       struct kstat *stat);
+		       struct kstat *statm, struct cred *cred);
 
 /* fat/inode.c */
 extern void fat_attach(struct inode *inode, loff_t i_pos);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 333abc5..d26fd56 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -288,7 +288,8 @@ extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
 				struct nfs_fattr *);
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
-extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+		       struct cred *);
 extern int nfs_permission(struct inode *, int, struct nameidata *,
 			  struct cred *);
 extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *);


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

* [PATCH 46/52] CRED: Pass credentials through the setxattr() inode op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (44 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 45/52] CRED: Pass credentials through the getattr() " David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-12 16:09 ` [PATCH 47/52] CRED: Pass credentials through the xattr get() handler David Howells
                   ` (7 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the setxattr() inode operation.

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

 fs/bad_inode.c         |    2 +-
 fs/nfs/nfs3acl.c       |    3 +--
 fs/nfs/nfs4_fs.h       |    3 ++-
 fs/nfs/nfs4proc.c      |    3 +--
 fs/xattr.c             |    8 +++++---
 include/linux/fs.h     |    3 ++-
 include/linux/nfs_fs.h |    2 +-
 include/linux/xattr.h  |    3 ++-
 8 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index a891eaa..d82d101 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -266,7 +266,7 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs,
 }
 
 static int bad_inode_setxattr(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags)
+		const void *value, size_t size, int flags, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 0fefed1..c09da17 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -78,9 +78,8 @@ ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
 }
 
 int nfs3_setxattr(struct dentry *dentry, const char *name,
-	     const void *value, size_t size, int flags)
+	     const void *value, size_t size, int flags, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl;
 	int type, error;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 007329e..ac7c050 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -168,7 +168,8 @@ extern const struct inode_operations nfs4_dir_inode_operations;
 
 /* inode.c */
 extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
-extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t, int);
+extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t,
+			 int, struct cred *);
 extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
 
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c10f3de..a9a88eb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3717,9 +3717,8 @@ out:
 #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
 
 int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
-		size_t buflen, int flags)
+		size_t buflen, int flags, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 
 	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
diff --git a/fs/xattr.c b/fs/xattr.c
index 7917579..257305e 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -71,6 +71,7 @@ int
 vfs_setxattr(struct dentry *dentry, char *name, void *value,
 		size_t size, int flags)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int error;
 
@@ -84,7 +85,8 @@ vfs_setxattr(struct dentry *dentry, char *name, void *value,
 		goto out;
 	error = -EOPNOTSUPP;
 	if (inode->i_op->setxattr) {
-		error = inode->i_op->setxattr(dentry, name, value, size, flags);
+		error = inode->i_op->setxattr(dentry, name, value, size, flags,
+					      cred);
 		if (!error) {
 			fsnotify_xattr(dentry);
 			security_inode_post_setxattr(dentry, name, value,
@@ -585,9 +587,9 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
  * Find the handler for the prefix and dispatch its set() operation.
  */
 int
-generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
+generic_setxattr(struct dentry *dentry, const char *name, const void *value,
+		 size_t size, int flags, struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 395b272..598006c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1160,7 +1160,8 @@ struct inode_operations {
 	int (*setattr) (struct dentry *, struct iattr *, struct cred *);
 	int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *,
 			struct cred *);
-	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+	int (*setxattr) (struct dentry *, const char *,const void *, size_t,
+			 int, struct cred *);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index d26fd56..fbd1af5 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -356,7 +356,7 @@ static inline struct rpc_cred *nfs_file_cred(struct file *file)
 extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
 extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t);
 extern int nfs3_setxattr(struct dentry *, const char *,
-			const void *, size_t, int);
+			const void *, size_t, int, struct cred *);
 extern int nfs3_removexattr (struct dentry *, const char *name);
 #else
 # define nfs3_listxattr NULL
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 50c35d9..dd98be1 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -53,7 +53,8 @@ int vfs_removexattr(struct dentry *, char *);
 
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
-int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
+int generic_setxattr(struct dentry *dentry, const char *name, const void *value,
+		     size_t size, int flags, struct cred *cred);
 int generic_removexattr(struct dentry *dentry, const char *name);
 
 #endif  /*  __KERNEL__  */


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

* [PATCH 47/52] CRED: Pass credentials through the xattr get() handler
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (45 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 46/52] CRED: Pass credentials through the setxattr() " David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-12 16:09 ` [PATCH 48/52] CRED: Pass credentials through the getxattr() inode op David Howells
                   ` (6 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the xattr get() handler.

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

 fs/ext3/acl.c            |    4 ++--
 fs/ext3/xattr_security.c |    2 +-
 fs/ext3/xattr_trusted.c  |    2 +-
 fs/ext3/xattr_user.c     |    2 +-
 fs/xattr.c               |    3 ++-
 include/linux/xattr.h    |    2 +-
 mm/shmem.c               |    3 ++-
 mm/shmem_acl.c           |    4 ++--
 8 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 0f7fd74..0ce1d87 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -466,7 +466,7 @@ ext3_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
 
 static int
 ext3_xattr_get_acl_access(struct inode *inode, const char *name,
-			  void *buffer, size_t size)
+			  void *buffer, size_t size, struct cred *cred)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
@@ -475,7 +475,7 @@ ext3_xattr_get_acl_access(struct inode *inode, const char *name,
 
 static int
 ext3_xattr_get_acl_default(struct inode *inode, const char *name,
-			   void *buffer, size_t size)
+			   void *buffer, size_t size, struct cred *cred)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index 351bbb8..7d01840 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -29,7 +29,7 @@ ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 
 static int
 ext3_xattr_security_get(struct inode *inode, const char *name,
-		       void *buffer, size_t size)
+			void *buffer, size_t size, struct cred *cred)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index d086115..6073729 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -35,7 +35,7 @@ ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 
 static int
 ext3_xattr_trusted_get(struct inode *inode, const char *name,
-		       void *buffer, size_t size)
+		       void *buffer, size_t size, struct cred *cred)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index afbfc4d..f8a7663 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -34,7 +34,7 @@ ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 
 static int
 ext3_xattr_user_get(struct inode *inode, const char *name,
-		    void *buffer, size_t size)
+		    void *buffer, size_t size, struct cred *cred)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/xattr.c b/fs/xattr.c
index 257305e..634f0b1 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -545,13 +545,14 @@ xattr_resolve_name(struct xattr_handler **handlers, const char **name)
 ssize_t
 generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
 {
+	struct cred *cred = current->cred;
 	struct xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
 
 	handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(inode, name, buffer, size);
+	return handler->get(inode, name, buffer, size, cred);
 }
 
 /*
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index dd98be1..a5002eb 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -41,7 +41,7 @@ struct xattr_handler {
 	size_t (*list)(struct inode *inode, char *list, size_t list_size,
 		       const char *name, size_t name_len);
 	int (*get)(struct inode *inode, const char *name, void *buffer,
-		   size_t size);
+		   size_t size, struct cred *cred);
 	int (*set)(struct inode *inode, const char *name, const void *buffer,
 		   size_t size, int flags, struct cred *cred);
 };
diff --git a/mm/shmem.c b/mm/shmem.c
index a3c2007..45cc69e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1967,7 +1967,8 @@ static size_t shmem_xattr_security_list(struct inode *inode, char *list,
 }
 
 static int shmem_xattr_security_get(struct inode *inode, const char *name,
-				    void *buffer, size_t size)
+				    void *buffer, size_t size,
+				    struct cred *cred)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
index f78720f..7685a67 100644
--- a/mm/shmem_acl.c
+++ b/mm/shmem_acl.c
@@ -79,7 +79,7 @@ shmem_list_acl_access(struct inode *inode, char *list, size_t list_size,
 
 static int
 shmem_get_acl_access(struct inode *inode, const char *name, void *buffer,
-		     size_t size)
+		     size_t size, struct cred *cred)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
@@ -120,7 +120,7 @@ shmem_list_acl_default(struct inode *inode, char *list, size_t list_size,
 
 static int
 shmem_get_acl_default(struct inode *inode, const char *name, void *buffer,
-		      size_t size)
+		      size_t size, struct cred *cred)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;


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

* [PATCH 48/52] CRED: Pass credentials through the getxattr() inode op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (46 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 47/52] CRED: Pass credentials through the xattr get() handler David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-12 16:09 ` [PATCH 49/52] CRED: Pass credentials through the xattr list() handler David Howells
                   ` (5 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the getxattr() inode operation.

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

 fs/bad_inode.c           |    2 +-
 fs/nfs/nfs3acl.c         |    3 +--
 fs/nfs/nfs4_fs.h         |    3 ++-
 fs/nfs/nfs4proc.c        |    3 +--
 fs/xattr.c               |    7 ++++---
 include/linux/fs.h       |    3 ++-
 include/linux/nfs_fs.h   |    3 ++-
 include/linux/xattr.h    |    3 ++-
 security/selinux/hooks.c |    9 +++++----
 9 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index d82d101..b310af3 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -272,7 +272,7 @@ static int bad_inode_setxattr(struct dentry *dentry, const char *name,
 }
 
 static ssize_t bad_inode_getxattr(struct dentry *dentry, const char *name,
-			void *buffer, size_t size)
+			void *buffer, size_t size, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index c09da17..0d160be 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -48,9 +48,8 @@ ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
 }
 
 ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
-		void *buffer, size_t size)
+		void *buffer, size_t size, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl;
 	int type, error = 0;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index ac7c050..3f3dc4e 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -167,7 +167,8 @@ extern struct dentry_operations nfs4_dentry_operations;
 extern const struct inode_operations nfs4_dir_inode_operations;
 
 /* inode.c */
-extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
+extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t,
+			     struct cred *);
 extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t,
 			 int, struct cred *);
 extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a9a88eb..8be911a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3736,9 +3736,8 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
  * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported
  * attributes in kernel-managed attribute namespaces. */
 ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
-		size_t buflen)
+		size_t buflen, struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 
 	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
diff --git a/fs/xattr.c b/fs/xattr.c
index 634f0b1..3c9bf2e 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -109,6 +109,7 @@ EXPORT_SYMBOL_GPL(vfs_setxattr);
 ssize_t
 vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int error;
 
@@ -121,7 +122,7 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
 		return error;
 
 	if (inode->i_op->getxattr)
-		error = inode->i_op->getxattr(dentry, name, value, size);
+		error = inode->i_op->getxattr(dentry, name, value, size, cred);
 	else
 		error = -EOPNOTSUPP;
 
@@ -543,9 +544,9 @@ xattr_resolve_name(struct xattr_handler **handlers, const char **name)
  * Find the handler for the prefix and dispatch its get() operation.
  */
 ssize_t
-generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size,
+		 struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 598006c..28f0205 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1162,7 +1162,8 @@ struct inode_operations {
 			struct cred *);
 	int (*setxattr) (struct dentry *, const char *,const void *, size_t,
 			 int, struct cred *);
-	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,
+			     struct cred *);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
 	void (*truncate_range)(struct inode *, loff_t, loff_t);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index fbd1af5..d17ba8c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -354,7 +354,8 @@ static inline struct rpc_cred *nfs_file_cred(struct file *file)
  */
 #ifdef CONFIG_NFS_V3_ACL
 extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
-extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t);
+extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t,
+			     struct cred *);
 extern int nfs3_setxattr(struct dentry *, const char *,
 			const void *, size_t, int, struct cred *);
 extern int nfs3_removexattr (struct dentry *, const char *name);
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index a5002eb..e702226 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -51,7 +51,8 @@ ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
 int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
 int vfs_removexattr(struct dentry *, char *);
 
-ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
+ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer,
+			 size_t size, struct cred *cred);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
 int generic_setxattr(struct dentry *dentry, const char *name, const void *value,
 		     size_t size, int flags, struct cred *cred);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3c3fff3..bcd71b9 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -634,7 +634,8 @@ static int superblock_doinit(struct super_block *sb, void *data)
 			rc = -EOPNOTSUPP;
 			goto out;
 		}
-		rc = inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
+		rc = inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0,
+					   &init_cred);
 		if (rc < 0 && rc != -ENODATA) {
 			if (rc == -EOPNOTSUPP)
 				printk(KERN_WARNING "SELinux: (dev %s, type "
@@ -897,11 +898,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 			goto out_unlock;
 		}
 		rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
-					   context, len);
+					   context, len, &init_cred);
 		if (rc == -ERANGE) {
 			/* Need a larger buffer.  Query for the right size. */
 			rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
-						   NULL, 0);
+						   NULL, 0, &init_cred);
 			if (rc < 0) {
 				dput(dentry);
 				goto out_unlock;
@@ -916,7 +917,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 			}
 			rc = inode->i_op->getxattr(dentry,
 						   XATTR_NAME_SELINUX,
-						   context, len);
+						   context, len, &init_cred);
 		}
 		dput(dentry);
 		if (rc < 0) {


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

* [PATCH 49/52] CRED: Pass credentials through the xattr list() handler
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (47 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 48/52] CRED: Pass credentials through the getxattr() inode op David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-12 16:09 ` [PATCH 50/52] CRED: Pass credentials through the listxattr() inode op David Howells
                   ` (4 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the xattr list() handler.

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

 fs/ext3/acl.c            |    5 +++--
 fs/ext3/xattr.c          |   27 +++++++++++++++++----------
 fs/ext3/xattr.h          |    2 +-
 fs/ext3/xattr_security.c |    2 +-
 fs/ext3/xattr_trusted.c  |    2 +-
 fs/ext3/xattr_user.c     |    2 +-
 fs/xattr.c               |    6 ++++--
 include/linux/xattr.h    |    2 +-
 mm/shmem.c               |    2 +-
 mm/shmem_acl.c           |    4 ++--
 10 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 0ce1d87..b2d676e 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -420,7 +420,7 @@ out:
  */
 static size_t
 ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
-			   const char *name, size_t name_len)
+			   const char *name, size_t name_len, struct cred *cred)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
@@ -433,7 +433,8 @@ ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
 
 static size_t
 ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
-			    const char *name, size_t name_len)
+			    const char *name, size_t name_len,
+			    struct cred *cred)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 3b34cea..464395d 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -145,7 +145,8 @@ ext3_xattr_handler(int name_index)
 ssize_t
 ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-	return ext3_xattr_list(dentry->d_inode, buffer, size);
+	struct cred *cred = current->cred;
+	return ext3_xattr_list(dentry->d_inode, buffer, size, cred);
 }
 
 static int
@@ -331,7 +332,7 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
 
 static int
 ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
-			char *buffer, size_t buffer_size)
+			char *buffer, size_t buffer_size, struct cred *cred)
 {
 	size_t rest = buffer_size;
 
@@ -342,7 +343,8 @@ ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
 		if (handler) {
 			size_t size = handler->list(inode, buffer, rest,
 						    entry->e_name,
-						    entry->e_name_len);
+						    entry->e_name_len,
+						    cred);
 			if (buffer) {
 				if (size > rest)
 					return -ERANGE;
@@ -355,7 +357,8 @@ ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
 }
 
 static int
-ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size,
+		      struct cred *cred)
 {
 	struct buffer_head *bh = NULL;
 	int error;
@@ -381,7 +384,8 @@ ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
 		goto cleanup;
 	}
 	ext3_xattr_cache_insert(bh);
-	error = ext3_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
+	error = ext3_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size,
+					cred);
 
 cleanup:
 	brelse(bh);
@@ -390,7 +394,8 @@ cleanup:
 }
 
 static int
-ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size,
+		      struct cred *cred)
 {
 	struct ext3_xattr_ibody_header *header;
 	struct ext3_inode *raw_inode;
@@ -410,7 +415,7 @@ ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
 	if (error)
 		goto cleanup;
 	error = ext3_xattr_list_entries(inode, IFIRST(header),
-					buffer, buffer_size);
+					buffer, buffer_size, cred);
 
 cleanup:
 	brelse(iloc.bh);
@@ -428,12 +433,13 @@ cleanup:
  * used / required on success.
  */
 int
-ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size,
+		struct cred *cred)
 {
 	int i_error, b_error;
 
 	down_read(&EXT3_I(inode)->xattr_sem);
-	i_error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
+	i_error = ext3_xattr_ibody_list(inode, buffer, buffer_size, cred);
 	if (i_error < 0) {
 		b_error = 0;
 	} else {
@@ -441,7 +447,8 @@ ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
 			buffer += i_error;
 			buffer_size -= i_error;
 		}
-		b_error = ext3_xattr_block_list(inode, buffer, buffer_size);
+		b_error = ext3_xattr_block_list(inode, buffer, buffer_size,
+						cred);
 		if (b_error < 0)
 			i_error = 0;
 	}
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 8d00a18..9ed3328 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -67,7 +67,7 @@ extern struct xattr_handler ext3_xattr_security_handler;
 extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
 
 extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-extern int ext3_xattr_list(struct inode *, char *, size_t);
+extern int ext3_xattr_list(struct inode *, char *, size_t, struct cred *);
 extern int ext3_xattr_set(struct inode *, int, const char *, const void *,
 			  size_t, int, struct cred *);
 extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *,
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index 7d01840..1680b7b 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -13,7 +13,7 @@
 
 static size_t
 ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
-			 const char *name, size_t name_len)
+			 const char *name, size_t name_len, struct cred *cred)
 {
 	const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
 	const size_t total_len = prefix_len + name_len + 1;
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index 6073729..049587b 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -17,7 +17,7 @@
 
 static size_t
 ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
-			const char *name, size_t name_len)
+			const char *name, size_t name_len, struct cred *cred)
 {
 	const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
 	const size_t total_len = prefix_len + name_len + 1;
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index f8a7663..6012c7e 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -16,7 +16,7 @@
 
 static size_t
 ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
-		     const char *name, size_t name_len)
+		     const char *name, size_t name_len, struct cred *cred)
 {
 	const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1;
 	const size_t total_len = prefix_len + name_len + 1;
diff --git a/fs/xattr.c b/fs/xattr.c
index 3c9bf2e..b1ee403 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -563,18 +563,20 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
 ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
 	unsigned int size = 0;
 
 	if (!buffer) {
 		for_each_xattr_handler(handlers, handler)
-			size += handler->list(inode, NULL, 0, NULL, 0);
+			size += handler->list(inode, NULL, 0, NULL, 0, cred);
 	} else {
 		char *buf = buffer;
 
 		for_each_xattr_handler(handlers, handler) {
-			size = handler->list(inode, buf, buffer_size, NULL, 0);
+			size = handler->list(inode, buf, buffer_size, NULL, 0,
+					     cred);
 			if (size > buffer_size)
 				return -ERANGE;
 			buf += size;
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index e702226..485d57c 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -39,7 +39,7 @@ struct dentry;
 struct xattr_handler {
 	char *prefix;
 	size_t (*list)(struct inode *inode, char *list, size_t list_size,
-		       const char *name, size_t name_len);
+		       const char *name, size_t name_len, struct cred *cred);
 	int (*get)(struct inode *inode, const char *name, void *buffer,
 		   size_t size, struct cred *cred);
 	int (*set)(struct inode *inode, const char *name, const void *buffer,
diff --git a/mm/shmem.c b/mm/shmem.c
index 45cc69e..24d3237 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1961,7 +1961,7 @@ static const struct inode_operations shmem_symlink_inode_operations = {
 
 static size_t shmem_xattr_security_list(struct inode *inode, char *list,
 					size_t list_len, const char *name,
-					size_t name_len)
+					size_t name_len, struct cred *cred)
 {
 	return security_inode_listsecurity(inode, list, list_len);
 }
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
index 7685a67..cda0a12 100644
--- a/mm/shmem_acl.c
+++ b/mm/shmem_acl.c
@@ -71,7 +71,7 @@ struct generic_acl_operations shmem_acl_ops = {
 
 static size_t
 shmem_list_acl_access(struct inode *inode, char *list, size_t list_size,
-		      const char *name, size_t name_len)
+		      const char *name, size_t name_len, struct cred *cred)
 {
 	return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_ACCESS,
 				list, list_size);
@@ -112,7 +112,7 @@ struct xattr_handler shmem_xattr_acl_access_handler = {
 
 static size_t
 shmem_list_acl_default(struct inode *inode, char *list, size_t list_size,
-		       const char *name, size_t name_len)
+		       const char *name, size_t name_len, struct cred *cred)
 {
 	return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT,
 				list, list_size);


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

* [PATCH 50/52] CRED: Pass credentials through the listxattr() inode op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (48 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 49/52] CRED: Pass credentials through the xattr list() handler David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-12 16:09 ` [PATCH 51/52] CRED: Pass credentials through the removexattr() " David Howells
                   ` (3 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the listxattr() inode operation.

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

 fs/bad_inode.c         |    2 +-
 fs/ext3/xattr.c        |    4 ++--
 fs/ext3/xattr.h        |    2 +-
 fs/nfs/nfs3acl.c       |    4 ++--
 fs/nfs/nfs4_fs.h       |    2 +-
 fs/nfs/nfs4proc.c      |    3 ++-
 fs/xattr.c             |    7 ++++---
 include/linux/fs.h     |    2 +-
 include/linux/nfs_fs.h |    2 +-
 include/linux/xattr.h  |    3 ++-
 10 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index b310af3..1b06a95 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -278,7 +278,7 @@ static ssize_t bad_inode_getxattr(struct dentry *dentry, const char *name,
 }
 
 static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
-			size_t buffer_size)
+			size_t buffer_size, struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 464395d..a3ad1a5 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -143,9 +143,9 @@ ext3_xattr_handler(int name_index)
  * dentry->d_inode->i_mutex: don't care
  */
 ssize_t
-ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size,
+	       struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	return ext3_xattr_list(dentry->d_inode, buffer, size, cred);
 }
 
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 9ed3328..06f334f 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -64,7 +64,7 @@ extern struct xattr_handler ext3_xattr_acl_access_handler;
 extern struct xattr_handler ext3_xattr_acl_default_handler;
 extern struct xattr_handler ext3_xattr_security_handler;
 
-extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t, struct cred *);
 
 extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
 extern int ext3_xattr_list(struct inode *, char *, size_t, struct cred *);
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 0d160be..6e318e2 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -7,9 +7,9 @@
 
 #define NFSDBG_FACILITY	NFSDBG_PROC
 
-ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size,
+		       struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl;
 	int pos=0, len=0;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 3f3dc4e..ee76c2c 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -171,7 +171,7 @@ extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t,
 			     struct cred *);
 extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t,
 			 int, struct cred *);
-extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
+extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t, struct cred *);
 
 
 /* nfs4proc.c */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 8be911a..4287752 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3746,7 +3746,8 @@ ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
 	return nfs4_proc_get_acl(inode, buf, buflen, acred);
 }
 
-ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
+ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen,
+		       struct cred *acred)
 {
 	size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
 
diff --git a/fs/xattr.c b/fs/xattr.c
index b1ee403..7b3bd56 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -146,6 +146,7 @@ EXPORT_SYMBOL_GPL(vfs_getxattr);
 ssize_t
 vfs_listxattr(struct dentry *d, char *list, size_t size)
 {
+	struct cred *cred = current->cred;
 	ssize_t error;
 
 	error = security_inode_listxattr(d);
@@ -153,7 +154,7 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
 		return error;
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
-		error = d->d_inode->i_op->listxattr(d, list, size);
+		error = d->d_inode->i_op->listxattr(d, list, size, cred);
 	} else {
 		error = security_inode_listsecurity(d->d_inode, list, size);
 		if (size && error > size)
@@ -561,9 +562,9 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
  * list.
  */
 ssize_t
-generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
+generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size,
+		  struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
 	unsigned int size = 0;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 28f0205..308b3a3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1164,7 +1164,7 @@ struct inode_operations {
 			 int, struct cred *);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,
 			     struct cred *);
-	ssize_t (*listxattr) (struct dentry *, char *, size_t);
+	ssize_t (*listxattr) (struct dentry *, char *, size_t, struct cred *);
 	int (*removexattr) (struct dentry *, const char *);
 	void (*truncate_range)(struct inode *, loff_t, loff_t);
 	long (*fallocate)(struct inode *inode, int mode, loff_t offset,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index d17ba8c..da642ac 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -353,7 +353,7 @@ static inline struct rpc_cred *nfs_file_cred(struct file *file)
  * linux/fs/nfs/xattr.c
  */
 #ifdef CONFIG_NFS_V3_ACL
-extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
+extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t, struct cred *);
 extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t,
 			     struct cred *);
 extern int nfs3_setxattr(struct dentry *, const char *,
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 485d57c..8b1237a 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -53,7 +53,8 @@ int vfs_removexattr(struct dentry *, char *);
 
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer,
 			 size_t size, struct cred *cred);
-ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
+ssize_t generic_listxattr(struct dentry *dentry, char *buffer,
+			  size_t buffer_size, struct cred *cred);
 int generic_setxattr(struct dentry *dentry, const char *name, const void *value,
 		     size_t size, int flags, struct cred *cred);
 int generic_removexattr(struct dentry *dentry, const char *name);


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

* [PATCH 51/52] CRED: Pass credentials through the removexattr() inode op
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (49 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 50/52] CRED: Pass credentials through the listxattr() inode op David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-12 16:09 ` [PATCH 52/52] CRED: Pass credentials through vfs_mkdir() David Howells
                   ` (2 subsequent siblings)
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through the removexattr() inode operation.

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

 fs/bad_inode.c         |    3 ++-
 fs/nfs/nfs3acl.c       |    4 ++--
 fs/xattr.c             |    7 ++++---
 include/linux/fs.h     |    2 +-
 include/linux/nfs_fs.h |    2 +-
 include/linux/xattr.h  |    3 ++-
 6 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 1b06a95..5fde74f 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -283,7 +283,8 @@ static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
 	return -EIO;
 }
 
-static int bad_inode_removexattr(struct dentry *dentry, const char *name)
+static int bad_inode_removexattr(struct dentry *dentry, const char *name,
+				 struct cred *cred)
 {
 	return -EIO;
 }
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 6e318e2..143627c 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -99,9 +99,9 @@ int nfs3_setxattr(struct dentry *dentry, const char *name,
 	return error;
 }
 
-int nfs3_removexattr(struct dentry *dentry, const char *name)
+int nfs3_removexattr(struct dentry *dentry, const char *name,
+		     struct cred *acred)
 {
-	struct cred *acred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int type;
 
diff --git a/fs/xattr.c b/fs/xattr.c
index 7b3bd56..dee1ac4 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -167,6 +167,7 @@ EXPORT_SYMBOL_GPL(vfs_listxattr);
 int
 vfs_removexattr(struct dentry *dentry, char *name)
 {
+	struct cred *cred = current->cred;
 	struct inode *inode = dentry->d_inode;
 	int error;
 
@@ -182,7 +183,7 @@ vfs_removexattr(struct dentry *dentry, char *name)
 		return error;
 
 	mutex_lock(&inode->i_mutex);
-	error = inode->i_op->removexattr(dentry, name);
+	error = inode->i_op->removexattr(dentry, name, cred);
 	mutex_unlock(&inode->i_mutex);
 
 	if (!error)
@@ -611,9 +612,9 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value,
  * any associated extended attribute.
  */
 int
-generic_removexattr(struct dentry *dentry, const char *name)
+generic_removexattr(struct dentry *dentry, const char *name,
+		    struct cred *cred)
 {
-	struct cred *cred = current->cred;
 	struct xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 308b3a3..754e4ec 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1165,7 +1165,7 @@ struct inode_operations {
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,
 			     struct cred *);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t, struct cred *);
-	int (*removexattr) (struct dentry *, const char *);
+	int (*removexattr) (struct dentry *, const char *, struct cred *);
 	void (*truncate_range)(struct inode *, loff_t, loff_t);
 	long (*fallocate)(struct inode *inode, int mode, loff_t offset,
 			  loff_t len);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index da642ac..4733c6c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -358,7 +358,7 @@ extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t,
 			     struct cred *);
 extern int nfs3_setxattr(struct dentry *, const char *,
 			const void *, size_t, int, struct cred *);
-extern int nfs3_removexattr (struct dentry *, const char *name);
+extern int nfs3_removexattr (struct dentry *, const char *, struct cred *);
 #else
 # define nfs3_listxattr NULL
 # define nfs3_getxattr NULL
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 8b1237a..0e79b32 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -57,7 +57,8 @@ ssize_t generic_listxattr(struct dentry *dentry, char *buffer,
 			  size_t buffer_size, struct cred *cred);
 int generic_setxattr(struct dentry *dentry, const char *name, const void *value,
 		     size_t size, int flags, struct cred *cred);
-int generic_removexattr(struct dentry *dentry, const char *name);
+int generic_removexattr(struct dentry *dentry, const char *name,
+			struct cred *cred);
 
 #endif  /*  __KERNEL__  */
 


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

* [PATCH 52/52] CRED: Pass credentials through vfs_mkdir()
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (50 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 51/52] CRED: Pass credentials through the removexattr() " David Howells
@ 2007-10-12 16:09 ` David Howells
  2007-10-13 18:11 ` [PATCH 00/52] Introduce credential record Theodore Tso
  2007-10-13 21:46 ` David Howells
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-12 16:09 UTC (permalink / raw)
  To: viro; +Cc: kwc, Trond.Myklebust, linux-kernel, dhowells

Pass credentials through vfs_mkdir().

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

 0 files changed, 0 insertions(+), 0 deletions(-)



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

* Re: [PATCH 00/52] Introduce credential record
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (51 preceding siblings ...)
  2007-10-12 16:09 ` [PATCH 52/52] CRED: Pass credentials through vfs_mkdir() David Howells
@ 2007-10-13 18:11 ` Theodore Tso
  2007-10-13 18:19   ` Al Viro
  2007-10-13 21:46 ` David Howells
  53 siblings, 1 reply; 57+ messages in thread
From: Theodore Tso @ 2007-10-13 18:11 UTC (permalink / raw)
  To: David Howells; +Cc: viro, kwc, Trond.Myklebust, linux-kernel

Hi David,

   I'm going to ask a stupid question, and I probably missed something
in the 52 patches, but....  I see how the credential is used to do
access checks, but why does the credentials record need to passed all
the way into block allocator?  What is it used for there?

    	     	   	       	       	  - Ted

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

* Re: [PATCH 00/52] Introduce credential record
  2007-10-13 18:11 ` [PATCH 00/52] Introduce credential record Theodore Tso
@ 2007-10-13 18:19   ` Al Viro
  0 siblings, 0 replies; 57+ messages in thread
From: Al Viro @ 2007-10-13 18:19 UTC (permalink / raw)
  To: Theodore Tso, David Howells, kwc, Trond.Myklebust, linux-kernel

On Sat, Oct 13, 2007 at 02:11:37PM -0400, Theodore Tso wrote:
> Hi David,
> 
>    I'm going to ask a stupid question, and I probably missed something
> in the 52 patches, but....  I see how the credential is used to do
> access checks, but why does the credentials record need to passed all
> the way into block allocator?  What is it used for there?

"5% are reserved for root"

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

* Re: [PATCH 00/52] Introduce credential record
  2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
                   ` (52 preceding siblings ...)
  2007-10-13 18:11 ` [PATCH 00/52] Introduce credential record Theodore Tso
@ 2007-10-13 21:46 ` David Howells
  53 siblings, 0 replies; 57+ messages in thread
From: David Howells @ 2007-10-13 21:46 UTC (permalink / raw)
  To: Theodore Tso; +Cc: dhowells, viro, kwc, Trond.Myklebust, linux-kernel

Theodore Tso <tytso@mit.edu> wrote:

>    I'm going to ask a stupid question, and I probably missed something
> in the 52 patches, but....  I see how the credential is used to do
> access checks, but why does the credentials record need to passed all
> the way into block allocator?  What is it used for there?

Ext2, 3 & 4 use it to determine whether someone has the right to use the
reserved space according to whether their UID/GID match those in the
superblock.

See ext3_has_free_blocks() for an example.

David

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

* Re: [PATCH 01/52] CRED: Introduce a COW credentials record
  2007-10-12 16:05 ` [PATCH 01/52] CRED: Introduce a COW credentials record David Howells
@ 2007-10-15  1:53   ` David Chinner
  0 siblings, 0 replies; 57+ messages in thread
From: David Chinner @ 2007-10-15  1:53 UTC (permalink / raw)
  To: David Howells; +Cc: viro, kwc, Trond.Myklebust, linux-kernel

On Fri, Oct 12, 2007 at 05:05:24PM +0100, David Howells wrote:
> diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
> index 4ca4beb..a460508 100644
> --- a/fs/xfs/xfs_acl.c
> +++ b/fs/xfs/xfs_acl.c
> @@ -383,7 +383,7 @@ xfs_acl_allow_set(
>  	error = bhv_vop_getattr(vp, &va, 0, NULL);
>  	if (error)
>  		return error;
> -	if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
> +	if (va.va_uid != current->cred->uid && !capable(CAP_FOWNER))

current_fsuid() should be used here.

>  		return EPERM;
>  	return error;
>  }
> @@ -457,13 +457,13 @@ xfs_acl_access(
>  		switch (fap->acl_entry[i].ae_tag) {
>  		case ACL_USER_OBJ:
>  			seen_userobj = 1;
> -			if (fuid != current->fsuid)
> +			if (fuid != current->cred->uid)
>  				continue;
>  			matched.ae_tag = ACL_USER_OBJ;
>  			matched.ae_perm = allows;
>  			break;
>  		case ACL_USER:
> -			if (fap->acl_entry[i].ae_id != current->fsuid)
> +			if (fap->acl_entry[i].ae_id != current->cred->uid)

and here as well....

Cheers,

Dave.
-- 
Dave Chinner
Principal Engineer
SGI Australian Software Group

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

end of thread, other threads:[~2007-10-15  1:53 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-10-12 16:05 [PATCH 00/52] Introduce credential record David Howells
2007-10-12 16:05 ` [PATCH 01/52] CRED: Introduce a COW credentials record David Howells
2007-10-15  1:53   ` David Chinner
2007-10-12 16:05 ` [PATCH 02/52] CRED: Give in_group_p() a cred pointer David Howells
2007-10-12 16:05 ` [PATCH 03/52] CRED: Pass credentials down to ext3 block allocator David Howells
2007-10-12 16:05 ` [PATCH 04/52] CRED: Pass credentials down to ext3 inode allocator David Howells
2007-10-12 16:05 ` [PATCH 05/52] CRED: Prepare TMPFS for cred passing David Howells
2007-10-12 16:05 ` [PATCH 06/52] CRED: Prepare RAMFS " David Howells
2007-10-12 16:05 ` [PATCH 07/52] CRED: Pass credentials down to ext2 block allocator David Howells
2007-10-12 16:06 ` [PATCH 08/52] CRED: Pass credentials down to ext2 inode allocator David Howells
2007-10-12 16:06 ` [PATCH 09/52] CRED: Pass credentials down to ext4 block allocator David Howells
2007-10-12 16:06 ` [PATCH 10/52] CRED: Pass credentials down to ext4 inode allocator David Howells
2007-10-12 16:06 ` [PATCH 11/52] CRED: Give the get_block() callback a credentials pointer David Howells
2007-10-12 16:06 ` [PATCH 12/52] CRED: Make mpage read functions take " David Howells
2007-10-12 16:06 ` [PATCH 13/52] CRED: Make block_prepare_write() and co " David Howells
2007-10-12 16:06 ` [PATCH 14/52] CRED: Provide a writeback credentials record David Howells
2007-10-12 16:06 ` [PATCH 15/52] CRED: Make Ext3 use the writeback credentials David Howells
2007-10-12 16:06 ` [PATCH 16/52] CRED: Pass credentials through the internals of ext3 truncation David Howells
2007-10-12 16:06 ` [PATCH 17/52] CRED: Make rpcauth_lookupcred() take a credentials pointer David Howells
2007-10-12 16:06 ` [PATCH 18/52] CRED: Make rpcauth_bindcred() " David Howells
2007-10-12 16:06 ` [PATCH 19/52] CRED: Add a credentials pointer to struct rpc_task David Howells
2007-10-12 16:07 ` [PATCH 20/52] CRED: Pass credentials into rpc_init_task() David Howells
2007-10-12 16:07 ` [PATCH 21/52] CRED: Pass credentials through the truncate() inode operation David Howells
2007-10-12 16:07 ` [PATCH 22/52] CRED: Pass credentials to nfs_setattr_update_inode() David Howells
2007-10-12 16:07 ` [PATCH 23/52] CRED: Pass credentials to the setattr() inode operation David Howells
2007-10-12 16:07 ` [PATCH 24/52] CRED: Pass credentials through inode_setattr() David Howells
2007-10-12 16:07 ` [PATCH 25/52] CRED: Give the mknod() inode op a credentials pointer David Howells
2007-10-12 16:07 ` [PATCH 26/52] CRED: Give the mkdir() " David Howells
2007-10-12 16:07 ` [PATCH 27/52] CRED: Give the create() " David Howells
2007-10-12 16:07 ` [PATCH 28/52] CRED: Give the link() " David Howells
2007-10-12 16:07 ` [PATCH 29/52] CRED: Give the unlink() " David Howells
2007-10-12 16:07 ` [PATCH 30/52] CRED: Give the rmdir() " David Howells
2007-10-12 16:07 ` [PATCH 31/52] CRED: Give the rename() " David Howells
2007-10-12 16:08 ` [PATCH 32/52] CRED: Give the symlink() " David Howells
2007-10-12 16:08 ` [PATCH 33/52] CRED: Make the get_parent() export op take a credential pointer David Howells
2007-10-12 16:08 ` [PATCH 34/52] CRED: Make Ext3 ACL set handlers pass credentials down David Howells
2007-10-12 16:08 ` [PATCH 35/52] CRED: Make the ACL set() handler take a credentials pointer David Howells
2007-10-12 16:08 ` [PATCH 36/52] CRED: Make ext3_fill_super() pass credentials down David Howells
2007-10-12 16:08 ` [PATCH 37/52] CRED: Pass credentials to the get_sb() op and various fill_super() ops David Howells
2007-10-12 16:08 ` [PATCH 38/52] CRED: Pass credentials through the quota_read() op David Howells
2007-10-12 16:08 ` [PATCH 39/52] CRED: Pass credentials through the quota_write() op David Howells
2007-10-12 16:08 ` [PATCH 40/52] CRED: Give the lookup() inode op a credentials pointer David Howells
2007-10-12 16:08 ` [PATCH 41/52] CRED: Pass credentials through d_revalidate() David Howells
2007-10-12 16:08 ` [PATCH 42/52] CRED: Pass credentials through the permission() inode op David Howells
2007-10-12 16:08 ` [PATCH 43/52] CRED: Pass credentials through the statfs() superblock op David Howells
2007-10-12 16:09 ` [PATCH 44/52] CRED: Pass credentials through the follow_link() inode op David Howells
2007-10-12 16:09 ` [PATCH 45/52] CRED: Pass credentials through the getattr() " David Howells
2007-10-12 16:09 ` [PATCH 46/52] CRED: Pass credentials through the setxattr() " David Howells
2007-10-12 16:09 ` [PATCH 47/52] CRED: Pass credentials through the xattr get() handler David Howells
2007-10-12 16:09 ` [PATCH 48/52] CRED: Pass credentials through the getxattr() inode op David Howells
2007-10-12 16:09 ` [PATCH 49/52] CRED: Pass credentials through the xattr list() handler David Howells
2007-10-12 16:09 ` [PATCH 50/52] CRED: Pass credentials through the listxattr() inode op David Howells
2007-10-12 16:09 ` [PATCH 51/52] CRED: Pass credentials through the removexattr() " David Howells
2007-10-12 16:09 ` [PATCH 52/52] CRED: Pass credentials through vfs_mkdir() David Howells
2007-10-13 18:11 ` [PATCH 00/52] Introduce credential record Theodore Tso
2007-10-13 18:19   ` Al Viro
2007-10-13 21:46 ` David Howells

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.