diff options
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 | ||
17 | struct tty_audit_buf { | 15 | struct 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 | ||
16 | ifeq ($(CONFIG_BLOCK),y) | 16 | ifeq ($(CONFIG_BLOCK),y) |
17 | obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o | 17 | obj-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); |
1029 | out_free_interp: | 1013 | out_free_interp: |
1030 | kfree(elf_interpreter); | 1014 | kfree(elf_interpreter); |
1031 | out_free_file: | ||
1032 | sys_close(elf_exec_fileno); | ||
1033 | out_free_ph: | 1015 | out_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: | |||
188 | static int | 188 | static int |
189 | load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) | 189 | load_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 | } |
207 | EXPORT_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); | |||
3315 | EXPORT_SYMBOL(end_buffer_read_sync); | 3315 | EXPORT_SYMBOL(end_buffer_read_sync); |
3316 | EXPORT_SYMBOL(end_buffer_write_sync); | 3316 | EXPORT_SYMBOL(end_buffer_write_sync); |
3317 | EXPORT_SYMBOL(file_fsync); | 3317 | EXPORT_SYMBOL(file_fsync); |
3318 | EXPORT_SYMBOL(fsync_bdev); | ||
3319 | EXPORT_SYMBOL(generic_block_bmap); | 3318 | EXPORT_SYMBOL(generic_block_bmap); |
3320 | EXPORT_SYMBOL(generic_cont_expand_simple); | 3319 | EXPORT_SYMBOL(generic_cont_expand_simple); |
3321 | EXPORT_SYMBOL(init_buffer); | 3320 | EXPORT_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(¤t->fs->lock); | ||
1557 | current->fs->in_exec = 0; | ||
1558 | write_unlock(¤t->fs->lock); | ||
1552 | current->in_execve = 0; | 1559 | current->in_execve = 0; |
1553 | mutex_unlock(¤t->cred_exec_mutex); | 1560 | mutex_unlock(¤t->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 | ||
1577 | out_unmark: | ||
1578 | write_lock(¤t->fs->lock); | ||
1579 | current->fs->in_exec = 0; | ||
1580 | write_unlock(¤t->fs->lock); | ||
1581 | |||
1570 | out_unlock: | 1582 | out_unlock: |
1571 | current->in_execve = 0; | 1583 | current->in_execve = 0; |
1572 | mutex_unlock(¤t->cred_exec_mutex); | 1584 | mutex_unlock(¤t->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 | ||
37 | int sysctl_vfs_cache_pressure __read_mostly = 100; | 37 | int sysctl_vfs_cache_pressure __read_mostly = 100; |
@@ -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 | */ |
1059 | void check_unsafe_exec(struct linux_binprm *bprm) | 1060 | int 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(¤t->fs->lock); | ||
1359 | current->fs->in_exec = 0; | ||
1360 | write_unlock(¤t->fs->lock); | ||
1347 | current->in_execve = 0; | 1361 | current->in_execve = 0; |
1348 | mutex_unlock(¤t->cred_exec_mutex); | 1362 | mutex_unlock(¤t->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 | ||
1379 | out_unmark: | ||
1380 | write_lock(¤t->fs->lock); | ||
1381 | current->fs->in_exec = 0; | ||
1382 | write_unlock(¤t->fs->lock); | ||
1383 | |||
1365 | out_unlock: | 1384 | out_unlock: |
1366 | current->in_execve = 0; | 1385 | current->in_execve = 0; |
1367 | mutex_unlock(¤t->cred_exec_mutex); | 1386 | mutex_unlock(¤t->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 | */ | ||
12 | void 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 | */ | ||
29 | void 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 | |||
43 | void 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 | |||
76 | void 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 | |||
83 | void 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 | |||
100 | struct 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 | |||
119 | int 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 | } | ||
140 | EXPORT_SYMBOL_GPL(unshare_fs_struct); | ||
141 | |||
142 | int current_umask(void) | ||
143 | { | ||
144 | return current->fs->umask; | ||
145 | } | ||
146 | EXPORT_SYMBOL(current_umask); | ||
147 | |||
148 | /* to be mentioned only in INIT_TASK */ | ||
149 | struct fs_struct init_fs = { | ||
150 | .users = 1, | ||
151 | .lock = __RW_LOCK_UNLOCKED(init_fs.lock), | ||
152 | .umask = 0022, | ||
153 | }; | ||
154 | |||
155 | void 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 | ||
12 | struct super_block; | 12 | struct super_block; |
13 | struct linux_binprm; | 13 | struct linux_binprm; |
14 | struct 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 | */ |
46 | extern void check_unsafe_exec(struct linux_binprm *); | 47 | extern 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 *); | |||
60 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); | 61 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); |
61 | 62 | ||
62 | extern void __init mnt_init(void); | 63 | extern void __init mnt_init(void); |
64 | |||
65 | /* | ||
66 | * fs_struct.c | ||
67 | */ | ||
68 | extern 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) | |||
182 | cleanup: | 182 | cleanup: |
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 | ||
85 | struct bio *mpage_bio_submit(int rw, struct bio *bio) | 85 | static 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 | } |
93 | EXPORT_SYMBOL(mpage_bio_submit); | ||
94 | 93 | ||
95 | static struct bio * | 94 | static struct bio * |
96 | mpage_alloc(struct block_device *bdev, | 95 | mpage_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 | ||
442 | int __mpage_writepage(struct page *page, struct writeback_control *wbc, | 441 | struct 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 | |||
448 | static 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 | } |
651 | EXPORT_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); | |||
2897 | EXPORT_SYMBOL(vfs_unlink); | 2898 | EXPORT_SYMBOL(vfs_unlink); |
2898 | EXPORT_SYMBOL(dentry_unhash); | 2899 | EXPORT_SYMBOL(dentry_unhash); |
2899 | EXPORT_SYMBOL(generic_readlink); | 2900 | EXPORT_SYMBOL(generic_readlink); |
2900 | |||
2901 | /* to be mentioned only in INIT_TASK */ | ||
2902 | struct 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 | */ | ||
2099 | void 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 | */ | ||
2116 | void 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 | |||
2130 | static 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 | |||
403 | nfsd(void *vrqstp) | 403 | nfsd(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; |
@@ -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 | ||
33 | int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 34 | int 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(¤t->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 | ||
333 | static inline void buffer_init(void) {} | 333 | static inline void buffer_init(void) {} |
334 | static inline int try_to_free_buffers(struct page *page) { return 1; } | 334 | static inline int try_to_free_buffers(struct page *page) { return 1; } |
335 | static inline int sync_blockdev(struct block_device *bdev) { return 0; } | ||
336 | static inline int inode_has_buffers(struct inode *inode) { return 0; } | 335 | static inline int inode_has_buffers(struct inode *inode) { return 0; } |
337 | static inline void invalidate_inode_buffers(struct inode *inode) {} | 336 | static inline void invalidate_inode_buffers(struct inode *inode) {} |
338 | static inline int remove_inode_buffers(struct inode *inode) { return 1; } | 337 | static inline int remove_inode_buffers(struct inode *inode) { return 1; } |
339 | static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; } | 338 | static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; } |
340 | static inline void invalidate_bdev(struct block_device *bdev) {} | ||
341 | |||
342 | static inline struct super_block *freeze_bdev(struct block_device *sb) | ||
343 | { | ||
344 | return NULL; | ||
345 | } | ||
346 | |||
347 | static 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 | ||
1742 | extern int vfs_statfs(struct dentry *, struct kstatfs *); | 1742 | extern int vfs_statfs(struct dentry *, struct kstatfs *); |
1743 | 1743 | ||
1744 | extern int current_umask(void); | ||
1745 | |||
1744 | /* /sys/fs */ | 1746 | /* /sys/fs */ |
1745 | extern struct kobject *fs_kobj; | 1747 | extern struct kobject *fs_kobj; |
1746 | 1748 | ||
@@ -1885,6 +1887,18 @@ extern int fsync_super(struct super_block *); | |||
1885 | extern int fsync_no_super(struct block_device *); | 1887 | extern int fsync_no_super(struct block_device *); |
1886 | #else | 1888 | #else |
1887 | static inline void bd_forget(struct inode *inode) {} | 1889 | static inline void bd_forget(struct inode *inode) {} |
1890 | static inline int sync_blockdev(struct block_device *bdev) { return 0; } | ||
1891 | static inline void invalidate_bdev(struct block_device *bdev) {} | ||
1892 | |||
1893 | static inline struct super_block *freeze_bdev(struct block_device *sb) | ||
1894 | { | ||
1895 | return NULL; | ||
1896 | } | ||
1897 | |||
1898 | static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb) | ||
1899 | { | ||
1900 | return 0; | ||
1901 | } | ||
1888 | #endif | 1902 | #endif |
1889 | extern const struct file_operations def_blk_fops; | 1903 | extern const struct file_operations def_blk_fops; |
1890 | extern const struct file_operations def_chr_fops; | 1904 | extern 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 | ||
6 | struct fs_struct { | 6 | struct 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 *); | |||
19 | extern void set_fs_root(struct fs_struct *, struct path *); | 17 | extern void set_fs_root(struct fs_struct *, struct path *); |
20 | extern void set_fs_pwd(struct fs_struct *, struct path *); | 18 | extern void set_fs_pwd(struct fs_struct *, struct path *); |
21 | extern struct fs_struct *copy_fs_struct(struct fs_struct *); | 19 | extern struct fs_struct *copy_fs_struct(struct fs_struct *); |
22 | extern void put_fs_struct(struct fs_struct *); | 20 | extern void free_fs_struct(struct fs_struct *); |
21 | extern void daemonize_fs_struct(void); | ||
22 | extern 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 | ||
25 | struct fs_struct; | ||
26 | |||
25 | extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, | 27 | extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, |
26 | struct fs_struct *); | 28 | struct fs_struct *); |
27 | extern void __put_mnt_ns(struct mnt_namespace *ns); | 29 | extern 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 | ||
14 | struct 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 | |||
21 | struct writeback_control; | 14 | struct writeback_control; |
22 | 15 | ||
23 | struct bio *mpage_bio_submit(int rw, struct bio *bio); | ||
24 | int mpage_readpages(struct address_space *mapping, struct list_head *pages, | 16 | int 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); |
26 | int mpage_readpage(struct page *page, get_block_t get_block); | 18 | int mpage_readpage(struct page *page, get_block_t get_block); |
27 | int __mpage_writepage(struct page *page, struct writeback_control *wbc, | ||
28 | void *data); | ||
29 | int mpage_writepages(struct address_space *mapping, | 19 | int 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); |
31 | int mpage_writepage(struct page *page, get_block_t *get_block, | 21 | int 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; | |||
8 | struct uts_namespace; | 8 | struct uts_namespace; |
9 | struct ipc_namespace; | 9 | struct ipc_namespace; |
10 | struct pid_namespace; | 10 | struct pid_namespace; |
11 | struct 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; | |||
97 | struct robust_list_head; | 97 | struct robust_list_head; |
98 | struct bio; | 98 | struct bio; |
99 | struct bts_tracer; | 99 | struct bts_tracer; |
100 | struct 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 | ||
23 | static void default_handler(int, struct pt_regs *); | 24 | static 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(¤t->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); | |||
420 | void daemonize(const char *name, ...) | 421 | void 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(¤t->files->count); | 459 | atomic_inc(¤t->files->count); |
@@ -556,30 +552,6 @@ void exit_files(struct task_struct *tsk) | |||
556 | } | 552 | } |
557 | } | 553 | } |
558 | 554 | ||
559 | void 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 | |||
569 | void 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 | |||
581 | EXPORT_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 | ||
684 | static 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 | |||
702 | struct fs_struct *copy_fs_struct(struct fs_struct *old) | ||
703 | { | ||
704 | return __copy_fs_struct(old); | ||
705 | } | ||
706 | |||
707 | EXPORT_SYMBOL_GPL(copy_fs_struct); | ||
708 | |||
709 | static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) | 685 | static 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(¤t->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 | ||
1706 | bad_unshare_cleanup_fs: | 1699 | bad_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 | ||
1710 | bad_unshare_cleanup_thread: | 1703 | bad_unshare_cleanup_thread: |
1711 | bad_unshare_out: | 1704 | bad_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 | ||