mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 04:30:52 +07:00
[PATCH] sanitize unshare_files/reset_files_struct
* let unshare_files() give caller the displaced files_struct * don't bother with grabbing reference only to drop it in the caller if it hadn't been shared in the first place * in that form unshare_files() is trivially implemented via unshare_fd(), so we eliminate the duplicate logics in fork.c * reset_files_struct() is not just only called for current; it will break the system if somebody ever calls it for anything else (we can't modify ->files of somebody else). Lose the task_struct * argument. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
fd8328be87
commit
3b1253880b
18
fs/exec.c
18
fs/exec.c
@ -1269,19 +1269,13 @@ int do_execve(char * filename,
|
|||||||
struct linux_binprm *bprm;
|
struct linux_binprm *bprm;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
unsigned long env_p;
|
unsigned long env_p;
|
||||||
struct files_struct *files;
|
struct files_struct *displaced;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
files = current->files;
|
retval = unshare_files(&displaced);
|
||||||
retval = unshare_files();
|
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out_ret;
|
goto out_ret;
|
||||||
|
|
||||||
if (files == current->files) {
|
|
||||||
put_files_struct(files);
|
|
||||||
files = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
|
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
|
||||||
if (!bprm)
|
if (!bprm)
|
||||||
@ -1340,8 +1334,8 @@ int do_execve(char * filename,
|
|||||||
security_bprm_free(bprm);
|
security_bprm_free(bprm);
|
||||||
acct_update_integrals(current);
|
acct_update_integrals(current);
|
||||||
kfree(bprm);
|
kfree(bprm);
|
||||||
if (files)
|
if (displaced)
|
||||||
put_files_struct(files);
|
put_files_struct(displaced);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1363,8 +1357,8 @@ int do_execve(char * filename,
|
|||||||
kfree(bprm);
|
kfree(bprm);
|
||||||
|
|
||||||
out_files:
|
out_files:
|
||||||
if (files)
|
if (displaced)
|
||||||
reset_files_struct(current, files);
|
reset_files_struct(displaced);
|
||||||
out_ret:
|
out_ret:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,8 @@ struct task_struct;
|
|||||||
|
|
||||||
struct files_struct *get_files_struct(struct task_struct *);
|
struct files_struct *get_files_struct(struct task_struct *);
|
||||||
void put_files_struct(struct files_struct *fs);
|
void put_files_struct(struct files_struct *fs);
|
||||||
void reset_files_struct(struct task_struct *, struct files_struct *);
|
void reset_files_struct(struct files_struct *);
|
||||||
|
int unshare_files(struct files_struct **);
|
||||||
|
|
||||||
extern struct kmem_cache *files_cachep;
|
extern struct kmem_cache *files_cachep;
|
||||||
|
|
||||||
|
@ -2033,9 +2033,6 @@ static inline ino_t parent_ino(struct dentry *dentry)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* kernel/fork.c */
|
|
||||||
extern int unshare_files(void);
|
|
||||||
|
|
||||||
/* Transaction based IO helpers */
|
/* Transaction based IO helpers */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -507,8 +507,9 @@ void put_files_struct(struct files_struct *files)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
|
void reset_files_struct(struct files_struct *files)
|
||||||
{
|
{
|
||||||
|
struct task_struct *tsk = current;
|
||||||
struct files_struct *old;
|
struct files_struct *old;
|
||||||
|
|
||||||
old = tsk->files;
|
old = tsk->files;
|
||||||
|
@ -840,36 +840,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
struct files_struct *newf;
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
BUG_ON(!files);
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
newf = dup_fd(files, &error);
|
|
||||||
if (newf) {
|
|
||||||
task_lock(current);
|
|
||||||
current->files = newf;
|
|
||||||
task_unlock(current);
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
|
static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
|
||||||
{
|
{
|
||||||
struct sighand_struct *sig;
|
struct sighand_struct *sig;
|
||||||
@ -1807,3 +1777,27 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|||||||
bad_unshare_out:
|
bad_unshare_out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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(struct files_struct **displaced)
|
||||||
|
{
|
||||||
|
struct task_struct *task = current;
|
||||||
|
struct files_struct *copy;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = unshare_fd(CLONE_FILES, ©);
|
||||||
|
if (error || !copy) {
|
||||||
|
*displaced = NULL;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
*displaced = task->files;
|
||||||
|
task_lock(task);
|
||||||
|
task->files = copy;
|
||||||
|
task_unlock(task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user