diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-03 00:09:10 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-03 00:09:10 -0400 |
| commit | 8fe74cf053de7ad2124a894996f84fa890a81093 (patch) | |
| tree | 77dcd8fbf33ce53a3821942233962fb28c6f2848 /kernel | |
| parent | c2eb2fa6d2b6fe122d3479ec5b28d978418b2698 (diff) | |
| parent | ced117c73edc917e96dea7cca98c91383f0792f7 (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()
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/auditsc.c | 1 | ||||
| -rw-r--r-- | kernel/exec_domain.c | 23 | ||||
| -rw-r--r-- | kernel/exit.c | 32 | ||||
| -rw-r--r-- | kernel/fork.c | 63 | ||||
| -rw-r--r-- | kernel/sys.c | 1 |
5 files changed, 33 insertions, 87 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 8cbddff6c28..2bfc6478676 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 667c841c295..c35452cadde 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 3bec141c82f..6686ed1e4aa 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 f7445823144..660c2b8765b 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 742cefa527e..51dbb55604e 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> |
