diff options
| author | Andrew Morton <akpm@osdl.org> | 2003-12-29 05:41:18 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-12-29 05:41:18 -0800 |
| commit | 02cda956de0b28eeb2f65185e9800191fced01c4 (patch) | |
| tree | 9f5c4870dca18805635ffde9d7d9948ad232480a /kernel/fork.c | |
| parent | 3a8d53478ed24a2d2df794986f7f1aab8e6c36b7 (diff) | |
[PATCH] unshare_files
From: Chris Wright <chrisw@osdl.org>
Introduce unshare_files as a helper for use during execve to eliminate
potential leak of the execve'd binary's fd.
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 381b80b510ba..0603f230146b 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -642,6 +642,11 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) goto out; } + /* + * Note: we may be using current for both targets (See exec.c) + * This works because we cache current->files (old) as oldf. Don't + * break this. + */ tsk->files = NULL; error = -ENOMEM; newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL); @@ -731,6 +736,35 @@ out_release: goto out; } +/* + * Helper to unshare the files of the current task. + * We don't want to expose copy_files internals to + * the exec layer of the kernel. + */ + +int unshare_files(void) +{ + struct files_struct *files = current->files; + int rc; + + if(!files) + BUG(); + + /* This can race but the race causes us to copy when we don't + need to and drop the copy */ + if(atomic_read(&files->count) == 1) + { + atomic_inc(&files->count); + return 0; + } + rc = copy_files(0, current); + if(rc) + current->files = files; + return rc; +} + +EXPORT_SYMBOL(unshare_files); + static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk) { struct sighand_struct *sig; |
