aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-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
5 files changed, 33 insertions, 87 deletions
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>