From 02cda956de0b28eeb2f65185e9800191fced01c4 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 29 Dec 2003 05:41:18 -0800 Subject: [PATCH] unshare_files From: Chris Wright Introduce unshare_files as a helper for use during execve to eliminate potential leak of the execve'd binary's fd. --- include/linux/fs.h | 3 +++ kernel/fork.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/linux/fs.h b/include/linux/fs.h index b3a714c094d2..dbe66b285870 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1408,5 +1408,8 @@ static inline ino_t parent_ino(struct dentry *dentry) return res; } +/* kernel/fork.c */ +extern int unshare_files(void); + #endif /* __KERNEL__ */ #endif /* _LINUX_FS_H */ 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; -- cgit v1.2.3