summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/fid.c2
-rw-r--r--fs/9p/vfs_inode.c4
-rw-r--r--fs/9p/vfs_super.c4
-rw-r--r--fs/affs/inode.c4
-rw-r--r--fs/affs/super.c4
-rw-r--r--fs/anon_inodes.c4
-rw-r--r--fs/attr.c4
-rw-r--r--fs/autofs/inode.c4
-rw-r--r--fs/autofs4/dev-ioctl.c3
-rw-r--r--fs/autofs4/inode.c4
-rw-r--r--fs/autofs4/waitq.c4
-rw-r--r--fs/bfs/dir.c4
-rw-r--r--fs/binfmt_aout.c2
-rw-r--r--fs/binfmt_elf.c20
-rw-r--r--fs/binfmt_elf_fdpic.c19
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/binfmt_som.c2
-rw-r--r--fs/cifs/cifs_fs_sb.h2
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/connect.c4
-rw-r--r--fs/cifs/dir.c12
-rw-r--r--fs/cifs/inode.c8
-rw-r--r--fs/cifs/ioctl.c2
-rw-r--r--fs/cifs/misc.c4
-rw-r--r--fs/coda/cache.c6
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/coda/upcall.c2
-rw-r--r--fs/compat.c42
-rw-r--r--fs/devpts/inode.c4
-rw-r--r--fs/dquot.c4
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h3
-rw-r--r--fs/ecryptfs/kthread.c9
-rw-r--r--fs/ecryptfs/main.c3
-rw-r--r--fs/ecryptfs/messaging.c18
-rw-r--r--fs/ecryptfs/miscdev.c20
-rw-r--r--fs/exec.c183
-rw-r--r--fs/exportfs/expfs.c4
-rw-r--r--fs/ext2/balloc.c2
-rw-r--r--fs/ext2/ialloc.c4
-rw-r--r--fs/ext3/balloc.c2
-rw-r--r--fs/ext3/ialloc.c4
-rw-r--r--fs/ext4/balloc.c2
-rw-r--r--fs/ext4/ialloc.c4
-rw-r--r--fs/fat/file.c2
-rw-r--r--fs/fat/inode.c4
-rw-r--r--fs/fcntl.c18
-rw-r--r--fs/file_table.c10
-rw-r--r--fs/fuse/dev.c4
-rw-r--r--fs/fuse/dir.c23
-rw-r--r--fs/gfs2/inode.c10
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfs/super.c4
-rw-r--r--fs/hfsplus/inode.c4
-rw-r--r--fs/hfsplus/options.c4
-rw-r--r--fs/hpfs/namei.c24
-rw-r--r--fs/hpfs/super.c4
-rw-r--r--fs/hppfs/hppfs.c6
-rw-r--r--fs/hugetlbfs/inode.c21
-rw-r--r--fs/inotify_user.c2
-rw-r--r--fs/internal.h6
-rw-r--r--fs/ioprio.c18
-rw-r--r--fs/jfs/jfs_inode.c4
-rw-r--r--fs/locks.c2
-rw-r--r--fs/minix/bitmap.c4
-rw-r--r--fs/namei.c10
-rw-r--r--fs/namespace.c2
-rw-r--r--fs/ncpfs/ioctl.c91
-rw-r--r--fs/nfsctl.c3
-rw-r--r--fs/nfsd/auth.c95
-rw-r--r--fs/nfsd/nfs4recover.c71
-rw-r--r--fs/nfsd/nfsfh.c11
-rw-r--r--fs/nfsd/vfs.c9
-rw-r--r--fs/ocfs2/dlm/dlmfs.c8
-rw-r--r--fs/ocfs2/namei.c4
-rw-r--r--fs/omfs/inode.c8
-rw-r--r--fs/open.c59
-rw-r--r--fs/pipe.c4
-rw-r--r--fs/posix_acl.c4
-rw-r--r--fs/proc/array.c32
-rw-r--r--fs/proc/base.c32
-rw-r--r--fs/quota.c4
-rw-r--r--fs/ramfs/inode.c4
-rw-r--r--fs/reiserfs/namei.c4
-rw-r--r--fs/smbfs/dir.c3
-rw-r--r--fs/smbfs/inode.c2
-rw-r--r--fs/smbfs/proc.c2
-rw-r--r--fs/sysv/ialloc.c4
-rw-r--r--fs/ubifs/budget.c2
-rw-r--r--fs/ubifs/dir.c4
-rw-r--r--fs/udf/ialloc.c4
-rw-r--r--fs/udf/namei.c2
-rw-r--r--fs/ufs/ialloc.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_cred.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c5
-rw-r--r--fs/xfs/xfs_acl.c6
-rw-r--r--fs/xfs/xfs_inode.h2
-rw-r--r--fs/xfs/xfs_vnodeops.h10
98 files changed, 643 insertions, 490 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 3031e3233dd..a43e4ab7c6c 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -120,7 +120,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
switch (access) {
case V9FS_ACCESS_SINGLE:
case V9FS_ACCESS_USER:
- uid = current->fsuid;
+ uid = current_fsuid();
any = 0;
break;
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 8314d3f43b7..8fddfe86a0d 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -215,8 +215,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_blocks = 0;
inode->i_rdev = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index d6cb1a0ca72..93212e40221 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -113,8 +113,8 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
struct v9fs_session_info *v9ses = NULL;
struct p9_wstat *st = NULL;
int mode = S_IRWXUGO | S_ISVTX;
- uid_t uid = current->fsuid;
- gid_t gid = current->fsgid;
+ uid_t uid = current_fsuid();
+ gid_t gid = current_fsgid();
struct p9_fid *fid;
int retval = 0;
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index a13b334a391..415d9c67ac1 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -293,8 +293,8 @@ affs_new_inode(struct inode *dir)
mark_buffer_dirty_inode(bh, inode);
affs_brelse(bh);
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_ino = block;
inode->i_nlink = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 8989c93193e..a19d64b582a 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -163,8 +163,8 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
/* Fill in defaults */
- *uid = current->uid;
- *gid = current->gid;
+ *uid = current_uid();
+ *gid = current_gid();
*reserved = 2;
*root = -1;
*blocksize = -1;
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 3662dd44896..c16d9be1b01 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -154,8 +154,8 @@ static struct inode *anon_inode_mkinode(void)
*/
inode->i_state = I_DIRTY;
inode->i_mode = S_IRUSR | S_IWUSR;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
return inode;
}
diff --git a/fs/attr.c b/fs/attr.c
index 7a83819f6ba..f4360192a93 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -29,13 +29,13 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
/* Make sure a caller can chown. */
if ((ia_valid & ATTR_UID) &&
- (current->fsuid != inode->i_uid ||
+ (current_fsuid() != inode->i_uid ||
attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
goto error;
/* Make sure caller can chgrp. */
if ((ia_valid & ATTR_GID) &&
- (current->fsuid != inode->i_uid ||
+ (current_fsuid() != inode->i_uid ||
(!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
!capable(CAP_CHOWN))
goto error;
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index b70eea1e8c5..c773680d5c6 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -76,8 +76,8 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
substring_t args[MAX_OPT_ARGS];
int option;
- *uid = current->uid;
- *gid = current->gid;
+ *uid = current_uid();
+ *gid = current_gid();
*pgrp = task_pgrp_nr(current);
*minproto = *maxproto = AUTOFS_PROTO_VERSION;
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 33bf8cbfd05..63b7c7afe8d 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -308,7 +308,8 @@ static int autofs_dev_ioctl_open_mountpoint(const char *path, dev_t devid)
goto out;
}
- filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY);
+ filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
+ current_cred());
if (IS_ERR(filp)) {
err = PTR_ERR(filp);
goto out;
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index c7e65bb30ba..7b19802cfef 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -235,8 +235,8 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
substring_t args[MAX_OPT_ARGS];
int option;
- *uid = current->uid;
- *gid = current->gid;
+ *uid = current_uid();
+ *gid = current_gid();
*pgrp = task_pgrp_nr(current);
*minproto = AUTOFS_MIN_PROTO_VERSION;
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 4b67c2a2d77..e02cc8ae5eb 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -391,8 +391,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
memcpy(&wq->name, &qstr, sizeof(struct qstr));
wq->dev = autofs4_get_dev(sbi);
wq->ino = autofs4_get_ino(sbi);
- wq->uid = current->uid;
- wq->gid = current->gid;
+ wq->uid = current_uid();
+ wq->gid = current_gid();
wq->pid = current->pid;
wq->tgid = current->tgid;
wq->status = -EINTR; /* Status return if interrupted */
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index daae463068e..4dd1b623f93 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -106,8 +106,8 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
}
set_bit(ino, info->si_imap);
info->si_freei--;
- inode->i_uid = current->fsuid;
- inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current_fsgid();
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
inode->i_blocks = 0;
inode->i_op = &bfs_file_inops;
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 204cfd1d767..f1f3f4192a6 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -320,7 +320,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->free_area_cache = current->mm->mmap_base;
current->mm->cached_hole_size = 0;
- compute_creds(bprm);
+ install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
#ifdef __sparc__
if (N_MAGIC(ex) == NMAGIC) {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 8fcfa398d35..f458c1217c5 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -157,7 +157,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
int items;
elf_addr_t *elf_info;
int ei_index = 0;
- struct task_struct *tsk = current;
+ const struct cred *cred = current_cred();
struct vm_area_struct *vma;
/*
@@ -223,10 +223,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
NEW_AUX_ENT(AT_BASE, interp_load_addr);
NEW_AUX_ENT(AT_FLAGS, 0);
NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
- NEW_AUX_ENT(AT_UID, tsk->uid);
- NEW_AUX_ENT(AT_EUID, tsk->euid);
- NEW_AUX_ENT(AT_GID, tsk->gid);
- NEW_AUX_ENT(AT_EGID, tsk->egid);
+ NEW_AUX_ENT(AT_UID, cred->uid);
+ NEW_AUX_ENT(AT_EUID, cred->euid);
+ NEW_AUX_ENT(AT_GID, cred->gid);
+ NEW_AUX_ENT(AT_EGID, cred->egid);
NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
NEW_AUX_ENT(AT_EXECFN, bprm->exec);
if (k_platform) {
@@ -956,7 +956,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
}
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
- compute_creds(bprm);
+ install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
retval = create_elf_tables(bprm, &loc->elf_ex,
load_addr, interp_load_addr);
@@ -1361,6 +1361,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
struct mm_struct *mm)
{
+ const struct cred *cred;
unsigned int i, len;
/* first copy the parameters from user space */
@@ -1388,8 +1389,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_zomb = psinfo->pr_sname == 'Z';
psinfo->pr_nice = task_nice(p);
psinfo->pr_flag = p->flags;
- SET_UID(psinfo->pr_uid, p->uid);
- SET_GID(psinfo->pr_gid, p->gid);
+ rcu_read_lock();
+ cred = __task_cred(p);
+ SET_UID(psinfo->pr_uid, cred->uid);
+ SET_GID(psinfo->pr_gid, cred->gid);
+ rcu_read_unlock();
strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
return 0;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 5b5424cb339..aa5b43205e3 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -404,7 +404,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
current->mm->start_stack = current->mm->start_brk + stack_size;
#endif
- compute_creds(bprm);
+ install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
if (create_elf_fdpic_tables(bprm, current->mm,
&exec_params, &interp_params) < 0)
@@ -475,6 +475,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
struct elf_fdpic_params *exec_params,
struct elf_fdpic_params *interp_params)
{
+ const struct cred *cred = current_cred();
unsigned long sp, csp, nitems;
elf_caddr_t __user *argv, *envp;
size_t platform_len = 0, len;
@@ -623,10 +624,10 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
NEW_AUX_ENT(AT_BASE, interp_params->elfhdr_addr);
NEW_AUX_ENT(AT_FLAGS, 0);
NEW_AUX_ENT(AT_ENTRY, exec_params->entry_addr);
- NEW_AUX_ENT(AT_UID, (elf_addr_t) current->uid);
- NEW_AUX_ENT(AT_EUID, (elf_addr_t) current->euid);
- NEW_AUX_ENT(AT_GID, (elf_addr_t) current->gid);
- NEW_AUX_ENT(AT_EGID, (elf_addr_t) current->egid);
+ NEW_AUX_ENT(AT_UID, (elf_addr_t) cred->uid);
+ NEW_AUX_ENT(AT_EUID, (elf_addr_t) cred->euid);
+ NEW_AUX_ENT(AT_GID, (elf_addr_t) cred->gid);
+ NEW_AUX_ENT(AT_EGID, (elf_addr_t) cred->egid);
NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
NEW_AUX_ENT(AT_EXECFN, bprm->exec);
@@ -1413,6 +1414,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
struct mm_struct *mm)
{
+ const struct cred *cred;
unsigned int i, len;
/* first copy the parameters from user space */
@@ -1440,8 +1442,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_zomb = psinfo->pr_sname == 'Z';
psinfo->pr_nice = task_nice(p);
psinfo->pr_flag = p->flags;
- SET_UID(psinfo->pr_uid, p->uid);
- SET_GID(psinfo->pr_gid, p->gid);
+ rcu_read_lock();
+ cred = __task_cred(p);
+ SET_UID(psinfo->pr_uid, cred->uid);
+ SET_GID(psinfo->pr_gid, cred->gid);
+ rcu_read_unlock();
strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
return 0;
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index ccb781a6a80..7bbd5c6b372 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -880,7 +880,7 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
(libinfo.lib_list[j].loaded)?
libinfo.lib_list[j].start_data:UNLOADED_LIB;
- compute_creds(bprm);
+ install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
set_binfmt(&flat_format);
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index 74e587a5279..08644a61616 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -255,7 +255,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
kfree(hpuxhdr);
set_binfmt(&som_format);
- compute_creds(bprm);
+ install_exec_creds(bprm);
setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
create_som_tables(bprm);
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 877c85409f1..1e7b87497f2 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -19,7 +19,7 @@
#define _CIFS_FS_SB_H
#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
-#define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */
+#define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */
#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 6f21ecb85ce..9d8b978137a 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 *, bool);
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",__func__, xid,current->fsuid));
+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
extern char *build_path_from_dentry(struct dentry *);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c7d34171458..683dee4d2f7 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -836,8 +836,8 @@ cifs_parse_mount_options(char *options, const char *devname,
/* null target name indicates to use *SMBSERVR default called name
if we end up sending RFC1001 session initialize */
vol->target_rfc1001_name[0] = 0;
- vol->linux_uid = current->uid; /* current->euid instead? */
- vol->linux_gid = current->gid;
+ vol->linux_uid = current_uid(); /* use current_euid() instead? */
+ vol->linux_gid = current_gid();
vol->dir_mode = S_IRWXUGO;
/* 2767 perms indicate mandatory locking support */
vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e962e75e6f7..2f02c52db66 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -235,11 +235,11 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = (__u64) current->fsuid;
+ args.uid = (__u64) current_fsuid();
if (inode->i_mode & S_ISGID)
args.gid = (__u64) inode->i_gid;
else
- args.gid = (__u64) current->fsgid;
+ args.gid = (__u64) current_fsgid();
} else {
args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64;
@@ -271,13 +271,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if ((oplock & CIFS_CREATE_ACTION) &&
(cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_SET_UID)) {
- newinode->i_uid = current->fsuid;
+ newinode->i_uid = current_fsuid();
if (inode->i_mode & S_ISGID)
newinode->i_gid =
inode->i_gid;
else
newinode->i_gid =
- current->fsgid;
+ current_fsgid();
}
}
}
@@ -375,8 +375,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
.device = device_number,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = (__u64) current->fsuid;
- args.gid = (__u64) current->fsgid;
+ args.uid = (__u64) current_fsuid();
+ args.gid = (__u64) current_fsgid();
} else {
args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index ff8c68de4a9..8b7305e73d7 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1143,11 +1143,11 @@ mkdir_get_info:
.device = 0,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = (__u64)current->fsuid;
+ args.uid = (__u64)current_fsuid();
if (inode->i_mode & S_ISGID)
args.gid = (__u64)inode->i_gid;
else
- args.gid = (__u64)current->fsgid;
+ args.gid = (__u64)current_fsgid();
} else {
args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64;
@@ -1184,13 +1184,13 @@ mkdir_get_info:
if (cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_SET_UID) {
direntry->d_inode->i_uid =
- current->fsuid;
+ current_fsuid();
if (inode->i_mode & S_ISGID)
direntry->d_inode->i_gid =
inode->i_gid;
else
direntry->d_inode->i_gid =
- current->fsgid;
+ current_fsgid();
}
}
}
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 0088a5b5256..f94650683a0 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -65,7 +65,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
switch (command) {
case CIFS_IOC_CHECKUMOUNT:
cFYI(1, ("User unmount attempted"));
- if (cifs_sb->mnt_uid == current->uid)
+ if (cifs_sb->mnt_uid == current_uid())
rc = 0;
else {
rc = -EACCES;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index addd1dcc2d7..f108040ca1b 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -338,13 +338,13 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
/* BB Add support for establishing new tCon and SMB Session */
/* with userid/password pairs found on the smb session */
/* for other target tcp/ip addresses BB */
- if (current->fsuid != treeCon->ses->linux_uid) {
+ if (current_fsuid() != treeCon->ses->linux_uid) {
cFYI(1, ("Multiuser mode and UID "
"did not match tcon uid"));
read_lock(&cifs_tcp_ses_lock);
list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
- if (ses->linux_uid == current->fsuid) {
+ if (ses->linux_uid == current_fsuid()) {
if (ses->server == treeCon->ses->server) {
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 8a2370341c7..a5bf5771a22 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -32,8 +32,8 @@ void coda_cache_enter(struct inode *inode, int mask)
struct coda_inode_info *cii = ITOC(inode);
cii->c_cached_epoch = atomic_read(&permission_epoch);
- if (cii->c_uid != current->fsuid) {
- cii->c_uid = current->fsuid;
+ if (cii->c_uid != current_fsuid()) {
+ cii->c_uid = current_fsuid();
cii->c_cached_perm = mask;
} else
cii->c_cached_perm |= mask;
@@ -60,7 +60,7 @@ int coda_cache_check(struct inode *inode, int mask)
int hit;
hit = (mask & cii->c_cached_perm) == mask &&
- cii->c_uid == current->fsuid &&
+ cii->c_uid == current_fsuid() &&
cii->c_cached_epoch == atomic_read(&permission_epoch);
return hit;
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 29137ff3ca6..5a876998549 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->fsuid);
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 ce432bca95d..c274d949179 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -52,7 +52,7 @@ static void *alloc_upcall(int opcode, int size)
inp->ih.opcode = opcode;
inp->ih.pid = current->pid;
inp->ih.pgid = task_pgrp_nr(current);
- inp->ih.uid = current->fsuid;
+ inp->ih.uid = current_fsuid();
return (void*)inp;
}
diff --git a/fs/compat.c b/fs/compat.c
index e5f49f53850..d1ece79b641 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1393,10 +1393,20 @@ int compat_do_execve(char * filename,
if (!bprm)
goto out_ret;
+ retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+ if (retval < 0)
+ goto out_free;
+
+ retval = -ENOMEM;
+ bprm->cred = prepare_exec_creds();
+ if (!bprm->cred)
+ goto out_unlock;
+ check_unsafe_exec(bprm);
+
file = open_exec(filename);
retval = PTR_ERR(file);
if (IS_ERR(file))
- goto out_kfree;
+ goto out_unlock;
sched_exec();
@@ -1410,14 +1420,10 @@ int compat_do_execve(char * filename,
bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
if ((retval = bprm->argc) < 0)
- goto out_mm;
+ goto out;
bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
if ((retval = bprm->envc) < 0)
- goto out_mm;
-
- retval = security_bprm_alloc(bprm);
- if (retval)
goto out;
retval = prepare_binprm(bprm);
@@ -1438,19 +1444,16 @@ int compat_do_execve(char * filename,
goto out;
retval = search_binary_handler(bprm, regs);
- if (retval >= 0) {
- /* execve success */
- security_bprm_free(bprm);
- acct_update_integrals(current);
- free_bprm(bprm);
- return retval;
- }
+ if (retval < 0)
+ goto out;
-out:
- if (bprm->security)
- security_bprm_free(bprm);
+ /* execve succeeded */
+ mutex_unlock(&current->cred_exec_mutex);
+ acct_update_integrals(current);
+ free_bprm(bprm);
+ return retval;
-out_mm:
+out:
if (bprm->mm)
mmput(bprm->mm);
@@ -1460,7 +1463,10 @@ out_file:
fput(bprm->file);
}
-out_kfree:
+out_unlock:
+ mutex_unlock(&current->cred_exec_mutex);
+
+out_free:
free_bprm(bprm);
out_ret:
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 4a714f6c1be..5d61b7c06e1 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -222,8 +222,8 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
return -ENOMEM;
inode->i_ino = number+2;
- inode->i_uid = config.setuid ? config.uid : current->fsuid;
- inode->i_gid = config.setgid ? config.gid : current->fsgid;
+ inode->i_uid = config.setuid ? config.uid : current_fsuid();
+ inode->i_gid = config.setgid ? config.gid : current_fsgid();
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|config.mode, device);
inode->i_private = tty;
diff --git a/fs/dquot.c b/fs/dquot.c
index 5e95261005b..c237ccc8581 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -874,7 +874,7 @@ static inline int need_print_warning(struct dquot *dquot)
switch (dquot->dq_type) {
case USRQUOTA:
- return current->fsuid == dquot->dq_id;
+ return current_fsuid() == dquot->dq_id;
case GRPQUOTA:
return in_group_p(dquot->dq_id);
}
@@ -981,7 +981,7 @@ static void send_warning(const struct dquot *dquot, const char warntype)
MINOR(dquot->dq_sb->s_dev));
if (ret)
goto attr_err_out;
- ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current->user->uid);
+ ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid());
if (ret)
goto attr_err_out;
genlmsg_end(skb, msg_head);
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 3504cf9df35..a75026d35d1 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -691,7 +691,8 @@ int ecryptfs_init_kthread(void);
void ecryptfs_destroy_kthread(void);
int ecryptfs_privileged_open(struct file **lower_file,
struct dentry *lower_dentry,
- struct vfsmount *lower_mnt);
+ struct vfsmount *lower_mnt,
+ const struct cred *cred);
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
index c440c6b58b2..c6d7a4d748a 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -73,7 +73,7 @@ static int ecryptfs_threadfn(void *ignored)
mntget(req->lower_mnt);
(*req->lower_file) = dentry_open(
req->lower_dentry, req->lower_mnt,
- (O_RDWR | O_LARGEFILE));
+ (O_RDWR | O_LARGEFILE), current_cred());
req->flags |= ECRYPTFS_REQ_PROCESSED;
}
wake_up(&req->wait);
@@ -132,7 +132,8 @@ void ecryptfs_destroy_kthread(void)
*/
int ecryptfs_privileged_open(struct file **lower_file,
struct dentry *lower_dentry,
- struct vfsmount *lower_mnt)
+ struct vfsmount *lower_mnt,
+ const struct cred *cred)
{
struct ecryptfs_open_req *req;
int rc = 0;
@@ -143,7 +144,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
dget(lower_dentry);
mntget(lower_mnt);
(*lower_file) = dentry_open(lower_dentry, lower_mnt,
- (O_RDWR | O_LARGEFILE));
+ (O_RDWR | O_LARGEFILE), cred);
if (!IS_ERR(*lower_file))
goto out;
req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
@@ -184,7 +185,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
dget(lower_dentry);
mntget(lower_mnt);
(*lower_file) = dentry_open(lower_dentry, lower_mnt,
- (O_RDONLY | O_LARGEFILE));
+ (O_RDONLY | O_LARGEFILE), cred);
if (IS_ERR(*lower_file)) {
rc = PTR_ERR(*req->lower_file);
(*lower_file) = NULL;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 64d2ba980df..fd630713c5c 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -115,6 +115,7 @@ void __ecryptfs_printk(const char *fmt, ...)
*/
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
{
+ const struct cred *cred = current_cred();
struct ecryptfs_inode_info *inode_info =
ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
int rc = 0;
@@ -127,7 +128,7 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
rc = ecryptfs_privileged_open(&inode_info->lower_file,
- lower_dentry, lower_mnt);
+ lower_dentry, lower_mnt, cred);
if (rc || IS_ERR(inode_info->lower_file)) {
printk(KERN_ERR "Error opening lower persistent file "
"for lower_dentry [0x%p] and lower_mnt [0x%p]; "
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index c6983978a31..e0b0a4e28b9 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -361,6 +361,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
size_t msg_size;
struct nsproxy *nsproxy;
struct user_namespace *current_user_ns;
+ uid_t ctx_euid;
int rc;
if (msg->index >= ecryptfs_message_buf_len) {
@@ -385,8 +386,8 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
goto wake_up;
}
current_user_ns = nsproxy->user_ns;
- rc = ecryptfs_find_daemon_by_euid(&daemon, msg_ctx->task->euid,
- current_user_ns);
+ ctx_euid = task_euid(msg_ctx->task);
+ rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, current_user_ns);
rcu_read_unlock();
mutex_unlock(&ecryptfs_daemon_hash_mux);
if (rc) {
@@ -394,14 +395,14 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
printk(KERN_WARNING "%s: User [%d] received a "
"message response from process [0x%p] but does "
"not have a registered daemon\n", __func__,
- msg_ctx->task->euid, pid);
+ ctx_euid, pid);
goto wake_up;
}
- if (msg_ctx->task->euid != euid) {
+ if (ctx_euid != euid) {
rc = -EBADMSG;
printk(KERN_WARNING "%s: Received message from user "
"[%d]; expected message from user [%d]\n", __func__,
- euid, msg_ctx->task->euid);
+ euid, ctx_euid);
goto unlock;
}
if (current_user_ns != user_ns) {
@@ -415,7 +416,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
rc = -EBADMSG;
printk(KERN_ERR "%s: User [%d] sent a message response "
"from an unrecognized process [0x%p]\n",
- __func__, msg_ctx->task->euid, pid);
+ __func__, ctx_euid, pid);
goto unlock;
}
if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
@@ -464,14 +465,15 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,
struct ecryptfs_msg_ctx **msg_ctx)
{
struct ecryptfs_daemon *daemon;
+ uid_t euid = current_euid();
int rc;
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid,
current->nsproxy->user_ns);
if (rc || !daemon) {
rc = -ENOTCONN;
printk(KERN_ERR "%s: User [%d] does not have a daemon "
- "registered\n", __func__, current->euid);
+ "registered\n", __func__, euid);
goto out;
}
mutex_lock(&ecryptfs_msg_ctx_lists_mux);
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index b484792a099..047ac609695 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -42,11 +42,12 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
{
struct ecryptfs_daemon *daemon;
unsigned int mask = 0;
+ uid_t euid = current_euid();
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
/* TODO: Just use file->private_data? */
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid,
current->nsproxy->user_ns);
BUG_ON(rc || !daemon);
mutex_lock(&daemon->mux);
@@ -83,6 +84,7 @@ static int
ecryptfs_miscdev_open(struct inode *inode, struct file *file)
{
struct ecryptfs_daemon *daemon = NULL;
+ uid_t euid = current_euid();
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
@@ -93,10 +95,10 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
"count; rc = [%d]\n", __func__, rc);
goto out_unlock_daemon_list;
}
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid,
current->nsproxy->user_ns);
if (rc || !daemon) {
- rc = ecryptfs_spawn_daemon(&daemon, current->euid,
+ rc = ecryptfs_spawn_daemon(&daemon, euid,
current->nsproxy->user_ns,
task_pid(current));
if (rc) {
@@ -147,10 +149,11 @@ static int
ecryptfs_miscdev_release(struct inode *inode, struct file *file)
{
struct ecryptfs_daemon *daemon = NULL;
+ uid_t euid = current_euid();
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid,
current->nsproxy->user_ns);
BUG_ON(rc || !daemon);
mutex_lock(&daemon->mux);
@@ -246,11 +249,12 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
char packet_length[3];
size_t i;
size_t total_length;
+ uid_t euid = current_euid();
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
/* TODO: Just use file->private_data? */
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid,
current->nsproxy->user_ns);
BUG_ON(rc || !daemon);
mutex_lock(&daemon->mux);
@@ -290,7 +294,7 @@ check_list:
* message from the queue; try again */
goto check_list;
}
- BUG_ON(current->euid != daemon->euid);
+ BUG_ON(euid != daemon->euid);
BUG_ON(current->nsproxy->user_ns != daemon->user_ns);
BUG_ON(task_pid(current) != daemon->pid);
msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
@@ -414,6 +418,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
size_t packet_size, packet_size_length, i;
ssize_t sz = 0;
char *data;
+ uid_t euid = current_euid();
int rc;
if (count == 0)
@@ -463,8 +468,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
goto out_free;
}
rc = ecryptfs_miscdev_response(&data[i], packet_size,
- current->euid,
- current->nsproxy->user_ns,
+ euid, current->nsproxy->user_ns,
task_pid(current), seq);
if (rc)
printk(KERN_WARNING "%s: Failed to deliver miscdev "
diff --git a/fs/exec.c b/fs/exec.c
index 4e834f16d9d..32f13e29941 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -55,6 +55,7 @@
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/tlb.h>
+#include "internal.h"
#ifdef __alpha__
/* for /sbin/loader handling in search_binary_handler() */
@@ -980,7 +981,7 @@ int flush_old_exec(struct linux_binprm * bprm)
/* This is the point of no return */
current->sas_ss_sp = current->sas_ss_size = 0;
- if (current->euid == current->uid && current->egid == current->gid)
+ if (current_euid() == current_uid() && current_egid() == current_gid())
set_dumpable(current->mm, 1);
else
set_dumpable(current->mm, suid_dumpable);
@@ -1007,16 +1008,17 @@ int flush_old_exec(struct linux_binprm * bprm)
*/
current->mm->task_size = TASK_SIZE;
- if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) {
- suid_keys(current);
- set_dumpable(current->mm, suid_dumpable);
+ /* install the new credentials */
+ if (bprm->cred->uid != current_euid() ||
+ bprm->cred->gid != current_egid()) {
current->pdeath_signal = 0;
} else if (file_permission(bprm->file, MAY_READ) ||
- (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
- suid_keys(current);
+ bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) {
set_dumpable(current->mm, suid_dumpable);
}
+ current->personality &= ~bprm->per_clear;
+
/* An exec changes our domain. We are no longer part of the thread
group */
@@ -1033,13 +1035,50 @@ out:
EXPORT_SYMBOL(flush_old_exec);
+/*
+ * install the new credentials for this executable
+ */
+void install_exec_creds(struct linux_binprm *bprm)
+{
+ security_bprm_committing_creds(bprm);
+
+ commit_creds(bprm->cred);
+ bprm->cred = NULL;
+
+ /* cred_exec_mutex must be held at least to this point to prevent
+ * ptrace_attach() from altering our determination of the task's
+ * credentials; any time after this it may be unlocked */
+
+ security_bprm_committed_creds(bprm);
+}
+EXPORT_SYMBOL(install_exec_creds);
+
+/*
+ * determine how safe it is to execute the proposed program
+ * - the caller must hold current->cred_exec_mutex to protect against
+ * PTRACE_ATTACH
+ */
+void check_unsafe_exec(struct linux_binprm *bprm)
+{
+ struct task_struct *p = current;
+
+ bprm->unsafe = tracehook_unsafe_exec(p);
+
+ if (atomic_read(&p->fs->count) > 1 ||
+ atomic_read(&p->files->count) > 1 ||
+ atomic_read(&p->sighand->count) > 1)
+ bprm->unsafe |= LSM_UNSAFE_SHARE;
+}
+
/*
* Fill the binprm structure from the inode.
* Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
+ *
+ * This may be called multiple times for binary chains (scripts for example).
*/
int prepare_binprm(struct linux_binprm *bprm)
{
- int mode;
+ umode_t mode;
struct inode * inode = bprm->file->f_path.dentry->d_inode;
int retval;
@@ -1047,14 +1086,15 @@ int prepare_binprm(struct linux_binprm *bprm)
if (bprm->file->f_op == NULL)
return -EACCES;
- bprm->e_uid = current->euid;
- bprm->e_gid = current->egid;
+ /* clear any previous set[ug]id data from a previous binary */
+ bprm->cred->euid = current_euid();
+ bprm->cred->egid = current_egid();
- if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
+ if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
/* Set-uid? */
if (mode & S_ISUID) {
- current->personality &= ~PER_CLEAR_ON_SETID;
- bprm->e_uid = inode->i_uid;
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+ bprm->cred->euid = inode->i_uid;
}
/* Set-gid? */
@@ -1064,52 +1104,23 @@ int prepare_binprm(struct linux_binprm *bprm)
* executable.
*/
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
- current->personality &= ~PER_CLEAR_ON_SETID;
- bprm->e_gid = inode->i_gid;
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+ bprm->cred->egid = inode->i_gid;
}
}
/* fill in binprm security blob */
- retval = security_bprm_set(bprm);
+ retval = security_bprm_set_creds(bprm);
if (retval)
return retval;
+ bprm->cred_prepared = 1;
- memset(bprm->buf,0,BINPRM_BUF_SIZE);
- return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
+ memset(bprm->buf, 0, BINPRM_BUF_SIZE);
+ return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
}
EXPORT_SYMBOL(prepare_binprm);
-static int unsafe_exec(struct task_struct *p)
-{
- int unsafe = tracehook_unsafe_exec(p);
-
- if (atomic_read(&p->fs->count) > 1 ||
- atomic_read(&p->files->count) > 1 ||
- atomic_read(&p->sighand->count) > 1)
- unsafe |= LSM_UNSAFE_SHARE;
-
- return unsafe;
-}
-
-void compute_creds(struct linux_binprm *bprm)
-{
- int unsafe;
-
- if (bprm->e_uid != current->uid) {
- suid_keys(current);
- current->pdeath_signal = 0;
- }
- exec_keys(current);
-
- task_lock(current);
- unsafe = unsafe_exec(current);
- security_bprm_apply_creds(bprm, unsafe);
- task_unlock(current);
- security_bprm_post_apply_creds(bprm);
-}
-EXPORT_SYMBOL(compute_creds);
-
/*
* Arguments are '\0' separated strings found at the location bprm->p
* points to; chop off the first by relocating brpm->p to right after
@@ -1262,6 +1273,8 @@ EXPORT_SYMBOL(search_binary_handler);
void free_bprm(struct linux_binprm *bprm)
{
free_arg_pages(bprm);
+ if (bprm->cred)
+ abort_creds(bprm->cred);
kfree(bprm);
}
@@ -1287,10 +1300,20 @@ int do_execve(char * filename,
if (!bprm)
goto out_files;
+ retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+ if (retval < 0)
+ goto out_free;
+
+ retval = -ENOMEM;
+ bprm->cred = prepare_exec_creds();
+ if (!bprm->cred)
+ goto out_unlock;
+ check_unsafe_exec(bprm);
+
file = open_exec(filename);
retval = PTR_ERR(file);
if (IS_ERR(file))
- goto out_kfree;
+ goto out_unlock;
sched_exec();
@@ -1304,14 +1327,10 @@ int do_execve(char * filename,
bprm->argc = count(argv, MAX_ARG_STRINGS);
if ((retval = bprm->argc) < 0)
- goto out_mm;
+ goto out;
bprm->envc = count(envp, MAX_ARG_STRINGS);
if ((retval = bprm->envc) < 0)
- goto out_mm;
-
- retval = security_bprm_alloc(bprm);
- if (retval)
goto out;
retval = prepare_binprm(bprm);
@@ -1333,21 +1352,18 @@ int do_execve(char * filename,
current->flags &= ~PF_KTHREAD;
retval = search_binary_handler(bprm,regs);
- if (retval >= 0) {
- /* execve success */
- security_bprm_free(bprm);
- acct_update_integrals(current);
- free_bprm(bprm);
- if (displaced)
- put_files_struct(displaced);
- return retval;
- }
+ if (retval < 0)
+ goto out;
-out:
- if (bprm->security)
- security_bprm_free(bprm);
+ /* execve succeeded */
+ mutex_unlock(&current->cred_exec_mutex);
+ acct_update_integrals(current);
+ free_bprm(bprm);
+ if (displaced)
+ put_files_struct(displaced);
+ return retval;
-out_mm:
+out:
if (bprm->mm)
mmput (bprm->mm);
@@ -1356,7 +1372,11 @@ out_file:
allow_write_access(bprm->file);
fput(bprm->file);
}
-out_kfree:
+
+out_unlock:
+ mutex_unlock(&current->cred_exec_mutex);
+
+out_free:
free_bprm(bprm);
out_files:
@@ -1388,6 +1408,7 @@ EXPORT_SYMBOL(set_binfmt);
*/
static int format_corename(char *corename, long signr)
{
+ const struct cred *cred = current_cred();
const char *pat_ptr = core_pattern;
int ispipe = (*pat_ptr == '|');
char *out_ptr = corename;
@@ -1424,7 +1445,7 @@ static int format_corename(char *corename, long signr)
/* uid */
case 'u':
rc = snprintf(out_ptr, out_end - out_ptr,
- "%d", current->uid);
+ "%d", cred->uid);
if (rc > out_end - out_ptr)
goto out;
out_ptr += rc;
@@ -1432,7 +1453,7 @@ static int format_corename(char *corename, long signr)
/* gid */
case 'g':
rc = snprintf(out_ptr, out_end - out_ptr,
- "%d", current->gid);
+ "%d", cred->gid);
if (rc > out_end - out_ptr)
goto out;
out_ptr += rc;
@@ -1708,8 +1729,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
struct linux_binfmt * binfmt;
struct inode * inode;
struct file * file;
+ const struct cred *old_cred;
+ struct cred *cred;
int retval = 0;
- int fsuid = current->fsuid;
int flag = 0;
int ispipe = 0;
unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
@@ -1722,12 +1744,20 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
binfmt = current->binfmt;
if (!binfmt || !binfmt->core_dump)
goto fail;
+
+ cred = prepare_creds();
+ if (!cred) {
+ retval = -ENOMEM;
+ goto fail;
+ }
+
down_write(&mm->mmap_sem);
/*
* If another thread got here first, or we are not dumpable, bail out.
*/
if (mm->core_state || !get_dumpable(mm)) {
up_write(&mm->mmap_sem);
+ put_cred(cred);
goto fail;
}
@@ -1738,12 +1768,16 @@ 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 */
+ cred->fsuid = 0; /* Dump root private */
}
retval = coredump_wait(exit_code, &core_state);
- if (retval < 0)
+ if (retval < 0) {
+ put_cred(cred);
goto fail;
+ }
+
+ old_cred = override_creds(cred);
/*
* Clear any false indication of pending signals that might
@@ -1815,7 +1849,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
* Dont allow local users get cute and trick others to coredump
* into their pre-created files:
*/
- if (inode->i_uid != current->fsuid)
+ if (inode->i_uid != current_fsuid())
goto close_fail;
if (!file->f_op)
goto close_fail;
@@ -1834,7 +1868,8 @@ fail_unlock:
if (helper_argv)
argv_free(helper_argv);
- current->fsuid = fsuid;
+ revert_creds(old_cred);
+ put_cred(cred);
coredump_finish(mm);
fail:
return retval;
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 80246bad1b7..ec1fb918200 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/namei.h>
+#include <linux/sched.h>
#define dprintk(fmt, args...) do{}while(0)
@@ -249,6 +250,7 @@ static int filldir_one(void * __buf, const char * name, int len,
static int get_name(struct vfsmount *mnt, struct dentry *dentry,
char *name, struct dentry *child)
{
+ const struct cred *cred = current_cred();
struct inode *dir = dentry->d_inode;
int error;
struct file *file;
@@ -263,7 +265,7 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry,
/*
* Open the directory ...
*/
- file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY);
+ file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, cred);
error = PTR_ERR(file);
if (IS_ERR(file))
goto out;
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 6dac7ba2d22..4a29d637608 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -1193,7 +1193,7 @@ static int ext2_has_free_blocks(struct ext2_sb_info *sbi)
free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
- sbi->s_resuid != current->fsuid &&
+ sbi->s_resuid != current_fsuid() &&
(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
return 0;
}
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index f5974134676..8d0add62587 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -550,7 +550,7 @@ got:
sb->s_dirt = 1;
mark_buffer_dirty(bh2);
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
if (test_opt (sb, GRPID))
inode->i_gid = dir->i_gid;
else if (dir->i_mode & S_ISGID) {
@@ -558,7 +558,7 @@ got:
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
inode->i_mode = mode;
inode->i_ino = ino;
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index f5b57a2ca35..0dbf1c04847 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1422,7 +1422,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
- sbi->s_resuid != current->fsuid &&
+ sbi->s_resuid != current_fsuid() &&
(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
return 0;
}
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 47b678d73e7..490bd0ed789 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -539,7 +539,7 @@ got:
percpu_counter_inc(&sbi->s_dirs_counter);
sb->s_dirt = 1;
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
if (test_opt (sb, GRPID))
inode->i_gid = dir->i_gid;
else if (dir->i_mode & S_ISGID) {
@@ -547,7 +547,7 @@ got:
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
inode->i_mode = mode;
inode->i_ino = ino;
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index d2003cdc36a..a932b9a2924 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -624,7 +624,7 @@ int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
return 1;
/* Hm, nope. Are (enough) root reserved blocks available? */
- if (sbi->s_resuid == current->fsuid ||
+ if (sbi->s_resuid == current_fsuid() ||
((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) ||
capable(CAP_SYS_RESOURCE)) {
if (free_blocks >= (nblocks + dirty_blocks))
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 2a117e286e5..08cac9fcace 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -787,7 +787,7 @@ got:
spin_unlock(sb_bgl_lock(sbi, flex_group));
}
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
if (test_opt(sb, GRPID))
inode->i_gid = dir->i_gid;
else if (dir->i_mode & S_ISGID) {
@@ -795,7 +795,7 @@ got:
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
inode->i_mode = mode;
inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
diff --git a/fs/fat/file.c b/fs/fat/file.c
index f06a4e525ec..0a7f4a9918b 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -304,7 +304,7 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
{
mode_t allow_utime = sbi->options.allow_utime;
- if (current->fsuid != inode->i_uid) {
+ if (current_fsuid() != inode->i_uid) {
if (in_group_p(inode->i_gid))
allow_utime >>= 3;
if (allow_utime & MAY_WRITE)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index bdd8fb7be2c..d937aaf7737 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -926,8 +926,8 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
opts->isvfat = is_vfat;
- opts->fs_uid = current->uid;
- opts->fs_gid = current->gid;
+ opts->fs_uid = current_uid();
+ opts->fs_gid = current_gid();
opts->fs_fmask = opts->fs_dmask = current->fs->umask;
opts->allow_utime = -1;
opts->codepage = fat_default_codepage;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index ac4f7db9f13..87c39f1f081 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -205,13 +205,14 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
int __f_setown(struct file *filp, struct pid *pid, enum pid_type type,
int force)
{
+ const struct cred *cred = current_cred();
int err;
err = security_file_set_fowner(filp);
if (err)
return err;
- f_modown(filp, pid, type, current->uid, current->euid, force);
+ f_modown(filp, pid, type, cred->uid, cred->euid, force);
return 0;
}
EXPORT_SYMBOL(__f_setown);
@@ -400,10 +401,17 @@ static const long band_table[NSIGPOLL] = {
static inline int sigio_perm(struct task_struct *p,
struct fown_struct *fown, int sig)
{
- return (((fown->euid == 0) ||
- (fown->euid == p->suid) || (fown->euid == p->uid) ||
- (fown->uid == p->suid) || (fown->uid == p->uid)) &&
- !security_file_send_sigiotask(p, fown, sig));
+ const struct cred *cred;
+ int ret;
+
+ rcu_read_lock();
+ cred = __task_cred(p);
+ ret = ((fown->euid == 0 ||
+ fown->euid == cred->suid || fown->euid == cred->uid ||
+ fown->uid == cred->suid || fown->uid == cred->uid) &&
+ !security_file_send_sigiotask(p, fown, sig));
+ rcu_read_unlock();
+ return ret;
}
static void send_sigio_to_task(struct task_struct *p,
diff --git a/fs/file_table.c b/fs/file_table.c
index 5ad0eca6eea..0fbcacc3ea7 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -36,7 +36,9 @@ static struct percpu_counter nr_files __cacheline_aligned_in_smp;
static inline void file_free_rcu(struct rcu_head *head)
{
- struct file *f = container_of(head, struct file, f_u.fu_rcuhead);
+ struct file *f = container_of(head, struct file, f_u.fu_rcuhead);
+
+ put_cred(f->f_cred);
kmem_cache_free(filp_cachep, f);
}
@@ -94,7 +96,7 @@ int proc_nr_files(ctl_table *table, int write, struct file *filp,
*/
struct file *get_empty_filp(void)
{
- struct task_struct *tsk;
+ const struct cred *cred = current_cred();
static int old_max;
struct file * f;
@@ -118,12 +120,10 @@ struct file *get_empty_filp(void)
if (security_file_alloc(f))
goto fail_sec;
- tsk = current;
INIT_LIST_HEAD(&f->f_u.fu_list);
atomic_long_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_cred(cred);
eventpoll_init_file(f);
/* f->f_version: 0 */
return f;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index b72361479be..fba571648a8 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -87,8 +87,8 @@ static void __fuse_put_request(struct fuse_req *req)
static void fuse_req_init_context(struct fuse_req *req)
{
- req->in.h.uid = current->fsuid;
- req->in.h.gid = current->fsgid;
+ req->in.h.uid = current_fsuid();
+ req->in.h.gid = current_fsgid();
req->in.h.pid = current->pid;
}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index fd03330cade..95bc22bdd06 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -869,18 +869,25 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
*/
int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
{
+ const struct cred *cred;
+ int ret;
+
if (fc->flags & FUSE_ALLOW_OTHER)
return 1;
- if (task->euid == fc->user_id &&
- task->suid == fc->user_id &&
- task->uid == fc->user_id &&
- task->egid == fc->group_id &&
- task->sgid == fc->group_id &&
- task->gid == fc->group_id)
- return 1;
+ rcu_read_lock();
+ ret = 0;
+ cred = __task_cred(task);
+ if (cred->euid == fc->user_id &&
+ cred->suid == fc->user_id &&
+ cred->uid == fc->user_id &&
+ cred->egid == fc->group_id &&
+ cred->sgid == fc->group_id &&
+ cred->gid == fc->group_id)
+ ret = 1;
+ rcu_read_unlock();
- return 0;
+ return ret;
}
static int fuse_access(struct inode *inode, int mask)
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 7cee695fa44..d57616840e8 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -705,18 +705,18 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
(dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
if (S_ISDIR(*mode))
*mode |= S_ISUID;
- else if (dip->i_inode.i_uid != current->fsuid)
+ else if (dip->i_inode.i_uid != current_fsuid())
*mode &= ~07111;
*uid = dip->i_inode.i_uid;
} else
- *uid = current->fsuid;
+ *uid = current_fsuid();
if (dip->i_inode.i_mode & S_ISGID) {
if (S_ISDIR(*mode))
*mode |= S_ISGID;
*gid = dip->i_inode.i_gid;
} else
- *gid = current->fsgid;
+ *gid = current_fsgid();
}
static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
@@ -1124,8 +1124,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
return -EPERM;
if ((dip->i_inode.i_mode & S_ISVTX) &&
- dip->i_inode.i_uid != current->fsuid &&
- ip->i_inode.i_uid != current->fsuid && !capable(CAP_FOWNER))
+ dip->i_inode.i_uid != current_fsuid() &&
+ ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER))
return -EPERM;
if (IS_APPEND(&dip->i_inode))
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index c69b7ac75bf..9435dda8f1e 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -155,8 +155,8 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
inode->i_ino = HFS_SB(sb)->next_id++;
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_nlink = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
HFS_I(inode)->flags = 0;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 3c7c7637719..c8b5acf4b0b 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -210,8 +210,8 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
int tmp, token;
/* initialize the sb with defaults */
- hsb->s_uid = current->uid;
- hsb->s_gid = current->gid;
+ hsb->s_uid = current_uid();
+ hsb->s_gid = current_gid();
hsb->s_file_umask = 0133;
hsb->s_dir_umask = 0022;
hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f); /* == '????' */
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index b207f0e6fc2..f105ee9e1cc 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -296,8 +296,8 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_nlink = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 9699c56d323..bab7f8d1bdf 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -49,8 +49,8 @@ void hfsplus_fill_defaults(struct hfsplus_sb_info *opts)
opts->creator = HFSPLUS_DEF_CR_TYPE;
opts->type = HFSPLUS_DEF_CR_TYPE;
opts->umask = current->fs->umask;
- opts->uid = current->uid;
- opts->gid = current->gid;
+ opts->uid = current_uid();
+ opts->gid = current_gid();
opts->part = -1;
opts->session = -1;
}
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 10783f3d265..b649232dde9 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -92,11 +92,11 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
inc_nlink(dir);
insert_inode_hash(result);
- if (result->i_uid != current->fsuid ||
- result->i_gid != current->fsgid ||
+ if (result->i_uid != current_fsuid() ||
+ result->i_gid != current_fsgid() ||
result->i_mode != (mode | S_IFDIR)) {
- result->i_uid = current->fsuid;
- result->i_gid = current->fsgid;
+ result->i_uid = current_fsuid();
+ result->i_gid = current_fsgid();
result->i_mode = mode | S_IFDIR;
hpfs_write_inode_nolock(result);
}
@@ -184,11 +184,11 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
insert_inode_hash(result);
- if (result->i_uid != current->fsuid ||
- result->i_gid != current->fsgid ||
+ if (result->i_uid != current_fsuid() ||
+ result->i_gid != current_fsgid() ||
result->i_mode != (mode | S_IFREG)) {
- result->i_uid = current->fsuid;
- result->i_gid = current->fsgid;
+ result->i_uid = current_fsuid();
+ result->i_gid = current_fsgid();
result->i_mode = mode | S_IFREG;
hpfs_write_inode_nolock(result);
}
@@ -247,8 +247,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
result->i_mtime.tv_nsec = 0;
result->i_atime.tv_nsec = 0;
hpfs_i(result)->i_ea_size = 0;
- result->i_uid = current->fsuid;
- result->i_gid = current->fsgid;
+ result->i_uid = current_fsuid();
+ result->i_gid = current_fsgid();
result->i_nlink = 1;
result->i_size = 0;
result->i_blocks = 1;
@@ -325,8 +325,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
result->i_atime.tv_nsec = 0;
hpfs_i(result)->i_ea_size = 0;
result->i_mode = S_IFLNK | 0777;
- result->i_uid = current->fsuid;
- result->i_gid = current->fsgid;
+ result->i_uid = current_fsuid();
+ result->i_gid = current_fsgid();
result->i_blocks = 1;
result->i_nlink = 1;
result->i_size = strlen(symlink);
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 29ad461d568..0d049b8919c 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -475,8 +475,8 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
init_MUTEX(&sbi->hpfs_creation_de);
- uid = current->uid;
- gid = current->gid;
+ uid = current_uid();
+ gid = current_gid();
umask = current->fs->umask;
lowercase = 0;
conv = CONV_BINARY;
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 2b3d1828db9..b278f7f5202 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -426,6 +426,7 @@ static int file_mode(int fmode)
static int hppfs_open(struct inode *inode, struct file *file)
{
+ const struct cred *cred = file->f_cred;
struct hppfs_private *data;
struct vfsmount *proc_mnt;
struct dentry *proc_dentry;
@@ -446,7 +447,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
/* XXX This isn't closed anywhere */
data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
- file_mode(file->f_mode));
+ file_mode(file->f_mode), cred);
err = PTR_ERR(data->proc_file);
if (IS_ERR(data->proc_file))
goto out_free1;
@@ -489,6 +490,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
static int hppfs_dir_open(struct inode *inode, struct file *file)
{
+ const struct cred *cred = file->f_cred;
struct hppfs_private *data;
struct vfsmount *proc_mnt;
struct dentry *proc_dentry;
@@ -502,7 +504,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
proc_dentry = HPPFS_I(inode)->proc_dentry;
proc_mnt = inode->i_sb->s_fs_info;
data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
- file_mode(file->f_mode));
+ file_mode(file->f_mode), cred);
err = PTR_ERR(data->proc_file);
if (IS_ERR(data->proc_file))
goto out_free;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 61edc701b0e..7d479ce3ace 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -551,9 +551,9 @@ static int hugetlbfs_mknod(struct inode *dir,
if (S_ISDIR(mode))
mode |= S_ISGID;
} else {
- gid = current->fsgid;
+ gid = current_fsgid();
}
- inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid, gid, mode, dev);
+ inode = hugetlbfs_get_inode(dir->i_sb, current_fsuid(), gid, mode, dev);
if (inode) {
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
d_instantiate(dentry, inode);
@@ -586,9 +586,9 @@ static int hugetlbfs_symlink(struct inode *dir,
if (dir->i_mode & S_ISGID)
gid = dir->i_gid;
else
- gid = current->fsgid;
+ gid = current_fsgid();
- inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid,
+ inode = hugetlbfs_get_inode(dir->i_sb, current_fsuid(),
gid, S_IFLNK|S_IRWXUGO, 0);
if (inode) {
int l = strlen(symname)+1;
@@ -854,8 +854,8 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
config.nr_blocks = -1; /* No limit on size by default */
config.nr_inodes = -1; /* No limit on number of inodes by default */
- config.uid = current->fsuid;
- config.gid = current->fsgid;
+ config.uid = current_fsuid();
+ config.gid = current_fsgid();
config.mode = 0755;
config.hstate = &default_hstate;
ret = hugetlbfs_parse_options(data, &config);
@@ -951,6 +951,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
struct inode *inode;
struct dentry *dentry, *root;
struct qstr quick_string;
+ struct user_struct *user = current_user();
if (!hugetlbfs_vfsmount)
return ERR_PTR(-ENOENT);
@@ -958,7 +959,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
if (!can_do_hugetlb_shm())
return ERR_PTR(-EPERM);
- if (!user_shm_lock(size, current->user))
+ if (!user_shm_lock(size, user))
return ERR_PTR(-ENOMEM);
root = hugetlbfs_vfsmount->mnt_root;
@@ -970,8 +971,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
goto out_shm_unlock;
error = -ENOSPC;
- inode = hugetlbfs_get_inode(root->d_sb, current->fsuid,
- current->fsgid, S_IFREG | S_IRWXUGO, 0);
+ inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(),
+ current_fsgid(), S_IFREG | S_IRWXUGO, 0);
if (!inode)
goto out_dentry;
@@ -998,7 +999,7 @@ out_inode:
out_dentry:
dput(dentry);
out_shm_unlock:
- user_shm_unlock(size, current->user);
+ user_shm_unlock(size, user);
return ERR_PTR(error);
}
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index d367e9b9286..e2425bbd871 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -601,7 +601,7 @@ asmlinkage long sys_inotify_init1(int flags)
goto out_put_fd;
}
- user = get_uid(current->user);
+ user = get_current_user();
if (unlikely(atomic_read(&user->inotify_devs) >=
inotify_max_user_instances)) {
ret = -EMFILE;
diff --git a/fs/internal.h b/fs/internal.h
index 80aa9a02337..53af885f173 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -10,6 +10,7 @@
*/
struct super_block;
+struct linux_binprm;
/*
* block_dev.c
@@ -40,6 +41,11 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
extern void __init chrdev_init(void);
/*
+ * exec.c
+ */
+extern void check_unsafe_exec(struct linux_binprm *);
+
+/*
* namespace.c
*/
extern int copy_mount_options(const void __user *, unsigned long *);
diff --git a/fs/ioprio.c b/fs/ioprio.c
index da3cc460d4d..3569e0ad86a 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -31,10 +31,16 @@ static int set_task_ioprio(struct task_struct *task, int ioprio)
{
int err;
struct io_context *ioc;
+ const struct cred *cred = current_cred(), *tcred;
- if (task->uid != current->euid &&
- task->uid != current->uid && !capable(CAP_SYS_NICE))
+ rcu_read_lock();
+ tcred = __task_cred(task);
+ if (tcred->uid != cred->euid &&
+ tcred->uid != cred->uid && !capable(CAP_SYS_NICE)) {
+ rcu_read_unlock();
return -EPERM;
+ }
+ rcu_read_unlock();
err = security_task_setioprio(task, ioprio);
if (err)
@@ -123,7 +129,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
break;
case IOPRIO_WHO_USER:
if (!who)
- user = current->user;
+ user = current_user();
else
user = find_user(who);
@@ -131,7 +137,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
break;
do_each_thread(g, p) {
- if (p->uid != who)
+ if (__task_cred(p)->uid != who)
continue;
ret = set_task_ioprio(p, ioprio);
if (ret)
@@ -216,7 +222,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
break;
case IOPRIO_WHO_USER:
if (!who)
- user = current->user;
+ user = current_user();
else
user = find_user(who);
@@ -224,7 +230,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
break;
do_each_thread(g, p) {
- if (p->uid != user->uid)
+ if (__task_cred(p)->uid != user->uid)
continue;
tmpio = get_task_ioprio(p);
if (tmpio < 0)
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index ed6574bee51..70022fd1c53 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -93,13 +93,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
return ERR_PTR(rc);
}
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
if (parent->i_mode & S_ISGID) {
inode->i_gid = parent->i_gid;
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
/*
* New inodes need to save sane values on disk when
diff --git a/fs/locks.c b/fs/locks.c
index 09062e3ff10..46a2e12f7d4 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1349,7 +1349,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
struct inode *inode = dentry->d_inode;
int error, rdlease_count = 0, wrlease_count = 0;
- if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
+ if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE))
return -EACCES;
if (!S_ISREG(inode->i_mode))
return -EINVAL;
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 703cc35e04b..3aebe322271 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -262,8 +262,8 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
iput(inode);
return NULL;
}
- inode->i_uid = current->fsuid;
- inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current_fsgid();
inode->i_ino = j;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
inode->i_blocks = 0;
diff --git a/fs/namei.c b/fs/namei.c
index 09ce58e49e7..42d7b760693 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -186,7 +186,7 @@ int generic_permission(struct inode *inode, int mask,
mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
- if (current->fsuid == inode->i_uid)
+ if (current_fsuid() == inode->i_uid)
mode >>= 6;
else {
if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
@@ -441,7 +441,7 @@ static int exec_permission_lite(struct inode *inode)
if (inode->i_op && inode->i_op->permission)
return -EAGAIN;
- if (current->fsuid == inode->i_uid)
+ if (current_fsuid() == inode->i_uid)
mode >>= 6;
else if (in_group_p(inode->i_gid))
mode >>= 3;
@@ -1334,11 +1334,13 @@ static int user_path_parent(int dfd, const char __user *path,
*/
static inline int check_sticky(struct inode *dir, struct inode *inode)
{
+ uid_t fsuid = current_fsuid();
+
if (!(dir->i_mode & S_ISVTX))
return 0;
- if (inode->i_uid == current->fsuid)
+ if (inode->i_uid == fsuid)
return 0;
- if (dir->i_uid == current->fsuid)
+ if (dir->i_uid == fsuid)
return 0;
return !capable(CAP_FOWNER);
}
diff --git a/fs/namespace.c b/fs/namespace.c
index 65b3dc844c8..1c09cab8f7c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1176,7 +1176,7 @@ static int mount_is_safe(struct path *path)
if (S_ISLNK(path->dentry->d_inode->i_mode))
return -EPERM;
if (path->dentry->d_inode->i_mode & S_ISVTX) {
- if (current->uid != path->dentry->d_inode->i_uid)
+ if (current_uid() != path->dentry->d_inode->i_uid)
return -EPERM;
}
if (inode_permission(path->dentry->d_inode, MAY_WRITE))
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 3a97c95e1ca..6d04e050c74 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -40,10 +40,10 @@ ncp_get_fs_info(struct ncp_server * server, struct file *file,
struct inode *inode = file->f_path.dentry->d_inode;
struct ncp_fs_info info;
- if ((file_permission(file, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (file_permission(file, MAY_WRITE) != 0
+ && current_uid() != server->m.mounted_uid)
return -EACCES;
- }
+
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -70,10 +70,10 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
struct inode *inode = file->f_path.dentry->d_inode;
struct ncp_fs_info_v2 info2;
- if ((file_permission(file, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (file_permission(file, MAY_WRITE) != 0
+ && current_uid() != server->m.mounted_uid)
return -EACCES;
- }
+
if (copy_from_user(&info2, arg, sizeof(info2)))
return -EFAULT;
@@ -141,10 +141,10 @@ ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
struct inode *inode = file->f_path.dentry->d_inode;
struct compat_ncp_fs_info_v2 info2;
- if ((file_permission(file, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (file_permission(file, MAY_WRITE) != 0
+ && current_uid() != server->m.mounted_uid)
return -EACCES;
- }
+
if (copy_from_user(&info2, arg, sizeof(info2)))
return -EFAULT;
@@ -270,16 +270,17 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
struct ncp_ioctl_request request;
char* bouncebuffer;
void __user *argp = (void __user *)arg;
+ uid_t uid = current_uid();
switch (cmd) {
#ifdef CONFIG_COMPAT
case NCP_IOC_NCPREQUEST_32:
#endif
case NCP_IOC_NCPREQUEST:
- if ((file_permission(filp, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (file_permission(filp, MAY_WRITE) != 0
+ && uid != server->m.mounted_uid)
return -EACCES;
- }
+
#ifdef CONFIG_COMPAT
if (cmd == NCP_IOC_NCPREQUEST_32) {
struct compat_ncp_ioctl_request request32;
@@ -356,10 +357,10 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
case NCP_IOC_GETMOUNTUID16:
case NCP_IOC_GETMOUNTUID32:
case NCP_IOC_GETMOUNTUID64:
- if ((file_permission(filp, MAY_READ) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (file_permission(filp, MAY_READ) != 0
+ && uid != server->m.mounted_uid)
return -EACCES;
- }
+
if (cmd == NCP_IOC_GETMOUNTUID16) {
u16 uid;
SET_UID(uid, server->m.mounted_uid);
@@ -380,11 +381,10 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
{
struct ncp_setroot_ioctl sr;
- if ((file_permission(filp, MAY_READ) != 0)
- && (current->uid != server->m.mounted_uid))
- {
+ if (file_permission(filp, MAY_READ) != 0
+ && uid != server->m.mounted_uid)
return -EACCES;
- }
+
if (server->m.mounted_vol[0]) {
struct dentry* dentry = inode->i_sb->s_root;
@@ -408,6 +408,7 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
return -EFAULT;
return 0;
}
+
case NCP_IOC_SETROOT:
{
struct ncp_setroot_ioctl sr;
@@ -455,11 +456,10 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
#ifdef CONFIG_NCPFS_PACKET_SIGNING
case NCP_IOC_SIGN_INIT:
- if ((file_permission(filp, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid))
- {
+ if (file_permission(filp, MAY_WRITE) != 0
+ && uid != server->m.mounted_uid)
return -EACCES;
- }
+
if (argp) {
if (server->sign_wanted)
{
@@ -478,24 +478,22 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
return 0;
case NCP_IOC_SIGN_WANTED:
- if ((file_permission(filp, MAY_READ) != 0)
- && (current->uid != server->m.mounted_uid))
- {
+ if (file_permission(filp, MAY_READ) != 0
+ && uid != server->m.mounted_uid)
return -EACCES;
- }
if (put_user(server->sign_wanted, (int __user *)argp))
return -EFAULT;
return 0;
+
case NCP_IOC_SET_SIGN_WANTED:
{
int newstate;
- if ((file_permission(filp, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid))
- {
+ if (file_permission(filp, MAY_WRITE) != 0
+ && uid != server->m.mounted_uid)
return -EACCES;
- }
+
/* get only low 8 bits... */
if (get_user(newstate, (unsigned char __user *)argp))
return -EFAULT;
@@ -512,11 +510,10 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp,
#ifdef CONFIG_NCPFS_IOCTL_LOCKING
case NCP_IOC_LOCKUNLOCK:
- if ((file_permission(filp, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid))
- {
+ if (file_permission(filp, MAY_WRITE) != 0
+ && uid != server->m.mounted_uid)
return -EACCES;
- }
+
{
struct ncp_lock_ioctl rqdata;
@@ -585,9 +582,8 @@ outrel:
#ifdef CONFIG_COMPAT
case NCP_IOC_GETOBJECTNAME_32:
- if (current->uid != server->m.mounted_uid) {
+ if (uid != server->m.mounted_uid)
return -EACCES;
- }
{
struct compat_ncp_objectname_ioctl user;
size_t outl;
@@ -609,10 +605,10 @@ outrel:
return 0;
}
#endif
+
case NCP_IOC_GETOBJECTNAME:
- if (current->uid != server->m.mounted_uid) {
+ if (uid != server->m.mounted_uid)
return -EACCES;
- }
{
struct ncp_objectname_ioctl user;
size_t outl;
@@ -633,13 +629,13 @@ outrel:
return -EFAULT;
return 0;
}
+
#ifdef CONFIG_COMPAT
case NCP_IOC_SETOBJECTNAME_32:
#endif
case NCP_IOC_SETOBJECTNAME:
- if (current->uid != server->m.mounted_uid) {
+ if (uid != server->m.mounted_uid)
return -EACCES;
- }
{
struct ncp_objectname_ioctl user;
void* newname;
@@ -691,13 +687,13 @@ outrel:
kfree(oldname);
return 0;
}
+
#ifdef CONFIG_COMPAT
case NCP_IOC_GETPRIVATEDATA_32:
#endif
case NCP_IOC_GETPRIVATEDATA:
- if (current->uid != server->m.mounted_uid) {
+ if (uid != server->m.mounted_uid)
return -EACCES;
- }
{
struct ncp_privatedata_ioctl user;
size_t outl;
@@ -736,13 +732,13 @@ outrel:
return 0;
}
+
#ifdef CONFIG_COMPAT
case NCP_IOC_SETPRIVATEDATA_32:
#endif
case NCP_IOC_SETPRIVATEDATA:
- if (current->uid != server->m.mounted_uid) {
+ if (uid != server->m.mounted_uid)
return -EACCES;
- }
{
struct ncp_privatedata_ioctl user;
void* new;
@@ -794,9 +790,10 @@ outrel:
#endif /* CONFIG_NCPFS_NLS */
case NCP_IOC_SETDENTRYTTL:
- if ((file_permission(filp, MAY_WRITE) != 0) &&
- (current->uid != server->m.mounted_uid))
+ if (file_permission(filp, MAY_WRITE) != 0 &&
+ uid != server->m.mounted_uid)
return -EACCES;
+
{
u_int32_t user;
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index aed8145d908..cc4ef2642a5 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -41,7 +41,8 @@ static struct file *do_open(char *name, int flags)
error = may_open(&nd, MAY_WRITE, FMODE_WRITE);
if (!error)
- return dentry_open(nd.path.dentry, nd.path.mnt, flags);
+ return dentry_open(nd.path.dentry, nd.path.mnt, flags,
+ current_cred());
path_put(&nd.path);
return ERR_PTR(error);
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 294992e9bf6..0184fe9b514 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -27,53 +27,70 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
{
- struct svc_cred cred = rqstp->rq_cred;
+ struct group_info *rqgi;
+ struct group_info *gi;
+ struct cred *new;
int i;
int flags = nfsexp_flags(rqstp, exp);
int ret;
+ /* discard any old override before preparing the new set */
+ revert_creds(get_cred(current->real_cred));
+ new = prepare_creds();
+ if (!new)
+ return -ENOMEM;
+
+ new->fsuid = rqstp->rq_cred.cr_uid;
+ new->fsgid = rqstp->rq_cred.cr_gid;
+
+ rqgi = rqstp->rq_cred.cr_group_info;
+
if (flags & NFSEXP_ALLSQUASH) {
- cred.cr_uid = exp->ex_anon_uid;
- cred.cr_gid = exp->ex_anon_gid;
- cred.cr_group_info = groups_alloc(0);
+ new->fsuid = exp->ex_anon_uid;
+ new->fsgid = exp->ex_anon_gid;
+ gi = groups_alloc(0);
} else if (flags & NFSEXP_ROOTSQUASH) {
- struct group_info *gi;
- if (!cred.cr_uid)
- cred.cr_uid = exp->ex_anon_uid;
- if (!cred.cr_gid)
- cred.cr_gid = exp->ex_anon_gid;
- gi = groups_alloc(cred.cr_group_info->ngroups);
- if (gi)
- for (i = 0; i < cred.cr_group_info->ngroups; i++) {
- if (!GROUP_AT(cred.cr_group_info, i))
- GROUP_AT(gi, i) = exp->ex_anon_gid;
- else
- GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i);
- }
- cred.cr_group_info = gi;
- } else
- get_group_info(cred.cr_group_info);
-
- if (cred.cr_uid != (uid_t) -1)
- current->fsuid = cred.cr_uid;
- else
- current->fsuid = exp->ex_anon_uid;
- if (cred.cr_gid != (gid_t) -1)
- current->fsgid = cred.cr_gid;
- else
- current->fsgid = exp->ex_anon_gid;
+ if (!new->fsuid)
+ new->fsuid = exp->ex_anon_uid;
+ if (!new->fsgid)
+ new->fsgid = exp->ex_anon_gid;
- if (!cred.cr_group_info)
- return -ENOMEM;
- ret = set_current_groups(cred.cr_group_info);
- put_group_info(cred.cr_group_info);
- if ((cred.cr_uid)) {
- current->cap_effective =
- cap_drop_nfsd_set(current->cap_effective);
+ gi = groups_alloc(rqgi->ngroups);
+ if (!gi)
+ goto oom;
+
+ for (i = 0; i < rqgi->ngroups; i++) {
+ if (!GROUP_AT(rqgi, i))
+ GROUP_AT(gi, i) = exp->ex_anon_gid;
+ else
+ GROUP_AT(gi, i) = GROUP_AT(rqgi, i);
+ }
} else {
- current->cap_effective =
- cap_raise_nfsd_set(current->cap_effective,
- current->cap_permitted);
+ gi = get_group_info(rqgi);
}
+
+ if (new->fsuid == (uid_t) -1)
+ new->fsuid = exp->ex_anon_uid;
+ if (new->fsgid == (gid_t) -1)
+ new->fsgid = exp->ex_anon_gid;
+
+ ret = set_groups(new, gi);
+ put_group_info(gi);
+ if (!ret)
+ goto error;
+
+ if (new->uid)
+ new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
+ else
+ new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
+ new->cap_permitted);
+ put_cred(override_creds(new));
+ return 0;
+
+oom:
+ ret = -ENOMEM;
+error:
+ abort_creds(new);
return ret;
}
+
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index bb93946ace2..9371ea12d7f 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -54,20 +54,26 @@
static struct path rec_dir;
static int rec_dir_init = 0;
-static void
-nfs4_save_user(uid_t *saveuid, gid_t *savegid)
+static int
+nfs4_save_creds(const struct cred **original_creds)
{
- *saveuid = current->fsuid;
- *savegid = current->fsgid;
- current->fsuid = 0;
- current->fsgid = 0;
+ struct cred *new;
+
+ new = prepare_creds();
+ if (!new)
+ return -ENOMEM;
+
+ new->fsuid = 0;
+ new->fsgid = 0;
+ *original_creds = override_creds(new);
+ put_cred(new);
+ return 0;
}
static void
-nfs4_reset_user(uid_t saveuid, gid_t savegid)
+nfs4_reset_creds(const struct cred *original)
{
- current->fsuid = saveuid;
- current->fsgid = savegid;
+ revert_creds(original);
}
static void
@@ -129,10 +135,9 @@ nfsd4_sync_rec_dir(void)
int
nfsd4_create_clid_dir(struct nfs4_client *clp)
{
+ const struct cred *original_cred;
char *dname = clp->cl_recdir;
struct dentry *dentry;
- uid_t uid;
- gid_t gid;
int status;
dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
@@ -140,7 +145,9 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
if (!rec_dir_init || clp->cl_firststate)
return 0;
- nfs4_save_user(&uid, &gid);
+ status = nfs4_save_creds(&original_cred);
+ if (status < 0)
+ return status;
/* lock the parent */
mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
@@ -168,7 +175,7 @@ out_unlock:
clp->cl_firststate = 1;
nfsd4_sync_rec_dir();
}
- nfs4_reset_user(uid, gid);
+ nfs4_reset_creds(original_cred);
dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
return status;
}
@@ -211,22 +218,24 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
static int
nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
{
+ const struct cred *original_cred;
struct file *filp;
struct dentry_list_arg dla = {
.parent = dir,
};
struct list_head *dentries = &dla.dentries;
struct dentry_list *child;
- uid_t uid;
- gid_t gid;
int status;
if (!rec_dir_init)
return 0;
- nfs4_save_user(&uid, &gid);
+ status = nfs4_save_creds(&original_cred);
+ if (status < 0)
+ return status;
- filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
+ filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY,
+ current_cred());
status = PTR_ERR(filp);
if (IS_ERR(filp))
goto out;
@@ -249,7 +258,7 @@ out:
dput(child->dentry);
kfree(child);
}
- nfs4_reset_user(uid, gid);
+ nfs4_reset_creds(original_cred);
return status;
}
@@ -311,8 +320,7 @@ out:
void
nfsd4_remove_clid_dir(struct nfs4_client *clp)
{
- uid_t uid;
- gid_t gid;
+ const struct cred *original_cred;
int status;
if (!rec_dir_init || !clp->cl_firststate)
@@ -322,9 +330,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
if (status)
goto out;
clp->cl_firststate = 0;
- nfs4_save_user(&uid, &gid);
+
+ status = nfs4_save_creds(&original_cred);
+ if (status < 0)
+ goto out;
+
status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
- nfs4_reset_user(uid, gid);
+ nfs4_reset_creds(original_cred);
if (status == 0)
nfsd4_sync_rec_dir();
mnt_drop_write(rec_dir.mnt);
@@ -401,16 +413,21 @@ nfsd4_recdir_load(void) {
void
nfsd4_init_recdir(char *rec_dirname)
{
- uid_t uid = 0;
- gid_t gid = 0;
- int status;
+ const struct cred *original_cred;
+ int status;
printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
rec_dirname);
BUG_ON(rec_dir_init);
- nfs4_save_user(&uid, &gid);
+ status = nfs4_save_creds(&original_cred);
+ if (status < 0) {
+ printk("NFSD: Unable to change credentials to find recovery"
+ " directory: error %d\n",
+ status);
+ return;
+ }
status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
&rec_dir);
@@ -420,7 +437,7 @@ nfsd4_init_recdir(char *rec_dirname)
if (!status)
rec_dir_init = 1;
- nfs4_reset_user(uid, gid);
+ nfs4_reset_creds(original_cred);
}
void
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index cd25d91895a..f0da7d9c3a9 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -186,9 +186,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
* access control settings being in effect, we cannot
* fix that case easily.
*/
- current->cap_effective =
- cap_raise_nfsd_set(current->cap_effective,
- current->cap_permitted);
+ struct cred *new = prepare_creds();
+ if (!new)
+ return nfserrno(-ENOMEM);
+ new->cap_effective =
+ cap_raise_nfsd_set(new->cap_effective,
+ new->cap_permitted);
+ put_cred(override_creds(new));
+ put_cred(new);
} else {
error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 4433c8f0016..d1c5f787b36 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -671,6 +671,7 @@ __be32
nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
int access, struct file **filp)
{
+ const struct cred *cred = current_cred();
struct dentry *dentry;
struct inode *inode;
int flags = O_RDONLY|O_LARGEFILE;
@@ -725,7 +726,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
DQUOT_INIT(inode);
}
*filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
- flags);
+ flags, cred);
if (IS_ERR(*filp))
host_err = PTR_ERR(*filp);
out_nfserr:
@@ -1169,7 +1170,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
* send along the gid on create when it tries to implement
* setgid directories via NFS:
*/
- if (current->fsuid != 0)
+ if (current_fsuid() != 0)
iap->ia_valid &= ~(ATTR_UID|ATTR_GID);
if (iap->ia_valid)
return nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
@@ -2001,7 +2002,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
IS_APPEND(inode)? " append" : "",
__mnt_is_readonly(exp->ex_path.mnt)? " ro" : "");
dprintk(" owner %d/%d user %d/%d\n",
- inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
+ inode->i_uid, inode->i_gid, current_fsuid(), current_fsgid());
#endif
/* Normally we reject any write/sattr etc access on a read-only file
@@ -2044,7 +2045,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
* with NFSv3.
*/
if ((acc & NFSD_MAY_OWNER_OVERRIDE) &&
- inode->i_uid == current->fsuid)
+ inode->i_uid == current_fsuid())
return 0;
/* This assumes NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 533a789c3ef..3516d8a4166 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -339,8 +339,8 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
ip = DLMFS_I(inode);
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_blocks = 0;
inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -365,8 +365,8 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
return NULL;
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_blocks = 0;
inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f4967e634ff..2545e7402ef 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -421,13 +421,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(inode_ac->ac_alloc_slot);
- fe->i_uid = cpu_to_le32(current->fsuid);
+ fe->i_uid = cpu_to_le32(current_fsuid());
if (dir->i_mode & S_ISGID) {
fe->i_gid = cpu_to_le32(dir->i_gid);
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
- fe->i_gid = cpu_to_le32(current->fsgid);
+ fe->i_gid = cpu_to_le32(current_fsgid());
fe->i_mode = cpu_to_le16(mode);
if (S_ISCHR(mode) || S_ISBLK(mode))
fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index cbf047a847c..6afe57c84f8 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -37,8 +37,8 @@ struct inode *omfs_new_inode(struct inode *dir, int mode)
inode->i_ino = new_block;
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_blocks = 0;
inode->i_mapping->a_ops = &omfs_aops;
@@ -420,8 +420,8 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_fs_info = sbi;
- sbi->s_uid = current->uid;
- sbi->s_gid = current->gid;
+ sbi->s_uid = current_uid();
+ sbi->s_gid = current_gid();
sbi->s_dmask = sbi->s_fmask = current->fs->umask;
if (!parse_options((char *) data, sbi))
diff --git a/fs/open.c b/fs/open.c
index 83cdb9dee0c..c0a426d5766 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -425,39 +425,33 @@ out:
*/
asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
{
+ const struct cred *old_cred;
+ struct cred *override_cred;
struct path path;
struct inode *inode;
- int old_fsuid, old_fsgid;
- kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */
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;
+ override_cred = prepare_creds();
+ if (!override_cred)
+ return -ENOMEM;
- current->fsuid = current->uid;
- current->fsgid = current->gid;
+ override_cred->fsuid = override_cred->uid;
+ override_cred->fsgid = override_cred->gid;
if (!issecure(SECURE_NO_SETUID_FIXUP)) {
- /*
- * Clear the capabilities if we switch to a non-root user
- */
-#ifndef CONFIG_SECURITY_FILE_CAPABILITIES
- /*
- * FIXME: There is a race here against sys_capset. The
- * capabilities can change yet we will restore the old
- * value below. We should hold task_capabilities_lock,
- * but we cannot because user_path_at can sleep.
- */
-#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */
- if (current->uid)
- old_cap = cap_set_effective(__cap_empty_set);
+ /* Clear the capabilities if we switch to a non-root user */
+ if (override_cred->uid)
+ cap_clear(override_cred->cap_effective);
else
- old_cap = cap_set_effective(current->cap_permitted);
+ override_cred->cap_effective =
+ override_cred->cap_permitted;
}
+ old_cred = override_creds(override_cred);
+
res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
if (res)
goto out;
@@ -494,12 +488,8 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
out_path_release:
path_put(&path);
out:
- current->fsuid = old_fsuid;
- current->fsgid = old_fsgid;
-
- if (!issecure(SECURE_NO_SETUID_FIXUP))
- cap_set_effective(old_cap);
-
+ revert_creds(old_cred);
+ put_cred(override_cred);
return res;
}
@@ -792,7 +782,8 @@ static inline int __get_file_write_access(struct inode *inode,
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
int flags, struct file *f,
- int (*open)(struct inode *, struct file *))
+ int (*open)(struct inode *, struct file *),
+ const struct cred *cred)
{
struct inode *inode;
int error;
@@ -816,7 +807,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
f->f_op = fops_get(inode->i_fop);
file_move(f, &inode->i_sb->s_files);
- error = security_dentry_open(f);
+ error = security_dentry_open(f, cred);
if (error)
goto cleanup_all;
@@ -891,6 +882,8 @@ cleanup_file:
struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
int (*open)(struct inode *, struct file *))
{
+ const struct cred *cred = current_cred();
+
if (IS_ERR(nd->intent.open.file))
goto out;
if (IS_ERR(dentry))
@@ -898,7 +891,7 @@ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry
nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
nd->intent.open.flags - 1,
nd->intent.open.file,
- open);
+ open, cred);
out:
return nd->intent.open.file;
out_err:
@@ -917,6 +910,7 @@ EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
*/
struct file *nameidata_to_filp(struct nameidata *nd, int flags)
{
+ const struct cred *cred = current_cred();
struct file *filp;
/* Pick up the filp from the open intent */
@@ -924,7 +918,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
/* Has the filesystem initialised the file for us? */
if (filp->f_path.dentry == NULL)
filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp,
- NULL);
+ NULL, cred);
else
path_put(&nd->path);
return filp;
@@ -934,7 +928,8 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
* dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
* error.
*/
-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
+ const struct cred *cred)
{
int error;
struct file *f;
@@ -959,7 +954,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
return ERR_PTR(error);
}
- return __dentry_open(dentry, mnt, flags, f, NULL);
+ return __dentry_open(dentry, mnt, flags, f, NULL, cred);
}
EXPORT_SYMBOL(dentry_open);
diff --git a/fs/pipe.c b/fs/pipe.c
index 7aea8b89baa..aaf797bd57b 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -899,8 +899,8 @@ static struct inode * get_pipe_inode(void)
*/
inode->i_state = I_DIRTY;
inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
return inode;
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index aec931e0997..39df95a0ec2 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -217,11 +217,11 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
switch(pa->e_tag) {
case ACL_USER_OBJ:
/* (May have been checked already) */
- if (inode->i_uid == current->fsuid)
+ if (inode->i_uid == current_fsuid())
goto check_perm;
break;
case ACL_USER:
- if (pa->e_id == current->fsuid)
+ if (pa->e_id == current_fsuid())
goto mask;
break;
case ACL_GROUP_OBJ:
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 6af7fba7abb..7e4877d9dcb 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -159,6 +159,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
struct group_info *group_info;
int g;
struct fdtable *fdt = NULL;
+ const struct cred *cred;
pid_t ppid, tpid;
rcu_read_lock();
@@ -170,6 +171,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
if (tracer)
tpid = task_pid_nr_ns(tracer, ns);
}
+ cred = get_cred((struct cred *) __task_cred(p));
seq_printf(m,
"State:\t%s\n"
"Tgid:\t%d\n"
@@ -182,8 +184,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
task_tgid_nr_ns(p, ns),
pid_nr_ns(pid, ns),
ppid, tpid,
- p->uid, p->euid, p->suid, p->fsuid,
- p->gid, p->egid, p->sgid, p->fsgid);
+ cred->uid, cred->euid, cred->suid, cred->fsuid,
+ cred->gid, cred->egid, cred->sgid, cred->fsgid);
task_lock(p);
if (p->files)
@@ -194,13 +196,12 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
fdt ? fdt->max_fds : 0);
rcu_read_unlock();
- group_info = p->group_info;
- get_group_info(group_info);
+ group_info = cred->group_info;
task_unlock(p);
for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
seq_printf(m, "%d ", GROUP_AT(group_info, g));
- put_group_info(group_info);
+ put_cred(cred);
seq_printf(m, "\n");
}
@@ -262,7 +263,7 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
blocked = p->blocked;
collect_sigign_sigcatch(p, &ignored, &caught);
num_threads = atomic_read(&p->signal->count);
- qsize = atomic_read(&p->user->sigpending);
+ qsize = atomic_read(&__task_cred(p)->user->sigpending);
qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
unlock_task_sighand(p, &flags);
}
@@ -293,10 +294,21 @@ static void render_cap_t(struct seq_file *m, const char *header,
static inline void task_cap(struct seq_file *m, struct task_struct *p)
{
- render_cap_t(m, "CapInh:\t", &p->cap_inheritable);
- render_cap_t(m, "CapPrm:\t", &p->cap_permitted);
- render_cap_t(m, "CapEff:\t", &p->cap_effective);
- render_cap_t(m, "CapBnd:\t", &p->cap_bset);
+ const struct cred *cred;
+ kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
+
+ rcu_read_lock();
+ cred = __task_cred(p);
+ cap_inheritable = cred->cap_inheritable;
+ cap_permitted = cred->cap_permitted;
+ cap_effective = cred->cap_effective;
+ cap_bset = cred->cap_bset;
+ rcu_read_unlock();
+
+ render_cap_t(m, "CapInh:\t", &cap_inheritable);
+ render_cap_t(m, "CapPrm:\t", &cap_permitted);
+ render_cap_t(m, "CapEff:\t", &cap_effective);
+ render_cap_t(m, "CapBnd:\t", &cap_bset);
}
static inline void task_context_switch_counts(struct seq_file *m,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 486cf3fe713..cf42c42cbfb 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1406,6 +1406,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
{
struct inode * inode;
struct proc_inode *ei;
+ const struct cred *cred;
/* We need a new inode */
@@ -1428,8 +1429,11 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
inode->i_uid = 0;
inode->i_gid = 0;
if (task_dumpable(task)) {
- inode->i_uid = task->euid;
- inode->i_gid = task->egid;
+ rcu_read_lock();
+ cred = __task_cred(task);
+ inode->i_uid = cred->euid;
+ inode->i_gid = cred->egid;
+ rcu_read_unlock();
}
security_task_to_inode(task, inode);
@@ -1445,6 +1449,8 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
{
struct inode *inode = dentry->d_inode;
struct task_struct *task;
+ const struct cred *cred;
+
generic_fillattr(inode, stat);
rcu_read_lock();
@@ -1454,8 +1460,9 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
if (task) {
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
task_dumpable(task)) {
- stat->uid = task->euid;
- stat->gid = task->egid;
+ cred = __task_cred(task);
+ stat->uid = cred->euid;
+ stat->gid = cred->egid;
}
}
rcu_read_unlock();
@@ -1483,11 +1490,16 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
+ const struct cred *cred;
+
if (task) {
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
task_dumpable(task)) {
- inode->i_uid = task->euid;
- inode->i_gid = task->egid;
+ rcu_read_lock();
+ cred = __task_cred(task);
+ inode->i_uid = cred->euid;
+ inode->i_gid = cred->egid;
+ rcu_read_unlock();
} else {
inode->i_uid = 0;
inode->i_gid = 0;
@@ -1649,6 +1661,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
struct task_struct *task = get_proc_task(inode);
int fd = proc_fd(inode);
struct files_struct *files;
+ const struct cred *cred;
if (task) {
files = get_files_struct(task);
@@ -1658,8 +1671,11 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
rcu_read_unlock();
put_files_struct(files);
if (task_dumpable(task)) {
- inode->i_uid = task->euid;
- inode->i_gid = task->egid;
+ rcu_read_lock();
+ cred = __task_cred(task);
+ inode->i_uid = cred->euid;
+ inode->i_gid = cred->egid;
+ rcu_read_unlock();
} else {
inode->i_uid = 0;
inode->i_gid = 0;
diff --git a/fs/quota.c b/fs/quota.c
index 7f4386ebc23..b7fe44e0161 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -79,7 +79,7 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid
/* Check privileges */
if (cmd == Q_GETQUOTA) {
- if (((type == USRQUOTA && current->euid != id) ||
+ if (((type == USRQUOTA && current_euid() != id) ||
(type == GRPQUOTA && !in_egroup_p(id))) &&
!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -130,7 +130,7 @@ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t i
/* Check privileges */
if (cmd == Q_XGETQUOTA) {
- if (((type == XQM_USRQUOTA && current->euid != id) ||
+ if (((type == XQM_USRQUOTA && current_euid() != id) ||
(type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
!capable(CAP_SYS_ADMIN))
return -EPERM;
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index f031d1c925f..a83a3518ae3 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -55,8 +55,8 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
if (inode) {
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
inode->i_blocks = 0;
inode->i_mapping->a_ops = &ramfs_aops;
inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index f89ebb943f3..4f322e5ed84 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -573,7 +573,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
/* the quota init calls have to know who to charge the quota to, so
** we have to set uid and gid here
*/
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
inode->i_mode = mode;
/* Make inode invalid - just in case we are going to drop it before
* the initialization happens */
@@ -584,7 +584,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
if (S_ISDIR(mode))
inode->i_mode |= S_ISGID;
} else {
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
}
DQUOT_INIT(inode);
return 0;
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 48da4fa6b7d..e7ddd0328dd 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -667,8 +667,7 @@ smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
attr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID;
attr.ia_mode = mode;
- attr.ia_uid = current->euid;
- attr.ia_gid = current->egid;
+ current_euid_egid(&attr.ia_uid, &attr.ia_gid);
if (!new_valid_dev(dev))
return -EINVAL;
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 3528f40ffb0..fc27fbfc539 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -586,7 +586,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
if (parse_options(mnt, raw_data))
goto out_bad_option;
}
- mnt->mounted_uid = current->uid;
+ mnt->mounted_uid = current_uid();
smb_setcodepage(server, &mnt->codepage);
/*
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index ee536e8a649..9468168b9af 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -864,7 +864,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
goto out;
error = -EACCES;
- if (current->uid != server->mnt->mounted_uid &&
+ if (current_uid() != server->mnt->mounted_uid &&
!capable(CAP_SYS_ADMIN))
goto out;
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index 115ab0d6f4b..241e9765cfa 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -165,9 +165,9 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
inode->i_ino = fs16_to_cpu(sbi, ino);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
inode->i_blocks = 0;
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c
index 1a4973e1066..4a18f084cc4 100644
--- a/fs/ubifs/budget.c
+++ b/fs/ubifs/budget.c
@@ -363,7 +363,7 @@ long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs)
*/
static int can_use_rp(struct ubifs_info *c)
{
- if (current->fsuid == c->rp_uid || capable(CAP_SYS_RESOURCE) ||
+ if (current_fsuid() == c->rp_uid || capable(CAP_SYS_RESOURCE) ||
(c->rp_gid != 0 && in_group_p(c->rp_gid)))
return 1;
return 0;
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 526c01ec800..856189014a3 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -104,13 +104,13 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
*/
inode->i_flags |= (S_NOCMTIME);
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
inode->i_mode = mode;
inode->i_mtime = inode->i_atime = inode->i_ctime =
ubifs_current_time(inode);
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index a4f2b3ce45b..31fc84297dd 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -126,13 +126,13 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
}
mutex_unlock(&sbi->s_alloc_mutex);
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
mode |= S_ISGID;
} else {
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
}
iinfo->i_location.logicalBlockNum = block;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 082409cd4b8..f84bfaa8d94 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -604,7 +604,7 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
goto out;
iinfo = UDF_I(inode);
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
init_special_inode(inode, mode, rdev);
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
if (!fi) {
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index ac181f6806a..6f5dcf00609 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -304,13 +304,13 @@ cg_found:
inode->i_ino = cg * uspi->s_ipg + bit;
inode->i_mode = mode;
- inode->i_uid = current->fsuid;
+ inode->i_uid = current_fsuid();
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
inode->i_mode |= S_ISGID;
} else
- inode->i_gid = current->fsgid;
+ inode->i_gid = current_fsgid();
inode->i_blocks = 0;
inode->i_generation = 0;
diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h
index 652721ce0ea..8c022cd0ad6 100644
--- a/fs/xfs/linux-2.6/xfs_cred.h
+++ b/fs/xfs/linux-2.6/xfs_cred.h
@@ -23,11 +23,9 @@
/*
* Credentials
*/
-typedef struct cred {
- /* EMPTY */
-} cred_t;
+typedef const struct cred cred_t;
-extern struct cred *sys_cred;
+extern cred_t *sys_cred;
/* this is a hack.. (assumes sys_cred is the only cred_t in the system) */
static inline int capable_cred(cred_t *cr, int cid)
diff --git a/fs/xfs/linux-2.6/xfs_globals.h b/fs/xfs/linux-2.6/xfs_globals.h
index 2770b0085ee..6eda8a3eb6f 100644
--- a/fs/xfs/linux-2.6/xfs_globals.h
+++ b/fs/xfs/linux-2.6/xfs_globals.h
@@ -19,6 +19,6 @@
#define __XFS_GLOBALS_H__
extern uint64_t xfs_panic_mask; /* set to cause more panics */
-extern struct cred *sys_cred;
+extern cred_t *sys_cred;
#endif /* __XFS_GLOBALS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index d3438c72dca..281cbd5a25c 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -256,6 +256,7 @@ xfs_open_by_handle(
struct file *parfilp,
struct inode *parinode)
{
+ const struct cred *cred = current_cred();
int error;
int new_fd;
int permflag;
@@ -321,7 +322,7 @@ xfs_open_by_handle(
mntget(parfilp->f_path.mnt);
/* Create file pointer. */
- filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags);
+ filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags, cred);
if (IS_ERR(filp)) {
put_unused_fd(new_fd);
return -XFS_ERROR(-PTR_ERR(filp));
@@ -1007,7 +1008,7 @@ xfs_ioctl_setattr(
* to the file owner ID, except in cases where the
* CAP_FSETID capability is applicable.
*/
- if (current->fsuid != ip->i_d.di_uid && !capable(CAP_FOWNER)) {
+ if (current_fsuid() != ip->i_d.di_uid && !capable(CAP_FOWNER)) {
code = XFS_ERROR(EPERM);
goto error_return;
}
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index b2f639a1416..91d69338d3b 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -366,7 +366,7 @@ xfs_acl_allow_set(
return ENOTDIR;
if (vp->i_sb->s_flags & MS_RDONLY)
return EROFS;
- if (XFS_I(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER))
+ if (XFS_I(vp)->i_d.di_uid != current_fsuid() && !capable(CAP_FOWNER))
return EPERM;
return 0;
}
@@ -413,13 +413,13 @@ xfs_acl_access(
switch (fap->acl_entry[i].ae_tag) {
case ACL_USER_OBJ:
seen_userobj = 1;
- if (fuid != current->fsuid)
+ if (fuid != current_fsuid())
continue;
matched.ae_tag = ACL_USER_OBJ;
matched.ae_perm = allows;
break;
case ACL_USER:
- if (fap->acl_entry[i].ae_id != current->fsuid)
+ if (fap->acl_entry[i].ae_id != current_fsuid())
continue;
matched.ae_tag = ACL_USER;
matched.ae_perm = allows;
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 1420c49674d..6be310d41da 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -497,7 +497,7 @@ int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
xfs_inode_t **, xfs_daddr_t, uint);
int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
- xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
+ xfs_nlink_t, xfs_dev_t, cred_t *, xfs_prid_t,
int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
void xfs_dinode_from_disk(struct xfs_icdinode *,
struct xfs_dinode_core *);
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index e932a96bec5..7b0c2ab8833 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -16,7 +16,7 @@ struct xfs_iomap;
int xfs_open(struct xfs_inode *ip);
int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags,
- struct cred *credp);
+ cred_t *credp);
#define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */
#define XFS_ATTR_NONBLOCK 0x02 /* return EAGAIN if operation would block */
#define XFS_ATTR_NOLOCK 0x04 /* Don't grab any conflicting locks */
@@ -28,24 +28,24 @@ int xfs_inactive(struct xfs_inode *ip);
int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
struct xfs_inode **ipp, struct xfs_name *ci_name);
int xfs_create(struct xfs_inode *dp, struct xfs_name *name, mode_t mode,
- xfs_dev_t rdev, struct xfs_inode **ipp, struct cred *credp);
+ xfs_dev_t rdev, struct xfs_inode **ipp, cred_t *credp);
int xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
struct xfs_inode *ip);
int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
struct xfs_name *target_name);
int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
- mode_t mode, struct xfs_inode **ipp, struct cred *credp);
+ mode_t mode, struct xfs_inode **ipp, cred_t *credp);
int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize,
xfs_off_t *offset, filldir_t filldir);
int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
const char *target_path, mode_t mode, struct xfs_inode **ipp,
- struct cred *credp);
+ cred_t *credp);
int xfs_inode_flush(struct xfs_inode *ip, int flags);
int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
int xfs_reclaim(struct xfs_inode *ip);
int xfs_change_file_space(struct xfs_inode *ip, int cmd,
xfs_flock64_t *bf, xfs_off_t offset,
- struct cred *credp, int attr_flags);
+ cred_t *credp, int attr_flags);
int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name,
struct xfs_inode *src_ip, struct xfs_inode *target_dp,
struct xfs_name *target_name, struct xfs_inode *target_ip);