aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-03 00:09:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-03 00:09:10 -0400
commit8fe74cf053de7ad2124a894996f84fa890a81093 (patch)
tree77dcd8fbf33ce53a3821942233962fb28c6f2848
parentc2eb2fa6d2b6fe122d3479ec5b28d978418b2698 (diff)
parentced117c73edc917e96dea7cca98c91383f0792f7 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: Remove two unneeded exports and make two symbols static in fs/mpage.c Cleanup after commit 585d3bc06f4ca57f975a5a1f698f65a45ea66225 Trim includes of fdtable.h Don't crap into descriptor table in binfmt_som Trim includes in binfmt_elf Don't mess with descriptor table in load_elf_binary() Get rid of indirect include of fs_struct.h New helper - current_umask() check_unsafe_exec() doesn't care about signal handlers sharing New locking/refcounting for fs_struct Take fs_struct handling to new file (fs/fs_struct.c) Get rid of bumping fs_struct refcount in pivot_root(2) Kill unsharing fs_struct in __set_personality()
-rw-r--r--arch/cris/kernel/process.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c2
-rw-r--r--drivers/char/tty_audit.c2
-rw-r--r--drivers/char/tty_ldisc.c1
-rw-r--r--fs/Makefile2
-rw-r--r--fs/binfmt_elf.c22
-rw-r--r--fs/binfmt_som.c7
-rw-r--r--fs/block_dev.c1
-rw-r--r--fs/btrfs/acl.c2
-rw-r--r--fs/btrfs/ioctl.c2
-rw-r--r--fs/buffer.c1
-rw-r--r--fs/cifs/dir.c4
-rw-r--r--fs/cifs/inode.c4
-rw-r--r--fs/compat.c16
-rw-r--r--fs/dcache.c2
-rw-r--r--fs/exec.c35
-rw-r--r--fs/ext2/acl.c2
-rw-r--r--fs/ext3/acl.c2
-rw-r--r--fs/ext4/acl.c2
-rw-r--r--fs/fat/inode.c2
-rw-r--r--fs/fs_struct.c177
-rw-r--r--fs/generic_acl.c2
-rw-r--r--fs/gfs2/acl.c2
-rw-r--r--fs/hfsplus/options.c2
-rw-r--r--fs/hpfs/super.c2
-rw-r--r--fs/internal.h8
-rw-r--r--fs/jffs2/acl.c2
-rw-r--r--fs/jfs/acl.c2
-rw-r--r--fs/mpage.c13
-rw-r--r--fs/namei.c14
-rw-r--r--fs/namespace.c61
-rw-r--r--fs/nfs/nfs3proc.c6
-rw-r--r--fs/nfs/nfs4proc.c2
-rw-r--r--fs/nfsd/nfssvc.c7
-rw-r--r--fs/ocfs2/acl.c2
-rw-r--r--fs/omfs/inode.c2
-rw-r--r--fs/open.c1
-rw-r--r--fs/proc/base.c1
-rw-r--r--fs/proc/task_nommu.c3
-rw-r--r--fs/reiserfs/xattr_acl.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c4
-rw-r--r--include/linux/buffer_head.h12
-rw-r--r--include/linux/fs.h14
-rw-r--r--include/linux/fs_struct.h10
-rw-r--r--include/linux/mnt_namespace.h2
-rw-r--r--include/linux/mpage.h10
-rw-r--r--include/linux/nsproxy.h1
-rw-r--r--include/linux/sched.h3
-rw-r--r--init/do_mounts.c1
-rw-r--r--ipc/mqueue.c2
-rw-r--r--kernel/auditsc.c1
-rw-r--r--kernel/exec_domain.c23
-rw-r--r--kernel/exit.c32
-rw-r--r--kernel/fork.c63
-rw-r--r--kernel/sys.c1
-rw-r--r--net/unix/af_unix.c2
-rw-r--r--security/tomoyo/realpath.c1
57 files changed, 337 insertions, 268 deletions
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 60816e876455..4df0b320d524 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -19,7 +19,6 @@
19#include <asm/system.h> 19#include <asm/system.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/spinlock.h> 21#include <linux/spinlock.h>
22#include <linux/fs_struct.h>
23#include <linux/init_task.h> 22#include <linux/init_task.h>
24#include <linux/sched.h> 23#include <linux/sched.h>
25#include <linux/fs.h> 24#include <linux/fs.h>
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 64f068540d0d..706eb5c7e2ee 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -635,7 +635,7 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
635 if (dentry->d_inode) 635 if (dentry->d_inode)
636 goto out_dput; 636 goto out_dput;
637 637
638 mode &= ~current->fs->umask; 638 mode &= ~current_umask();
639 639
640 if (flags & SPU_CREATE_GANG) 640 if (flags & SPU_CREATE_GANG)
641 ret = spufs_create_gang(nd->path.dentry->d_inode, 641 ret = spufs_create_gang(nd->path.dentry->d_inode,
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
index 34ab6d798f81..55ba6f142883 100644
--- a/drivers/char/tty_audit.c
+++ b/drivers/char/tty_audit.c
@@ -10,8 +10,6 @@
10 */ 10 */
11 11
12#include <linux/audit.h> 12#include <linux/audit.h>
13#include <linux/file.h>
14#include <linux/fdtable.h>
15#include <linux/tty.h> 13#include <linux/tty.h>
16 14
17struct tty_audit_buf { 15struct tty_audit_buf {
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index 7a84b406a952..f78f5b0127a8 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -10,7 +10,6 @@
10#include <linux/tty_flip.h> 10#include <linux/tty_flip.h>
11#include <linux/devpts_fs.h> 11#include <linux/devpts_fs.h>
12#include <linux/file.h> 12#include <linux/file.h>
13#include <linux/fdtable.h>
14#include <linux/console.h> 13#include <linux/console.h>
15#include <linux/timer.h> 14#include <linux/timer.h>
16#include <linux/ctype.h> 15#include <linux/ctype.h>
diff --git a/fs/Makefile b/fs/Makefile
index 6e82a307bcd4..b5cd8e18dd9f 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -11,7 +11,7 @@ obj-y := open.o read_write.o file_table.o super.o \
11 attr.o bad_inode.o file.o filesystems.o namespace.o \ 11 attr.o bad_inode.o file.o filesystems.o namespace.o \
12 seq_file.o xattr.o libfs.o fs-writeback.o \ 12 seq_file.o xattr.o libfs.o fs-writeback.o \
13 pnode.o drop_caches.o splice.o sync.o utimes.o \ 13 pnode.o drop_caches.o splice.o sync.o utimes.o \
14 stack.o 14 stack.o fs_struct.o
15 15
16ifeq ($(CONFIG_BLOCK),y) 16ifeq ($(CONFIG_BLOCK),y)
17obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o 17obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 33b7235f853b..40381df34869 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -12,8 +12,6 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/fs.h> 14#include <linux/fs.h>
15#include <linux/stat.h>
16#include <linux/time.h>
17#include <linux/mm.h> 15#include <linux/mm.h>
18#include <linux/mman.h> 16#include <linux/mman.h>
19#include <linux/errno.h> 17#include <linux/errno.h>
@@ -21,20 +19,15 @@
21#include <linux/binfmts.h> 19#include <linux/binfmts.h>
22#include <linux/string.h> 20#include <linux/string.h>
23#include <linux/file.h> 21#include <linux/file.h>
24#include <linux/fcntl.h>
25#include <linux/ptrace.h>
26#include <linux/slab.h> 22#include <linux/slab.h>
27#include <linux/shm.h>
28#include <linux/personality.h> 23#include <linux/personality.h>
29#include <linux/elfcore.h> 24#include <linux/elfcore.h>
30#include <linux/init.h> 25#include <linux/init.h>
31#include <linux/highuid.h> 26#include <linux/highuid.h>
32#include <linux/smp.h>
33#include <linux/compiler.h> 27#include <linux/compiler.h>
34#include <linux/highmem.h> 28#include <linux/highmem.h>
35#include <linux/pagemap.h> 29#include <linux/pagemap.h>
36#include <linux/security.h> 30#include <linux/security.h>
37#include <linux/syscalls.h>
38#include <linux/random.h> 31#include <linux/random.h>
39#include <linux/elf.h> 32#include <linux/elf.h>
40#include <linux/utsname.h> 33#include <linux/utsname.h>
@@ -576,7 +569,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
576 unsigned long error; 569 unsigned long error;
577 struct elf_phdr *elf_ppnt, *elf_phdata; 570 struct elf_phdr *elf_ppnt, *elf_phdata;
578 unsigned long elf_bss, elf_brk; 571 unsigned long elf_bss, elf_brk;
579 int elf_exec_fileno;
580 int retval, i; 572 int retval, i;
581 unsigned int size; 573 unsigned int size;
582 unsigned long elf_entry; 574 unsigned long elf_entry;
@@ -631,12 +623,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
631 goto out_free_ph; 623 goto out_free_ph;
632 } 624 }
633 625
634 retval = get_unused_fd();
635 if (retval < 0)
636 goto out_free_ph;
637 get_file(bprm->file);
638 fd_install(elf_exec_fileno = retval, bprm->file);
639
640 elf_ppnt = elf_phdata; 626 elf_ppnt = elf_phdata;
641 elf_bss = 0; 627 elf_bss = 0;
642 elf_brk = 0; 628 elf_brk = 0;
@@ -655,13 +641,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
655 retval = -ENOEXEC; 641 retval = -ENOEXEC;
656 if (elf_ppnt->p_filesz > PATH_MAX || 642 if (elf_ppnt->p_filesz > PATH_MAX ||
657 elf_ppnt->p_filesz < 2) 643 elf_ppnt->p_filesz < 2)
658 goto out_free_file; 644 goto out_free_ph;
659 645
660 retval = -ENOMEM; 646 retval = -ENOMEM;
661 elf_interpreter = kmalloc(elf_ppnt->p_filesz, 647 elf_interpreter = kmalloc(elf_ppnt->p_filesz,
662 GFP_KERNEL); 648 GFP_KERNEL);
663 if (!elf_interpreter) 649 if (!elf_interpreter)
664 goto out_free_file; 650 goto out_free_ph;
665 651
666 retval = kernel_read(bprm->file, elf_ppnt->p_offset, 652 retval = kernel_read(bprm->file, elf_ppnt->p_offset,
667 elf_interpreter, 653 elf_interpreter,
@@ -956,8 +942,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
956 942
957 kfree(elf_phdata); 943 kfree(elf_phdata);
958 944
959 sys_close(elf_exec_fileno);
960
961 set_binfmt(&elf_format); 945 set_binfmt(&elf_format);
962 946
963#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES 947#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
@@ -1028,8 +1012,6 @@ out_free_dentry:
1028 fput(interpreter); 1012 fput(interpreter);
1029out_free_interp: 1013out_free_interp:
1030 kfree(elf_interpreter); 1014 kfree(elf_interpreter);
1031out_free_file:
1032 sys_close(elf_exec_fileno);
1033out_free_ph: 1015out_free_ph:
1034 kfree(elf_phdata); 1016 kfree(elf_phdata);
1035 goto out; 1017 goto out;
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index 08644a61616e..eff74b9c9e77 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -188,7 +188,6 @@ out:
188static int 188static int
189load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) 189load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
190{ 190{
191 int som_exec_fileno;
192 int retval; 191 int retval;
193 unsigned int size; 192 unsigned int size;
194 unsigned long som_entry; 193 unsigned long som_entry;
@@ -220,12 +219,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
220 goto out_free; 219 goto out_free;
221 } 220 }
222 221
223 retval = get_unused_fd();
224 if (retval < 0)
225 goto out_free;
226 get_file(bprm->file);
227 fd_install(som_exec_fileno = retval, bprm->file);
228
229 /* Flush all traces of the currently running executable */ 222 /* Flush all traces of the currently running executable */
230 retval = flush_old_exec(bprm); 223 retval = flush_old_exec(bprm);
231 if (retval) 224 if (retval)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 8c3c6899ccf3..f45dbc18dd17 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -204,6 +204,7 @@ int fsync_bdev(struct block_device *bdev)
204 } 204 }
205 return sync_blockdev(bdev); 205 return sync_blockdev(bdev);
206} 206}
207EXPORT_SYMBOL(fsync_bdev);
207 208
208/** 209/**
209 * freeze_bdev -- lock a filesystem and force it into a consistent state 210 * freeze_bdev -- lock a filesystem and force it into a consistent state
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 1d53b62dbba5..7fdd184a528d 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -256,7 +256,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
256 } 256 }
257 257
258 if (!acl) 258 if (!acl)
259 inode->i_mode &= ~current->fs->umask; 259 inode->i_mode &= ~current_umask();
260 } 260 }
261 261
262 if (IS_POSIXACL(dir) && acl) { 262 if (IS_POSIXACL(dir) && acl) {
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index bca729fc80c8..7594bec1be10 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -267,7 +267,7 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name,
267 goto out_dput; 267 goto out_dput;
268 268
269 if (!IS_POSIXACL(parent->dentry->d_inode)) 269 if (!IS_POSIXACL(parent->dentry->d_inode))
270 mode &= ~current->fs->umask; 270 mode &= ~current_umask();
271 271
272 error = mnt_want_write(parent->mnt); 272 error = mnt_want_write(parent->mnt);
273 if (error) 273 if (error)
diff --git a/fs/buffer.c b/fs/buffer.c
index 2963858f0f31..c2fa1be4923d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -3315,7 +3315,6 @@ EXPORT_SYMBOL(cont_write_begin);
3315EXPORT_SYMBOL(end_buffer_read_sync); 3315EXPORT_SYMBOL(end_buffer_read_sync);
3316EXPORT_SYMBOL(end_buffer_write_sync); 3316EXPORT_SYMBOL(end_buffer_write_sync);
3317EXPORT_SYMBOL(file_fsync); 3317EXPORT_SYMBOL(file_fsync);
3318EXPORT_SYMBOL(fsync_bdev);
3319EXPORT_SYMBOL(generic_block_bmap); 3318EXPORT_SYMBOL(generic_block_bmap);
3320EXPORT_SYMBOL(generic_cont_expand_simple); 3319EXPORT_SYMBOL(generic_cont_expand_simple);
3321EXPORT_SYMBOL(init_buffer); 3320EXPORT_SYMBOL(init_buffer);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 2f35cccfcd8d..54dce78fbb73 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -254,7 +254,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
254 return -ENOMEM; 254 return -ENOMEM;
255 } 255 }
256 256
257 mode &= ~current->fs->umask; 257 mode &= ~current_umask();
258 if (oplockEnabled) 258 if (oplockEnabled)
259 oplock = REQ_OPLOCK; 259 oplock = REQ_OPLOCK;
260 260
@@ -479,7 +479,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
479 rc = -ENOMEM; 479 rc = -ENOMEM;
480 else if (pTcon->unix_ext) { 480 else if (pTcon->unix_ext) {
481 struct cifs_unix_set_info_args args = { 481 struct cifs_unix_set_info_args args = {
482 .mode = mode & ~current->fs->umask, 482 .mode = mode & ~current_umask(),
483 .ctime = NO_CHANGE_64, 483 .ctime = NO_CHANGE_64,
484 .atime = NO_CHANGE_64, 484 .atime = NO_CHANGE_64,
485 .mtime = NO_CHANGE_64, 485 .mtime = NO_CHANGE_64,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a8797cc60805..f121a80fdd6f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1125,7 +1125,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
1125 goto mkdir_out; 1125 goto mkdir_out;
1126 } 1126 }
1127 1127
1128 mode &= ~current->fs->umask; 1128 mode &= ~current_umask();
1129 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, 1129 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
1130 mode, NULL /* netfid */, pInfo, &oplock, 1130 mode, NULL /* netfid */, pInfo, &oplock,
1131 full_path, cifs_sb->local_nls, 1131 full_path, cifs_sb->local_nls,
@@ -1204,7 +1204,7 @@ mkdir_get_info:
1204 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) 1204 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
1205 direntry->d_inode->i_nlink = 2; 1205 direntry->d_inode->i_nlink = 2;
1206 1206
1207 mode &= ~current->fs->umask; 1207 mode &= ~current_umask();
1208 /* must turn on setgid bit if parent dir has it */ 1208 /* must turn on setgid bit if parent dir has it */
1209 if (inode->i_mode & S_ISGID) 1209 if (inode->i_mode & S_ISGID)
1210 mode |= S_ISGID; 1210 mode |= S_ISGID;
diff --git a/fs/compat.c b/fs/compat.c
index 440a019256dd..1c859dae758f 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -51,6 +51,7 @@
51#include <linux/poll.h> 51#include <linux/poll.h>
52#include <linux/mm.h> 52#include <linux/mm.h>
53#include <linux/eventpoll.h> 53#include <linux/eventpoll.h>
54#include <linux/fs_struct.h>
54 55
55#include <asm/uaccess.h> 56#include <asm/uaccess.h>
56#include <asm/mmu_context.h> 57#include <asm/mmu_context.h>
@@ -1502,12 +1503,15 @@ int compat_do_execve(char * filename,
1502 bprm->cred = prepare_exec_creds(); 1503 bprm->cred = prepare_exec_creds();
1503 if (!bprm->cred) 1504 if (!bprm->cred)
1504 goto out_unlock; 1505 goto out_unlock;
1505 check_unsafe_exec(bprm); 1506
1507 retval = check_unsafe_exec(bprm);
1508 if (retval)
1509 goto out_unlock;
1506 1510
1507 file = open_exec(filename); 1511 file = open_exec(filename);
1508 retval = PTR_ERR(file); 1512 retval = PTR_ERR(file);
1509 if (IS_ERR(file)) 1513 if (IS_ERR(file))
1510 goto out_unlock; 1514 goto out_unmark;
1511 1515
1512 sched_exec(); 1516 sched_exec();
1513 1517
@@ -1549,6 +1553,9 @@ int compat_do_execve(char * filename,
1549 goto out; 1553 goto out;
1550 1554
1551 /* execve succeeded */ 1555 /* execve succeeded */
1556 write_lock(&current->fs->lock);
1557 current->fs->in_exec = 0;
1558 write_unlock(&current->fs->lock);
1552 current->in_execve = 0; 1559 current->in_execve = 0;
1553 mutex_unlock(&current->cred_exec_mutex); 1560 mutex_unlock(&current->cred_exec_mutex);
1554 acct_update_integrals(current); 1561 acct_update_integrals(current);
@@ -1567,6 +1574,11 @@ out_file:
1567 fput(bprm->file); 1574 fput(bprm->file);
1568 } 1575 }
1569 1576
1577out_unmark:
1578 write_lock(&current->fs->lock);
1579 current->fs->in_exec = 0;
1580 write_unlock(&current->fs->lock);
1581
1570out_unlock: 1582out_unlock:
1571 current->in_execve = 0; 1583 current->in_execve = 0;
1572 mutex_unlock(&current->cred_exec_mutex); 1584 mutex_unlock(&current->cred_exec_mutex);
diff --git a/fs/dcache.c b/fs/dcache.c
index 90bbd7e1b116..761d30be2683 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -17,7 +17,6 @@
17#include <linux/syscalls.h> 17#include <linux/syscalls.h>
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/fdtable.h>
21#include <linux/fs.h> 20#include <linux/fs.h>
22#include <linux/fsnotify.h> 21#include <linux/fsnotify.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
@@ -32,6 +31,7 @@
32#include <linux/seqlock.h> 31#include <linux/seqlock.h>
33#include <linux/swap.h> 32#include <linux/swap.h>
34#include <linux/bootmem.h> 33#include <linux/bootmem.h>
34#include <linux/fs_struct.h>
35#include "internal.h" 35#include "internal.h"
36 36
37int sysctl_vfs_cache_pressure __read_mostly = 100; 37int sysctl_vfs_cache_pressure __read_mostly = 100;
diff --git a/fs/exec.c b/fs/exec.c
index c5128fbc9165..052a961e41aa 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -53,6 +53,7 @@
53#include <linux/tracehook.h> 53#include <linux/tracehook.h>
54#include <linux/kmod.h> 54#include <linux/kmod.h>
55#include <linux/fsnotify.h> 55#include <linux/fsnotify.h>
56#include <linux/fs_struct.h>
56 57
57#include <asm/uaccess.h> 58#include <asm/uaccess.h>
58#include <asm/mmu_context.h> 59#include <asm/mmu_context.h>
@@ -1056,28 +1057,35 @@ EXPORT_SYMBOL(install_exec_creds);
1056 * - the caller must hold current->cred_exec_mutex to protect against 1057 * - the caller must hold current->cred_exec_mutex to protect against
1057 * PTRACE_ATTACH 1058 * PTRACE_ATTACH
1058 */ 1059 */
1059void check_unsafe_exec(struct linux_binprm *bprm) 1060int check_unsafe_exec(struct linux_binprm *bprm)
1060{ 1061{
1061 struct task_struct *p = current, *t; 1062 struct task_struct *p = current, *t;
1062 unsigned long flags; 1063 unsigned long flags;
1063 unsigned n_fs, n_sighand; 1064 unsigned n_fs;
1065 int res = 0;
1064 1066
1065 bprm->unsafe = tracehook_unsafe_exec(p); 1067 bprm->unsafe = tracehook_unsafe_exec(p);
1066 1068
1067 n_fs = 1; 1069 n_fs = 1;
1068 n_sighand = 1; 1070 write_lock(&p->fs->lock);
1069 lock_task_sighand(p, &flags); 1071 lock_task_sighand(p, &flags);
1070 for (t = next_thread(p); t != p; t = next_thread(t)) { 1072 for (t = next_thread(p); t != p; t = next_thread(t)) {
1071 if (t->fs == p->fs) 1073 if (t->fs == p->fs)
1072 n_fs++; 1074 n_fs++;
1073 n_sighand++;
1074 } 1075 }
1075 1076
1076 if (atomic_read(&p->fs->count) > n_fs || 1077 if (p->fs->users > n_fs) {
1077 atomic_read(&p->sighand->count) > n_sighand)
1078 bprm->unsafe |= LSM_UNSAFE_SHARE; 1078 bprm->unsafe |= LSM_UNSAFE_SHARE;
1079 } else {
1080 if (p->fs->in_exec)
1081 res = -EAGAIN;
1082 p->fs->in_exec = 1;
1083 }
1079 1084
1080 unlock_task_sighand(p, &flags); 1085 unlock_task_sighand(p, &flags);
1086 write_unlock(&p->fs->lock);
1087
1088 return res;
1081} 1089}
1082 1090
1083/* 1091/*
@@ -1296,12 +1304,15 @@ int do_execve(char * filename,
1296 bprm->cred = prepare_exec_creds(); 1304 bprm->cred = prepare_exec_creds();
1297 if (!bprm->cred) 1305 if (!bprm->cred)
1298 goto out_unlock; 1306 goto out_unlock;
1299 check_unsafe_exec(bprm); 1307
1308 retval = check_unsafe_exec(bprm);
1309 if (retval)
1310 goto out_unlock;
1300 1311
1301 file = open_exec(filename); 1312 file = open_exec(filename);
1302 retval = PTR_ERR(file); 1313 retval = PTR_ERR(file);
1303 if (IS_ERR(file)) 1314 if (IS_ERR(file))
1304 goto out_unlock; 1315 goto out_unmark;
1305 1316
1306 sched_exec(); 1317 sched_exec();
1307 1318
@@ -1344,6 +1355,9 @@ int do_execve(char * filename,
1344 goto out; 1355 goto out;
1345 1356
1346 /* execve succeeded */ 1357 /* execve succeeded */
1358 write_lock(&current->fs->lock);
1359 current->fs->in_exec = 0;
1360 write_unlock(&current->fs->lock);
1347 current->in_execve = 0; 1361 current->in_execve = 0;
1348 mutex_unlock(&current->cred_exec_mutex); 1362 mutex_unlock(&current->cred_exec_mutex);
1349 acct_update_integrals(current); 1363 acct_update_integrals(current);
@@ -1362,6 +1376,11 @@ out_file:
1362 fput(bprm->file); 1376 fput(bprm->file);
1363 } 1377 }
1364 1378
1379out_unmark:
1380 write_lock(&current->fs->lock);
1381 current->fs->in_exec = 0;
1382 write_unlock(&current->fs->lock);
1383
1365out_unlock: 1384out_unlock:
1366 current->in_execve = 0; 1385 current->in_execve = 0;
1367 mutex_unlock(&current->cred_exec_mutex); 1386 mutex_unlock(&current->cred_exec_mutex);
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index ae8c4f850b27..d46e38cb85c5 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -318,7 +318,7 @@ ext2_init_acl(struct inode *inode, struct inode *dir)
318 return PTR_ERR(acl); 318 return PTR_ERR(acl);
319 } 319 }
320 if (!acl) 320 if (!acl)
321 inode->i_mode &= ~current->fs->umask; 321 inode->i_mode &= ~current_umask();
322 } 322 }
323 if (test_opt(inode->i_sb, POSIX_ACL) && acl) { 323 if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
324 struct posix_acl *clone; 324 struct posix_acl *clone;
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index b60bb241880c..d81ef2fdb08e 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -323,7 +323,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
323 return PTR_ERR(acl); 323 return PTR_ERR(acl);
324 } 324 }
325 if (!acl) 325 if (!acl)
326 inode->i_mode &= ~current->fs->umask; 326 inode->i_mode &= ~current_umask();
327 } 327 }
328 if (test_opt(inode->i_sb, POSIX_ACL) && acl) { 328 if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
329 struct posix_acl *clone; 329 struct posix_acl *clone;
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 694ed6fadcc8..647e0d65a284 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -323,7 +323,7 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
323 return PTR_ERR(acl); 323 return PTR_ERR(acl);
324 } 324 }
325 if (!acl) 325 if (!acl)
326 inode->i_mode &= ~current->fs->umask; 326 inode->i_mode &= ~current_umask();
327 } 327 }
328 if (test_opt(inode->i_sb, POSIX_ACL) && acl) { 328 if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
329 struct posix_acl *clone; 329 struct posix_acl *clone;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 2cc952e4c3dc..296785a0dec8 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -934,7 +934,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
934 934
935 opts->fs_uid = current_uid(); 935 opts->fs_uid = current_uid();
936 opts->fs_gid = current_gid(); 936 opts->fs_gid = current_gid();
937 opts->fs_fmask = opts->fs_dmask = current->fs->umask; 937 opts->fs_fmask = current_umask();
938 opts->allow_utime = -1; 938 opts->allow_utime = -1;
939 opts->codepage = fat_default_codepage; 939 opts->codepage = fat_default_codepage;
940 opts->iocharset = fat_default_iocharset; 940 opts->iocharset = fat_default_iocharset;
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
new file mode 100644
index 000000000000..eee059052db5
--- /dev/null
+++ b/fs/fs_struct.c
@@ -0,0 +1,177 @@
1#include <linux/module.h>
2#include <linux/sched.h>
3#include <linux/fs.h>
4#include <linux/path.h>
5#include <linux/slab.h>
6#include <linux/fs_struct.h>
7
8/*
9 * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
10 * It can block.
11 */
12void set_fs_root(struct fs_struct *fs, struct path *path)
13{
14 struct path old_root;
15
16 write_lock(&fs->lock);
17 old_root = fs->root;
18 fs->root = *path;
19 path_get(path);
20 write_unlock(&fs->lock);
21 if (old_root.dentry)
22 path_put(&old_root);
23}
24
25/*
26 * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
27 * It can block.
28 */
29void set_fs_pwd(struct fs_struct *fs, struct path *path)
30{
31 struct path old_pwd;
32
33 write_lock(&fs->lock);
34 old_pwd = fs->pwd;
35 fs->pwd = *path;
36 path_get(path);
37 write_unlock(&fs->lock);
38
39 if (old_pwd.dentry)
40 path_put(&old_pwd);
41}
42
43void chroot_fs_refs(struct path *old_root, struct path *new_root)
44{
45 struct task_struct *g, *p;
46 struct fs_struct *fs;
47 int count = 0;
48
49 read_lock(&tasklist_lock);
50 do_each_thread(g, p) {
51 task_lock(p);
52 fs = p->fs;
53 if (fs) {
54 write_lock(&fs->lock);
55 if (fs->root.dentry == old_root->dentry
56 && fs->root.mnt == old_root->mnt) {
57 path_get(new_root);
58 fs->root = *new_root;
59 count++;
60 }
61 if (fs->pwd.dentry == old_root->dentry
62 && fs->pwd.mnt == old_root->mnt) {
63 path_get(new_root);
64 fs->pwd = *new_root;
65 count++;
66 }
67 write_unlock(&fs->lock);
68 }
69 task_unlock(p);
70 } while_each_thread(g, p);
71 read_unlock(&tasklist_lock);
72 while (count--)
73 path_put(old_root);
74}
75
76void free_fs_struct(struct fs_struct *fs)
77{
78 path_put(&fs->root);
79 path_put(&fs->pwd);
80 kmem_cache_free(fs_cachep, fs);
81}
82
83void exit_fs(struct task_struct *tsk)
84{
85 struct fs_struct *fs = tsk->fs;
86
87 if (fs) {
88 int kill;
89 task_lock(tsk);
90 write_lock(&fs->lock);
91 tsk->fs = NULL;
92 kill = !--fs->users;
93 write_unlock(&fs->lock);
94 task_unlock(tsk);
95 if (kill)
96 free_fs_struct(fs);
97 }
98}
99
100struct fs_struct *copy_fs_struct(struct fs_struct *old)
101{
102 struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
103 /* We don't need to lock fs - think why ;-) */
104 if (fs) {
105 fs->users = 1;
106 fs->in_exec = 0;
107 rwlock_init(&fs->lock);
108 fs->umask = old->umask;
109 read_lock(&old->lock);
110 fs->root = old->root;
111 path_get(&old->root);
112 fs->pwd = old->pwd;
113 path_get(&old->pwd);
114 read_unlock(&old->lock);
115 }
116 return fs;
117}
118
119int unshare_fs_struct(void)
120{
121 struct fs_struct *fs = current->fs;
122 struct fs_struct *new_fs = copy_fs_struct(fs);
123 int kill;
124
125 if (!new_fs)
126 return -ENOMEM;
127
128 task_lock(current);
129 write_lock(&fs->lock);
130 kill = !--fs->users;
131 current->fs = new_fs;
132 write_unlock(&fs->lock);
133 task_unlock(current);
134
135 if (kill)
136 free_fs_struct(fs);
137
138 return 0;
139}
140EXPORT_SYMBOL_GPL(unshare_fs_struct);
141
142int current_umask(void)
143{
144 return current->fs->umask;
145}
146EXPORT_SYMBOL(current_umask);
147
148/* to be mentioned only in INIT_TASK */
149struct fs_struct init_fs = {
150 .users = 1,
151 .lock = __RW_LOCK_UNLOCKED(init_fs.lock),
152 .umask = 0022,
153};
154
155void daemonize_fs_struct(void)
156{
157 struct fs_struct *fs = current->fs;
158
159 if (fs) {
160 int kill;
161
162 task_lock(current);
163
164 write_lock(&init_fs.lock);
165 init_fs.users++;
166 write_unlock(&init_fs.lock);
167
168 write_lock(&fs->lock);
169 current->fs = &init_fs;
170 kill = !--fs->users;
171 write_unlock(&fs->lock);
172
173 task_unlock(current);
174 if (kill)
175 free_fs_struct(fs);
176 }
177}
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index 995d63b2e747..e0b53aa7bbec 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -134,7 +134,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
134 mode_t mode = inode->i_mode; 134 mode_t mode = inode->i_mode;
135 int error; 135 int error;
136 136
137 inode->i_mode = mode & ~current->fs->umask; 137 inode->i_mode = mode & ~current_umask();
138 if (!S_ISLNK(inode->i_mode)) 138 if (!S_ISLNK(inode->i_mode))
139 acl = ops->getacl(dir, ACL_TYPE_DEFAULT); 139 acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
140 if (acl) { 140 if (acl) {
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 43764f4fa763..fa881bdc3d85 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -215,7 +215,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
215 if (error) 215 if (error)
216 return error; 216 return error;
217 if (!acl) { 217 if (!acl) {
218 mode &= ~current->fs->umask; 218 mode &= ~current_umask();
219 if (mode != ip->i_inode.i_mode) 219 if (mode != ip->i_inode.i_mode)
220 error = munge_mode(ip, mode); 220 error = munge_mode(ip, mode);
221 return error; 221 return error;
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index bab7f8d1bdfa..3fcbb0e1f6fc 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -48,7 +48,7 @@ void hfsplus_fill_defaults(struct hfsplus_sb_info *opts)
48 48
49 opts->creator = HFSPLUS_DEF_CR_TYPE; 49 opts->creator = HFSPLUS_DEF_CR_TYPE;
50 opts->type = HFSPLUS_DEF_CR_TYPE; 50 opts->type = HFSPLUS_DEF_CR_TYPE;
51 opts->umask = current->fs->umask; 51 opts->umask = current_umask();
52 opts->uid = current_uid(); 52 opts->uid = current_uid();
53 opts->gid = current_gid(); 53 opts->gid = current_gid();
54 opts->part = -1; 54 opts->part = -1;
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index c40f6e242444..fecf402d7b8a 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -480,7 +480,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
480 480
481 uid = current_uid(); 481 uid = current_uid();
482 gid = current_gid(); 482 gid = current_gid();
483 umask = current->fs->umask; 483 umask = current_umask();
484 lowercase = 0; 484 lowercase = 0;
485 conv = CONV_BINARY; 485 conv = CONV_BINARY;
486 eas = 2; 486 eas = 2;
diff --git a/fs/internal.h b/fs/internal.h
index 53af885f1732..b4dac4fb6b61 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -11,6 +11,7 @@
11 11
12struct super_block; 12struct super_block;
13struct linux_binprm; 13struct linux_binprm;
14struct path;
14 15
15/* 16/*
16 * block_dev.c 17 * block_dev.c
@@ -43,7 +44,7 @@ extern void __init chrdev_init(void);
43/* 44/*
44 * exec.c 45 * exec.c
45 */ 46 */
46extern void check_unsafe_exec(struct linux_binprm *); 47extern int check_unsafe_exec(struct linux_binprm *);
47 48
48/* 49/*
49 * namespace.c 50 * namespace.c
@@ -60,3 +61,8 @@ extern void umount_tree(struct vfsmount *, int, struct list_head *);
60extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); 61extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
61 62
62extern void __init mnt_init(void); 63extern void __init mnt_init(void);
64
65/*
66 * fs_struct.c
67 */
68extern void chroot_fs_refs(struct path *, struct path *);
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index d98713777a1b..77ccf8cb0823 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -336,7 +336,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
336 return PTR_ERR(acl); 336 return PTR_ERR(acl);
337 337
338 if (!acl) { 338 if (!acl) {
339 *i_mode &= ~current->fs->umask; 339 *i_mode &= ~current_umask();
340 } else { 340 } else {
341 if (S_ISDIR(*i_mode)) 341 if (S_ISDIR(*i_mode))
342 jffs2_iset_acl(inode, &f->i_acl_default, acl); 342 jffs2_iset_acl(inode, &f->i_acl_default, acl);
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index a166c1669e82..06ca1b8d2054 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -182,7 +182,7 @@ int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
182cleanup: 182cleanup:
183 posix_acl_release(acl); 183 posix_acl_release(acl);
184 } else 184 } else
185 inode->i_mode &= ~current->fs->umask; 185 inode->i_mode &= ~current_umask();
186 186
187 JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) | 187 JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
188 inode->i_mode; 188 inode->i_mode;
diff --git a/fs/mpage.c b/fs/mpage.c
index 16c3ef37eae3..680ba60863ff 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -82,7 +82,7 @@ static void mpage_end_io_write(struct bio *bio, int err)
82 bio_put(bio); 82 bio_put(bio);
83} 83}
84 84
85struct bio *mpage_bio_submit(int rw, struct bio *bio) 85static struct bio *mpage_bio_submit(int rw, struct bio *bio)
86{ 86{
87 bio->bi_end_io = mpage_end_io_read; 87 bio->bi_end_io = mpage_end_io_read;
88 if (rw == WRITE) 88 if (rw == WRITE)
@@ -90,7 +90,6 @@ struct bio *mpage_bio_submit(int rw, struct bio *bio)
90 submit_bio(rw, bio); 90 submit_bio(rw, bio);
91 return NULL; 91 return NULL;
92} 92}
93EXPORT_SYMBOL(mpage_bio_submit);
94 93
95static struct bio * 94static struct bio *
96mpage_alloc(struct block_device *bdev, 95mpage_alloc(struct block_device *bdev,
@@ -439,7 +438,14 @@ EXPORT_SYMBOL(mpage_readpage);
439 * just allocate full-size (16-page) BIOs. 438 * just allocate full-size (16-page) BIOs.
440 */ 439 */
441 440
442int __mpage_writepage(struct page *page, struct writeback_control *wbc, 441struct mpage_data {
442 struct bio *bio;
443 sector_t last_block_in_bio;
444 get_block_t *get_block;
445 unsigned use_writepage;
446};
447
448static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
443 void *data) 449 void *data)
444{ 450{
445 struct mpage_data *mpd = data; 451 struct mpage_data *mpd = data;
@@ -648,7 +654,6 @@ out:
648 mpd->bio = bio; 654 mpd->bio = bio;
649 return ret; 655 return ret;
650} 656}
651EXPORT_SYMBOL(__mpage_writepage);
652 657
653/** 658/**
654 * mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them 659 * mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them
diff --git a/fs/namei.c b/fs/namei.c
index d040ce11785d..b8433ebfae05 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -32,6 +32,7 @@
32#include <linux/file.h> 32#include <linux/file.h>
33#include <linux/fcntl.h> 33#include <linux/fcntl.h>
34#include <linux/device_cgroup.h> 34#include <linux/device_cgroup.h>
35#include <linux/fs_struct.h>
35#include <asm/uaccess.h> 36#include <asm/uaccess.h>
36 37
37#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) 38#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
@@ -1578,7 +1579,7 @@ static int __open_namei_create(struct nameidata *nd, struct path *path,
1578 struct dentry *dir = nd->path.dentry; 1579 struct dentry *dir = nd->path.dentry;
1579 1580
1580 if (!IS_POSIXACL(dir->d_inode)) 1581 if (!IS_POSIXACL(dir->d_inode))
1581 mode &= ~current->fs->umask; 1582 mode &= ~current_umask();
1582 error = security_path_mknod(&nd->path, path->dentry, mode, 0); 1583 error = security_path_mknod(&nd->path, path->dentry, mode, 0);
1583 if (error) 1584 if (error)
1584 goto out_unlock; 1585 goto out_unlock;
@@ -1989,7 +1990,7 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode,
1989 goto out_unlock; 1990 goto out_unlock;
1990 } 1991 }
1991 if (!IS_POSIXACL(nd.path.dentry->d_inode)) 1992 if (!IS_POSIXACL(nd.path.dentry->d_inode))
1992 mode &= ~current->fs->umask; 1993 mode &= ~current_umask();
1993 error = may_mknod(mode); 1994 error = may_mknod(mode);
1994 if (error) 1995 if (error)
1995 goto out_dput; 1996 goto out_dput;
@@ -2067,7 +2068,7 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode)
2067 goto out_unlock; 2068 goto out_unlock;
2068 2069
2069 if (!IS_POSIXACL(nd.path.dentry->d_inode)) 2070 if (!IS_POSIXACL(nd.path.dentry->d_inode))
2070 mode &= ~current->fs->umask; 2071 mode &= ~current_umask();
2071 error = mnt_want_write(nd.path.mnt); 2072 error = mnt_want_write(nd.path.mnt);
2072 if (error) 2073 if (error)
2073 goto out_dput; 2074 goto out_dput;
@@ -2897,10 +2898,3 @@ EXPORT_SYMBOL(vfs_symlink);
2897EXPORT_SYMBOL(vfs_unlink); 2898EXPORT_SYMBOL(vfs_unlink);
2898EXPORT_SYMBOL(dentry_unhash); 2899EXPORT_SYMBOL(dentry_unhash);
2899EXPORT_SYMBOL(generic_readlink); 2900EXPORT_SYMBOL(generic_readlink);
2900
2901/* to be mentioned only in INIT_TASK */
2902struct fs_struct init_fs = {
2903 .count = ATOMIC_INIT(1),
2904 .lock = __RW_LOCK_UNLOCKED(init_fs.lock),
2905 .umask = 0022,
2906};
diff --git a/fs/namespace.c b/fs/namespace.c
index 0a42e0e96027..c6f54e4c4290 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -27,6 +27,7 @@
27#include <linux/ramfs.h> 27#include <linux/ramfs.h>
28#include <linux/log2.h> 28#include <linux/log2.h>
29#include <linux/idr.h> 29#include <linux/idr.h>
30#include <linux/fs_struct.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
31#include <asm/unistd.h> 32#include <asm/unistd.h>
32#include "pnode.h" 33#include "pnode.h"
@@ -2093,66 +2094,6 @@ out1:
2093} 2094}
2094 2095
2095/* 2096/*
2096 * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
2097 * It can block. Requires the big lock held.
2098 */
2099void set_fs_root(struct fs_struct *fs, struct path *path)
2100{
2101 struct path old_root;
2102
2103 write_lock(&fs->lock);
2104 old_root = fs->root;
2105 fs->root = *path;
2106 path_get(path);
2107 write_unlock(&fs->lock);
2108 if (old_root.dentry)
2109 path_put(&old_root);
2110}
2111
2112/*
2113 * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
2114 * It can block. Requires the big lock held.
2115 */
2116void set_fs_pwd(struct fs_struct *fs, struct path *path)
2117{
2118 struct path old_pwd;
2119
2120 write_lock(&fs->lock);
2121 old_pwd = fs->pwd;
2122 fs->pwd = *path;
2123 path_get(path);
2124 write_unlock(&fs->lock);
2125
2126 if (old_pwd.dentry)
2127 path_put(&old_pwd);
2128}
2129
2130static void chroot_fs_refs(struct path *old_root, struct path *new_root)
2131{
2132 struct task_struct *g, *p;
2133 struct fs_struct *fs;
2134
2135 read_lock(&tasklist_lock);
2136 do_each_thread(g, p) {
2137 task_lock(p);
2138 fs = p->fs;
2139 if (fs) {
2140 atomic_inc(&fs->count);
2141 task_unlock(p);
2142 if (fs->root.dentry == old_root->dentry
2143 && fs->root.mnt == old_root->mnt)
2144 set_fs_root(fs, new_root);
2145 if (fs->pwd.dentry == old_root->dentry
2146 && fs->pwd.mnt == old_root->mnt)
2147 set_fs_pwd(fs, new_root);
2148 put_fs_struct(fs);
2149 } else
2150 task_unlock(p);
2151 } while_each_thread(g, p);
2152 read_unlock(&tasklist_lock);
2153}
2154
2155/*
2156 * pivot_root Semantics: 2097 * pivot_root Semantics:
2157 * Moves the root file system of the current process to the directory put_old, 2098 * Moves the root file system of the current process to the directory put_old,
2158 * makes new_root as the new root file system of the current process, and sets 2099 * makes new_root as the new root file system of the current process, and sets
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index b82fe6847f14..d0cc5ce0edfe 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -328,7 +328,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
328 data->arg.create.verifier[1] = current->pid; 328 data->arg.create.verifier[1] = current->pid;
329 } 329 }
330 330
331 sattr->ia_mode &= ~current->fs->umask; 331 sattr->ia_mode &= ~current_umask();
332 332
333 for (;;) { 333 for (;;) {
334 status = nfs3_do_create(dir, dentry, data); 334 status = nfs3_do_create(dir, dentry, data);
@@ -528,7 +528,7 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
528 528
529 dprintk("NFS call mkdir %s\n", dentry->d_name.name); 529 dprintk("NFS call mkdir %s\n", dentry->d_name.name);
530 530
531 sattr->ia_mode &= ~current->fs->umask; 531 sattr->ia_mode &= ~current_umask();
532 532
533 data = nfs3_alloc_createdata(); 533 data = nfs3_alloc_createdata();
534 if (data == NULL) 534 if (data == NULL)
@@ -639,7 +639,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
639 dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, 639 dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
640 MAJOR(rdev), MINOR(rdev)); 640 MAJOR(rdev), MINOR(rdev));
641 641
642 sattr->ia_mode &= ~current->fs->umask; 642 sattr->ia_mode &= ~current_umask();
643 643
644 data = nfs3_alloc_createdata(); 644 data = nfs3_alloc_createdata();
645 if (data == NULL) 645 if (data == NULL)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 97bacccff579..a4d242680299 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1501,7 +1501,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
1501 attr.ia_mode = nd->intent.open.create_mode; 1501 attr.ia_mode = nd->intent.open.create_mode;
1502 attr.ia_valid = ATTR_MODE; 1502 attr.ia_valid = ATTR_MODE;
1503 if (!IS_POSIXACL(dir)) 1503 if (!IS_POSIXACL(dir))
1504 attr.ia_mode &= ~current->fs->umask; 1504 attr.ia_mode &= ~current_umask();
1505 } else { 1505 } else {
1506 attr.ia_valid = 0; 1506 attr.ia_valid = 0;
1507 BUG_ON(nd->intent.open.flags & O_CREAT); 1507 BUG_ON(nd->intent.open.flags & O_CREAT);
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index bc3567bab8c4..7c09852be713 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -403,7 +403,6 @@ static int
403nfsd(void *vrqstp) 403nfsd(void *vrqstp)
404{ 404{
405 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 405 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
406 struct fs_struct *fsp;
407 int err, preverr = 0; 406 int err, preverr = 0;
408 407
409 /* Lock module and set up kernel thread */ 408 /* Lock module and set up kernel thread */
@@ -412,13 +411,11 @@ nfsd(void *vrqstp)
412 /* At this point, the thread shares current->fs 411 /* At this point, the thread shares current->fs
413 * with the init process. We need to create files with a 412 * with the init process. We need to create files with a
414 * umask of 0 instead of init's umask. */ 413 * umask of 0 instead of init's umask. */
415 fsp = copy_fs_struct(current->fs); 414 if (unshare_fs_struct() < 0) {
416 if (!fsp) {
417 printk("Unable to start nfsd thread: out of memory\n"); 415 printk("Unable to start nfsd thread: out of memory\n");
418 goto out; 416 goto out;
419 } 417 }
420 exit_fs(current); 418
421 current->fs = fsp;
422 current->fs->umask = 0; 419 current->fs->umask = 0;
423 420
424 /* 421 /*
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 12dfb44c22e5..fbeaec762103 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -296,7 +296,7 @@ int ocfs2_init_acl(handle_t *handle,
296 return PTR_ERR(acl); 296 return PTR_ERR(acl);
297 } 297 }
298 if (!acl) 298 if (!acl)
299 inode->i_mode &= ~current->fs->umask; 299 inode->i_mode &= ~current_umask();
300 } 300 }
301 if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { 301 if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
302 struct posix_acl *clone; 302 struct posix_acl *clone;
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index d79e808fd028..379ae5fb4411 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -426,7 +426,7 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
426 426
427 sbi->s_uid = current_uid(); 427 sbi->s_uid = current_uid();
428 sbi->s_gid = current_gid(); 428 sbi->s_gid = current_gid();
429 sbi->s_dmask = sbi->s_fmask = current->fs->umask; 429 sbi->s_dmask = sbi->s_fmask = current_umask();
430 430
431 if (!parse_options((char *) data, sbi)) 431 if (!parse_options((char *) data, sbi))
432 goto end; 432 goto end;
diff --git a/fs/open.c b/fs/open.c
index 75b61677daaf..377eb25b6abf 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -29,6 +29,7 @@
29#include <linux/rcupdate.h> 29#include <linux/rcupdate.h>
30#include <linux/audit.h> 30#include <linux/audit.h>
31#include <linux/falloc.h> 31#include <linux/falloc.h>
32#include <linux/fs_struct.h>
32 33
33int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) 34int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
34{ 35{
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e0afd326b688..f71559784bfb 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -80,6 +80,7 @@
80#include <linux/oom.h> 80#include <linux/oom.h>
81#include <linux/elf.h> 81#include <linux/elf.h>
82#include <linux/pid_namespace.h> 82#include <linux/pid_namespace.h>
83#include <linux/fs_struct.h>
83#include "internal.h" 84#include "internal.h"
84 85
85/* NOTE: 86/* NOTE:
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 370be0a2c909..863464d5519c 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -2,6 +2,7 @@
2#include <linux/mm.h> 2#include <linux/mm.h>
3#include <linux/file.h> 3#include <linux/file.h>
4#include <linux/fdtable.h> 4#include <linux/fdtable.h>
5#include <linux/fs_struct.h>
5#include <linux/mount.h> 6#include <linux/mount.h>
6#include <linux/ptrace.h> 7#include <linux/ptrace.h>
7#include <linux/seq_file.h> 8#include <linux/seq_file.h>
@@ -49,7 +50,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
49 else 50 else
50 bytes += kobjsize(mm); 51 bytes += kobjsize(mm);
51 52
52 if (current->fs && atomic_read(&current->fs->count) > 1) 53 if (current->fs && current->fs->users > 1)
53 sbytes += kobjsize(current->fs); 54 sbytes += kobjsize(current->fs);
54 else 55 else
55 bytes += kobjsize(current->fs); 56 bytes += kobjsize(current->fs);
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index d423416d93d1..c303c426fe2b 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -428,7 +428,7 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
428 } else { 428 } else {
429 apply_umask: 429 apply_umask:
430 /* no ACL, apply umask */ 430 /* no ACL, apply umask */
431 inode->i_mode &= ~current->fs->umask; 431 inode->i_mode &= ~current_umask();
432 } 432 }
433 433
434 return err; 434 return err;
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 7aa53fefc67f..2940612e3aeb 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -227,7 +227,7 @@ xfs_vn_mknod(
227 xfs_dentry_to_name(&name, dentry); 227 xfs_dentry_to_name(&name, dentry);
228 228
229 if (IS_POSIXACL(dir) && !default_acl) 229 if (IS_POSIXACL(dir) && !default_acl)
230 mode &= ~current->fs->umask; 230 mode &= ~current_umask();
231 231
232 switch (mode & S_IFMT) { 232 switch (mode & S_IFMT) {
233 case S_IFCHR: 233 case S_IFCHR:
@@ -416,7 +416,7 @@ xfs_vn_symlink(
416 mode_t mode; 416 mode_t mode;
417 417
418 mode = S_IFLNK | 418 mode = S_IFLNK |
419 (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); 419 (irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO);
420 xfs_dentry_to_name(&name, dentry); 420 xfs_dentry_to_name(&name, dentry);
421 421
422 error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL); 422 error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 3d7bcde2e332..7b73bb8f1970 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -332,22 +332,10 @@ extern int __set_page_dirty_buffers(struct page *page);
332 332
333static inline void buffer_init(void) {} 333static inline void buffer_init(void) {}
334static inline int try_to_free_buffers(struct page *page) { return 1; } 334static inline int try_to_free_buffers(struct page *page) { return 1; }
335static inline int sync_blockdev(struct block_device *bdev) { return 0; }
336static inline int inode_has_buffers(struct inode *inode) { return 0; } 335static inline int inode_has_buffers(struct inode *inode) { return 0; }
337static inline void invalidate_inode_buffers(struct inode *inode) {} 336static inline void invalidate_inode_buffers(struct inode *inode) {}
338static inline int remove_inode_buffers(struct inode *inode) { return 1; } 337static inline int remove_inode_buffers(struct inode *inode) { return 1; }
339static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; } 338static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; }
340static inline void invalidate_bdev(struct block_device *bdev) {}
341
342static inline struct super_block *freeze_bdev(struct block_device *sb)
343{
344 return NULL;
345}
346
347static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb)
348{
349 return 0;
350}
351 339
352#endif /* CONFIG_BLOCK */ 340#endif /* CONFIG_BLOCK */
353#endif /* _LINUX_BUFFER_HEAD_H */ 341#endif /* _LINUX_BUFFER_HEAD_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 61211ad823fe..a09e17c8f5fd 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1741,6 +1741,8 @@ extern void drop_collected_mounts(struct vfsmount *);
1741 1741
1742extern int vfs_statfs(struct dentry *, struct kstatfs *); 1742extern int vfs_statfs(struct dentry *, struct kstatfs *);
1743 1743
1744extern int current_umask(void);
1745
1744/* /sys/fs */ 1746/* /sys/fs */
1745extern struct kobject *fs_kobj; 1747extern struct kobject *fs_kobj;
1746 1748
@@ -1885,6 +1887,18 @@ extern int fsync_super(struct super_block *);
1885extern int fsync_no_super(struct block_device *); 1887extern int fsync_no_super(struct block_device *);
1886#else 1888#else
1887static inline void bd_forget(struct inode *inode) {} 1889static inline void bd_forget(struct inode *inode) {}
1890static inline int sync_blockdev(struct block_device *bdev) { return 0; }
1891static inline void invalidate_bdev(struct block_device *bdev) {}
1892
1893static inline struct super_block *freeze_bdev(struct block_device *sb)
1894{
1895 return NULL;
1896}
1897
1898static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb)
1899{
1900 return 0;
1901}
1888#endif 1902#endif
1889extern const struct file_operations def_blk_fops; 1903extern const struct file_operations def_blk_fops;
1890extern const struct file_operations def_chr_fops; 1904extern const struct file_operations def_chr_fops;
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h
index 18b467dbe278..78a05bfcd8eb 100644
--- a/include/linux/fs_struct.h
+++ b/include/linux/fs_struct.h
@@ -4,12 +4,10 @@
4#include <linux/path.h> 4#include <linux/path.h>
5 5
6struct fs_struct { 6struct fs_struct {
7 atomic_t count; /* This usage count is used by check_unsafe_exec() for 7 int users;
8 * security checking purposes - therefore it may not be
9 * incremented, except by clone(CLONE_FS).
10 */
11 rwlock_t lock; 8 rwlock_t lock;
12 int umask; 9 int umask;
10 int in_exec;
13 struct path root, pwd; 11 struct path root, pwd;
14}; 12};
15 13
@@ -19,6 +17,8 @@ extern void exit_fs(struct task_struct *);
19extern void set_fs_root(struct fs_struct *, struct path *); 17extern void set_fs_root(struct fs_struct *, struct path *);
20extern void set_fs_pwd(struct fs_struct *, struct path *); 18extern void set_fs_pwd(struct fs_struct *, struct path *);
21extern struct fs_struct *copy_fs_struct(struct fs_struct *); 19extern struct fs_struct *copy_fs_struct(struct fs_struct *);
22extern void put_fs_struct(struct fs_struct *); 20extern void free_fs_struct(struct fs_struct *);
21extern void daemonize_fs_struct(void);
22extern int unshare_fs_struct(void);
23 23
24#endif /* _LINUX_FS_STRUCT_H */ 24#endif /* _LINUX_FS_STRUCT_H */
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 830bbcd449d6..3a059298cc19 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -22,6 +22,8 @@ struct proc_mounts {
22 int event; 22 int event;
23}; 23};
24 24
25struct fs_struct;
26
25extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, 27extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
26 struct fs_struct *); 28 struct fs_struct *);
27extern void __put_mnt_ns(struct mnt_namespace *ns); 29extern void __put_mnt_ns(struct mnt_namespace *ns);
diff --git a/include/linux/mpage.h b/include/linux/mpage.h
index 5c42821da2d1..068a0c9946af 100644
--- a/include/linux/mpage.h
+++ b/include/linux/mpage.h
@@ -11,21 +11,11 @@
11 */ 11 */
12#ifdef CONFIG_BLOCK 12#ifdef CONFIG_BLOCK
13 13
14struct mpage_data {
15 struct bio *bio;
16 sector_t last_block_in_bio;
17 get_block_t *get_block;
18 unsigned use_writepage;
19};
20
21struct writeback_control; 14struct writeback_control;
22 15
23struct bio *mpage_bio_submit(int rw, struct bio *bio);
24int mpage_readpages(struct address_space *mapping, struct list_head *pages, 16int mpage_readpages(struct address_space *mapping, struct list_head *pages,
25 unsigned nr_pages, get_block_t get_block); 17 unsigned nr_pages, get_block_t get_block);
26int mpage_readpage(struct page *page, get_block_t get_block); 18int mpage_readpage(struct page *page, get_block_t get_block);
27int __mpage_writepage(struct page *page, struct writeback_control *wbc,
28 void *data);
29int mpage_writepages(struct address_space *mapping, 19int mpage_writepages(struct address_space *mapping,
30 struct writeback_control *wbc, get_block_t get_block); 20 struct writeback_control *wbc, get_block_t get_block);
31int mpage_writepage(struct page *page, get_block_t *get_block, 21int mpage_writepage(struct page *page, get_block_t *get_block,
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index afad7dec1b36..7b370c7cfeff 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -8,6 +8,7 @@ struct mnt_namespace;
8struct uts_namespace; 8struct uts_namespace;
9struct ipc_namespace; 9struct ipc_namespace;
10struct pid_namespace; 10struct pid_namespace;
11struct fs_struct;
11 12
12/* 13/*
13 * A structure to contain pointers to all per-process 14 * A structure to contain pointers to all per-process
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 206ac003e8c0..9da5aa0771ef 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -68,7 +68,7 @@ struct sched_param {
68#include <linux/smp.h> 68#include <linux/smp.h>
69#include <linux/sem.h> 69#include <linux/sem.h>
70#include <linux/signal.h> 70#include <linux/signal.h>
71#include <linux/fs_struct.h> 71#include <linux/path.h>
72#include <linux/compiler.h> 72#include <linux/compiler.h>
73#include <linux/completion.h> 73#include <linux/completion.h>
74#include <linux/pid.h> 74#include <linux/pid.h>
@@ -97,6 +97,7 @@ struct futex_pi_state;
97struct robust_list_head; 97struct robust_list_head;
98struct bio; 98struct bio;
99struct bts_tracer; 99struct bts_tracer;
100struct fs_struct;
100 101
101/* 102/*
102 * List of flags we want to share for kernel threads, 103 * List of flags we want to share for kernel threads,
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 8d4ff5afc1d8..dd7ee5f203f3 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -14,6 +14,7 @@
14#include <linux/fs.h> 14#include <linux/fs.h>
15#include <linux/initrd.h> 15#include <linux/initrd.h>
16#include <linux/async.h> 16#include <linux/async.h>
17#include <linux/fs_struct.h>
17 18
18#include <linux/nfs_fs.h> 19#include <linux/nfs_fs.h>
19#include <linux/nfs_fs_sb.h> 20#include <linux/nfs_fs_sb.h>
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index a8ddadbc7459..916785363f0f 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -602,7 +602,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
602 dentry->d_fsdata = attr; 602 dentry->d_fsdata = attr;
603 } 603 }
604 604
605 mode &= ~current->fs->umask; 605 mode &= ~current_umask();
606 ret = mnt_want_write(mqueue_mnt); 606 ret = mnt_want_write(mqueue_mnt);
607 if (ret) 607 if (ret)
608 goto out; 608 goto out;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8cbddff6c283..2bfc64786765 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -66,6 +66,7 @@
66#include <linux/syscalls.h> 66#include <linux/syscalls.h>
67#include <linux/inotify.h> 67#include <linux/inotify.h>
68#include <linux/capability.h> 68#include <linux/capability.h>
69#include <linux/fs_struct.h>
69 70
70#include "audit.h" 71#include "audit.h"
71 72
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index 667c841c2952..c35452cadded 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -18,6 +18,7 @@
18#include <linux/syscalls.h> 18#include <linux/syscalls.h>
19#include <linux/sysctl.h> 19#include <linux/sysctl.h>
20#include <linux/types.h> 20#include <linux/types.h>
21#include <linux/fs_struct.h>
21 22
22 23
23static void default_handler(int, struct pt_regs *); 24static void default_handler(int, struct pt_regs *);
@@ -145,28 +146,6 @@ __set_personality(u_long personality)
145 return 0; 146 return 0;
146 } 147 }
147 148
148 if (atomic_read(&current->fs->count) != 1) {
149 struct fs_struct *fsp, *ofsp;
150
151 fsp = copy_fs_struct(current->fs);
152 if (fsp == NULL) {
153 module_put(ep->module);
154 return -ENOMEM;
155 }
156
157 task_lock(current);
158 ofsp = current->fs;
159 current->fs = fsp;
160 task_unlock(current);
161
162 put_fs_struct(ofsp);
163 }
164
165 /*
166 * At that point we are guaranteed to be the sole owner of
167 * current->fs.
168 */
169
170 current->personality = personality; 149 current->personality = personality;
171 oep = current_thread_info()->exec_domain; 150 oep = current_thread_info()->exec_domain;
172 current_thread_info()->exec_domain = ep; 151 current_thread_info()->exec_domain = ep;
diff --git a/kernel/exit.c b/kernel/exit.c
index 3bec141c82f6..6686ed1e4aa3 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -46,6 +46,7 @@
46#include <linux/blkdev.h> 46#include <linux/blkdev.h>
47#include <linux/task_io_accounting_ops.h> 47#include <linux/task_io_accounting_ops.h>
48#include <linux/tracehook.h> 48#include <linux/tracehook.h>
49#include <linux/fs_struct.h>
49#include <linux/init_task.h> 50#include <linux/init_task.h>
50#include <trace/sched.h> 51#include <trace/sched.h>
51 52
@@ -420,7 +421,6 @@ EXPORT_SYMBOL(disallow_signal);
420void daemonize(const char *name, ...) 421void daemonize(const char *name, ...)
421{ 422{
422 va_list args; 423 va_list args;
423 struct fs_struct *fs;
424 sigset_t blocked; 424 sigset_t blocked;
425 425
426 va_start(args, name); 426 va_start(args, name);
@@ -453,11 +453,7 @@ void daemonize(const char *name, ...)
453 453
454 /* Become as one with the init task */ 454 /* Become as one with the init task */
455 455
456 exit_fs(current); /* current->fs->count--; */ 456 daemonize_fs_struct();
457 fs = init_task.fs;
458 current->fs = fs;
459 atomic_inc(&fs->count);
460
461 exit_files(current); 457 exit_files(current);
462 current->files = init_task.files; 458 current->files = init_task.files;
463 atomic_inc(&current->files->count); 459 atomic_inc(&current->files->count);
@@ -556,30 +552,6 @@ void exit_files(struct task_struct *tsk)
556 } 552 }
557} 553}
558 554
559void put_fs_struct(struct fs_struct *fs)
560{
561 /* No need to hold fs->lock if we are killing it */
562 if (atomic_dec_and_test(&fs->count)) {
563 path_put(&fs->root);
564 path_put(&fs->pwd);
565 kmem_cache_free(fs_cachep, fs);
566 }
567}
568
569void exit_fs(struct task_struct *tsk)
570{
571 struct fs_struct * fs = tsk->fs;
572
573 if (fs) {
574 task_lock(tsk);
575 tsk->fs = NULL;
576 task_unlock(tsk);
577 put_fs_struct(fs);
578 }
579}
580
581EXPORT_SYMBOL_GPL(exit_fs);
582
583#ifdef CONFIG_MM_OWNER 555#ifdef CONFIG_MM_OWNER
584/* 556/*
585 * Task p is exiting and it owned mm, lets find a new owner for it 557 * Task p is exiting and it owned mm, lets find a new owner for it
diff --git a/kernel/fork.c b/kernel/fork.c
index f74458231449..660c2b8765bc 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -60,6 +60,7 @@
60#include <linux/tty.h> 60#include <linux/tty.h>
61#include <linux/proc_fs.h> 61#include <linux/proc_fs.h>
62#include <linux/blkdev.h> 62#include <linux/blkdev.h>
63#include <linux/fs_struct.h>
63#include <trace/sched.h> 64#include <trace/sched.h>
64#include <linux/magic.h> 65#include <linux/magic.h>
65 66
@@ -681,38 +682,21 @@ fail_nomem:
681 return retval; 682 return retval;
682} 683}
683 684
684static struct fs_struct *__copy_fs_struct(struct fs_struct *old)
685{
686 struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
687 /* We don't need to lock fs - think why ;-) */
688 if (fs) {
689 atomic_set(&fs->count, 1);
690 rwlock_init(&fs->lock);
691 fs->umask = old->umask;
692 read_lock(&old->lock);
693 fs->root = old->root;
694 path_get(&old->root);
695 fs->pwd = old->pwd;
696 path_get(&old->pwd);
697 read_unlock(&old->lock);
698 }
699 return fs;
700}
701
702struct fs_struct *copy_fs_struct(struct fs_struct *old)
703{
704 return __copy_fs_struct(old);
705}
706
707EXPORT_SYMBOL_GPL(copy_fs_struct);
708
709static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) 685static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
710{ 686{
687 struct fs_struct *fs = current->fs;
711 if (clone_flags & CLONE_FS) { 688 if (clone_flags & CLONE_FS) {
712 atomic_inc(&current->fs->count); 689 /* tsk->fs is already what we want */
690 write_lock(&fs->lock);
691 if (fs->in_exec) {
692 write_unlock(&fs->lock);
693 return -EAGAIN;
694 }
695 fs->users++;
696 write_unlock(&fs->lock);
713 return 0; 697 return 0;
714 } 698 }
715 tsk->fs = __copy_fs_struct(current->fs); 699 tsk->fs = copy_fs_struct(fs);
716 if (!tsk->fs) 700 if (!tsk->fs)
717 return -ENOMEM; 701 return -ENOMEM;
718 return 0; 702 return 0;
@@ -1544,12 +1528,16 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
1544{ 1528{
1545 struct fs_struct *fs = current->fs; 1529 struct fs_struct *fs = current->fs;
1546 1530
1547 if ((unshare_flags & CLONE_FS) && 1531 if (!(unshare_flags & CLONE_FS) || !fs)
1548 (fs && atomic_read(&fs->count) > 1)) { 1532 return 0;
1549 *new_fsp = __copy_fs_struct(current->fs); 1533
1550 if (!*new_fsp) 1534 /* don't need lock here; in the worst case we'll do useless copy */
1551 return -ENOMEM; 1535 if (fs->users == 1)
1552 } 1536 return 0;
1537
1538 *new_fsp = copy_fs_struct(fs);
1539 if (!*new_fsp)
1540 return -ENOMEM;
1553 1541
1554 return 0; 1542 return 0;
1555} 1543}
@@ -1665,8 +1653,13 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
1665 1653
1666 if (new_fs) { 1654 if (new_fs) {
1667 fs = current->fs; 1655 fs = current->fs;
1656 write_lock(&fs->lock);
1668 current->fs = new_fs; 1657 current->fs = new_fs;
1669 new_fs = fs; 1658 if (--fs->users)
1659 new_fs = NULL;
1660 else
1661 new_fs = fs;
1662 write_unlock(&fs->lock);
1670 } 1663 }
1671 1664
1672 if (new_mm) { 1665 if (new_mm) {
@@ -1705,7 +1698,7 @@ bad_unshare_cleanup_sigh:
1705 1698
1706bad_unshare_cleanup_fs: 1699bad_unshare_cleanup_fs:
1707 if (new_fs) 1700 if (new_fs)
1708 put_fs_struct(new_fs); 1701 free_fs_struct(new_fs);
1709 1702
1710bad_unshare_cleanup_thread: 1703bad_unshare_cleanup_thread:
1711bad_unshare_out: 1704bad_unshare_out:
diff --git a/kernel/sys.c b/kernel/sys.c
index 742cefa527e6..51dbb55604e8 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -34,6 +34,7 @@
34#include <linux/seccomp.h> 34#include <linux/seccomp.h>
35#include <linux/cpu.h> 35#include <linux/cpu.h>
36#include <linux/ptrace.h> 36#include <linux/ptrace.h>
37#include <linux/fs_struct.h>
37 38
38#include <linux/compat.h> 39#include <linux/compat.h>
39#include <linux/syscalls.h> 40#include <linux/syscalls.h>
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index baac91049b0e..9dcc6e7f96ec 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -832,7 +832,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
832 * All right, let's create it. 832 * All right, let's create it.
833 */ 833 */
834 mode = S_IFSOCK | 834 mode = S_IFSOCK |
835 (SOCK_INODE(sock)->i_mode & ~current->fs->umask); 835 (SOCK_INODE(sock)->i_mode & ~current_umask());
836 err = mnt_want_write(nd.path.mnt); 836 err = mnt_want_write(nd.path.mnt);
837 if (err) 837 if (err)
838 goto out_mknod_dput; 838 goto out_mknod_dput;
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index d47f16b844b2..3bbe01a7a4b5 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -12,6 +12,7 @@
12#include <linux/types.h> 12#include <linux/types.h>
13#include <linux/mount.h> 13#include <linux/mount.h>
14#include <linux/mnt_namespace.h> 14#include <linux/mnt_namespace.h>
15#include <linux/fs_struct.h>
15#include "common.h" 16#include "common.h"
16#include "realpath.h" 17#include "realpath.h"
17 18