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 585d3bc06f
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()
This commit is contained in:
Коммит
8fe74cf053
|
@ -19,7 +19,6 @@
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/fs_struct.h>
|
|
||||||
#include <linux/init_task.h>
|
#include <linux/init_task.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
|
|
@ -635,7 +635,7 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
|
||||||
if (dentry->d_inode)
|
if (dentry->d_inode)
|
||||||
goto out_dput;
|
goto out_dput;
|
||||||
|
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
|
|
||||||
if (flags & SPU_CREATE_GANG)
|
if (flags & SPU_CREATE_GANG)
|
||||||
ret = spufs_create_gang(nd->path.dentry->d_inode,
|
ret = spufs_create_gang(nd->path.dentry->d_inode,
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
#include <linux/file.h>
|
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
|
|
||||||
struct tty_audit_buf {
|
struct tty_audit_buf {
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/devpts_fs.h>
|
#include <linux/devpts_fs.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
|
|
|
@ -11,7 +11,7 @@ obj-y := open.o read_write.o file_table.o super.o \
|
||||||
attr.o bad_inode.o file.o filesystems.o namespace.o \
|
attr.o bad_inode.o file.o filesystems.o namespace.o \
|
||||||
seq_file.o xattr.o libfs.o fs-writeback.o \
|
seq_file.o xattr.o libfs.o fs-writeback.o \
|
||||||
pnode.o drop_caches.o splice.o sync.o utimes.o \
|
pnode.o drop_caches.o splice.o sync.o utimes.o \
|
||||||
stack.o
|
stack.o fs_struct.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_BLOCK),y)
|
ifeq ($(CONFIG_BLOCK),y)
|
||||||
obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
|
obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/stat.h>
|
|
||||||
#include <linux/time.h>
|
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/mman.h>
|
#include <linux/mman.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
@ -21,20 +19,15 @@
|
||||||
#include <linux/binfmts.h>
|
#include <linux/binfmts.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fcntl.h>
|
|
||||||
#include <linux/ptrace.h>
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/shm.h>
|
|
||||||
#include <linux/personality.h>
|
#include <linux/personality.h>
|
||||||
#include <linux/elfcore.h>
|
#include <linux/elfcore.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/highuid.h>
|
#include <linux/highuid.h>
|
||||||
#include <linux/smp.h>
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/syscalls.h>
|
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
#include <linux/utsname.h>
|
#include <linux/utsname.h>
|
||||||
|
@ -576,7 +569,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||||
unsigned long error;
|
unsigned long error;
|
||||||
struct elf_phdr *elf_ppnt, *elf_phdata;
|
struct elf_phdr *elf_ppnt, *elf_phdata;
|
||||||
unsigned long elf_bss, elf_brk;
|
unsigned long elf_bss, elf_brk;
|
||||||
int elf_exec_fileno;
|
|
||||||
int retval, i;
|
int retval, i;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
unsigned long elf_entry;
|
unsigned long elf_entry;
|
||||||
|
@ -631,12 +623,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||||
goto out_free_ph;
|
goto out_free_ph;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = get_unused_fd();
|
|
||||||
if (retval < 0)
|
|
||||||
goto out_free_ph;
|
|
||||||
get_file(bprm->file);
|
|
||||||
fd_install(elf_exec_fileno = retval, bprm->file);
|
|
||||||
|
|
||||||
elf_ppnt = elf_phdata;
|
elf_ppnt = elf_phdata;
|
||||||
elf_bss = 0;
|
elf_bss = 0;
|
||||||
elf_brk = 0;
|
elf_brk = 0;
|
||||||
|
@ -655,13 +641,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||||
retval = -ENOEXEC;
|
retval = -ENOEXEC;
|
||||||
if (elf_ppnt->p_filesz > PATH_MAX ||
|
if (elf_ppnt->p_filesz > PATH_MAX ||
|
||||||
elf_ppnt->p_filesz < 2)
|
elf_ppnt->p_filesz < 2)
|
||||||
goto out_free_file;
|
goto out_free_ph;
|
||||||
|
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
elf_interpreter = kmalloc(elf_ppnt->p_filesz,
|
elf_interpreter = kmalloc(elf_ppnt->p_filesz,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!elf_interpreter)
|
if (!elf_interpreter)
|
||||||
goto out_free_file;
|
goto out_free_ph;
|
||||||
|
|
||||||
retval = kernel_read(bprm->file, elf_ppnt->p_offset,
|
retval = kernel_read(bprm->file, elf_ppnt->p_offset,
|
||||||
elf_interpreter,
|
elf_interpreter,
|
||||||
|
@ -956,8 +942,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||||
|
|
||||||
kfree(elf_phdata);
|
kfree(elf_phdata);
|
||||||
|
|
||||||
sys_close(elf_exec_fileno);
|
|
||||||
|
|
||||||
set_binfmt(&elf_format);
|
set_binfmt(&elf_format);
|
||||||
|
|
||||||
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
||||||
|
@ -1028,8 +1012,6 @@ out_free_dentry:
|
||||||
fput(interpreter);
|
fput(interpreter);
|
||||||
out_free_interp:
|
out_free_interp:
|
||||||
kfree(elf_interpreter);
|
kfree(elf_interpreter);
|
||||||
out_free_file:
|
|
||||||
sys_close(elf_exec_fileno);
|
|
||||||
out_free_ph:
|
out_free_ph:
|
||||||
kfree(elf_phdata);
|
kfree(elf_phdata);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -188,7 +188,6 @@ out:
|
||||||
static int
|
static int
|
||||||
load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
||||||
{
|
{
|
||||||
int som_exec_fileno;
|
|
||||||
int retval;
|
int retval;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
unsigned long som_entry;
|
unsigned long som_entry;
|
||||||
|
@ -220,12 +219,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = get_unused_fd();
|
|
||||||
if (retval < 0)
|
|
||||||
goto out_free;
|
|
||||||
get_file(bprm->file);
|
|
||||||
fd_install(som_exec_fileno = retval, bprm->file);
|
|
||||||
|
|
||||||
/* Flush all traces of the currently running executable */
|
/* Flush all traces of the currently running executable */
|
||||||
retval = flush_old_exec(bprm);
|
retval = flush_old_exec(bprm);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
|
|
@ -204,6 +204,7 @@ int fsync_bdev(struct block_device *bdev)
|
||||||
}
|
}
|
||||||
return sync_blockdev(bdev);
|
return sync_blockdev(bdev);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(fsync_bdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* freeze_bdev -- lock a filesystem and force it into a consistent state
|
* freeze_bdev -- lock a filesystem and force it into a consistent state
|
||||||
|
|
|
@ -256,7 +256,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!acl)
|
if (!acl)
|
||||||
inode->i_mode &= ~current->fs->umask;
|
inode->i_mode &= ~current_umask();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_POSIXACL(dir) && acl) {
|
if (IS_POSIXACL(dir) && acl) {
|
||||||
|
|
|
@ -267,7 +267,7 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name,
|
||||||
goto out_dput;
|
goto out_dput;
|
||||||
|
|
||||||
if (!IS_POSIXACL(parent->dentry->d_inode))
|
if (!IS_POSIXACL(parent->dentry->d_inode))
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
|
|
||||||
error = mnt_want_write(parent->mnt);
|
error = mnt_want_write(parent->mnt);
|
||||||
if (error)
|
if (error)
|
||||||
|
|
|
@ -3315,7 +3315,6 @@ EXPORT_SYMBOL(cont_write_begin);
|
||||||
EXPORT_SYMBOL(end_buffer_read_sync);
|
EXPORT_SYMBOL(end_buffer_read_sync);
|
||||||
EXPORT_SYMBOL(end_buffer_write_sync);
|
EXPORT_SYMBOL(end_buffer_write_sync);
|
||||||
EXPORT_SYMBOL(file_fsync);
|
EXPORT_SYMBOL(file_fsync);
|
||||||
EXPORT_SYMBOL(fsync_bdev);
|
|
||||||
EXPORT_SYMBOL(generic_block_bmap);
|
EXPORT_SYMBOL(generic_block_bmap);
|
||||||
EXPORT_SYMBOL(generic_cont_expand_simple);
|
EXPORT_SYMBOL(generic_cont_expand_simple);
|
||||||
EXPORT_SYMBOL(init_buffer);
|
EXPORT_SYMBOL(init_buffer);
|
||||||
|
|
|
@ -254,7 +254,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
if (oplockEnabled)
|
if (oplockEnabled)
|
||||||
oplock = REQ_OPLOCK;
|
oplock = REQ_OPLOCK;
|
||||||
|
|
||||||
|
@ -479,7 +479,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
else if (pTcon->unix_ext) {
|
else if (pTcon->unix_ext) {
|
||||||
struct cifs_unix_set_info_args args = {
|
struct cifs_unix_set_info_args args = {
|
||||||
.mode = mode & ~current->fs->umask,
|
.mode = mode & ~current_umask(),
|
||||||
.ctime = NO_CHANGE_64,
|
.ctime = NO_CHANGE_64,
|
||||||
.atime = NO_CHANGE_64,
|
.atime = NO_CHANGE_64,
|
||||||
.mtime = NO_CHANGE_64,
|
.mtime = NO_CHANGE_64,
|
||||||
|
|
|
@ -1125,7 +1125,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||||
goto mkdir_out;
|
goto mkdir_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
||||||
mode, NULL /* netfid */, pInfo, &oplock,
|
mode, NULL /* netfid */, pInfo, &oplock,
|
||||||
full_path, cifs_sb->local_nls,
|
full_path, cifs_sb->local_nls,
|
||||||
|
@ -1204,7 +1204,7 @@ mkdir_get_info:
|
||||||
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
||||||
direntry->d_inode->i_nlink = 2;
|
direntry->d_inode->i_nlink = 2;
|
||||||
|
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
/* must turn on setgid bit if parent dir has it */
|
/* must turn on setgid bit if parent dir has it */
|
||||||
if (inode->i_mode & S_ISGID)
|
if (inode->i_mode & S_ISGID)
|
||||||
mode |= S_ISGID;
|
mode |= S_ISGID;
|
||||||
|
|
16
fs/compat.c
16
fs/compat.c
|
@ -51,6 +51,7 @@
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/eventpoll.h>
|
#include <linux/eventpoll.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
@ -1502,12 +1503,15 @@ int compat_do_execve(char * filename,
|
||||||
bprm->cred = prepare_exec_creds();
|
bprm->cred = prepare_exec_creds();
|
||||||
if (!bprm->cred)
|
if (!bprm->cred)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
check_unsafe_exec(bprm);
|
|
||||||
|
retval = check_unsafe_exec(bprm);
|
||||||
|
if (retval)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
file = open_exec(filename);
|
file = open_exec(filename);
|
||||||
retval = PTR_ERR(file);
|
retval = PTR_ERR(file);
|
||||||
if (IS_ERR(file))
|
if (IS_ERR(file))
|
||||||
goto out_unlock;
|
goto out_unmark;
|
||||||
|
|
||||||
sched_exec();
|
sched_exec();
|
||||||
|
|
||||||
|
@ -1549,6 +1553,9 @@ int compat_do_execve(char * filename,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* execve succeeded */
|
/* execve succeeded */
|
||||||
|
write_lock(¤t->fs->lock);
|
||||||
|
current->fs->in_exec = 0;
|
||||||
|
write_unlock(¤t->fs->lock);
|
||||||
current->in_execve = 0;
|
current->in_execve = 0;
|
||||||
mutex_unlock(¤t->cred_exec_mutex);
|
mutex_unlock(¤t->cred_exec_mutex);
|
||||||
acct_update_integrals(current);
|
acct_update_integrals(current);
|
||||||
|
@ -1567,6 +1574,11 @@ out_file:
|
||||||
fput(bprm->file);
|
fput(bprm->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_unmark:
|
||||||
|
write_lock(¤t->fs->lock);
|
||||||
|
current->fs->in_exec = 0;
|
||||||
|
write_unlock(¤t->fs->lock);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
current->in_execve = 0;
|
current->in_execve = 0;
|
||||||
mutex_unlock(¤t->cred_exec_mutex);
|
mutex_unlock(¤t->cred_exec_mutex);
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/fsnotify.h>
|
#include <linux/fsnotify.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -32,6 +31,7 @@
|
||||||
#include <linux/seqlock.h>
|
#include <linux/seqlock.h>
|
||||||
#include <linux/swap.h>
|
#include <linux/swap.h>
|
||||||
#include <linux/bootmem.h>
|
#include <linux/bootmem.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
int sysctl_vfs_cache_pressure __read_mostly = 100;
|
int sysctl_vfs_cache_pressure __read_mostly = 100;
|
||||||
|
|
35
fs/exec.c
35
fs/exec.c
|
@ -53,6 +53,7 @@
|
||||||
#include <linux/tracehook.h>
|
#include <linux/tracehook.h>
|
||||||
#include <linux/kmod.h>
|
#include <linux/kmod.h>
|
||||||
#include <linux/fsnotify.h>
|
#include <linux/fsnotify.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
@ -1056,28 +1057,35 @@ EXPORT_SYMBOL(install_exec_creds);
|
||||||
* - the caller must hold current->cred_exec_mutex to protect against
|
* - the caller must hold current->cred_exec_mutex to protect against
|
||||||
* PTRACE_ATTACH
|
* PTRACE_ATTACH
|
||||||
*/
|
*/
|
||||||
void check_unsafe_exec(struct linux_binprm *bprm)
|
int check_unsafe_exec(struct linux_binprm *bprm)
|
||||||
{
|
{
|
||||||
struct task_struct *p = current, *t;
|
struct task_struct *p = current, *t;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned n_fs, n_sighand;
|
unsigned n_fs;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
bprm->unsafe = tracehook_unsafe_exec(p);
|
bprm->unsafe = tracehook_unsafe_exec(p);
|
||||||
|
|
||||||
n_fs = 1;
|
n_fs = 1;
|
||||||
n_sighand = 1;
|
write_lock(&p->fs->lock);
|
||||||
lock_task_sighand(p, &flags);
|
lock_task_sighand(p, &flags);
|
||||||
for (t = next_thread(p); t != p; t = next_thread(t)) {
|
for (t = next_thread(p); t != p; t = next_thread(t)) {
|
||||||
if (t->fs == p->fs)
|
if (t->fs == p->fs)
|
||||||
n_fs++;
|
n_fs++;
|
||||||
n_sighand++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&p->fs->count) > n_fs ||
|
if (p->fs->users > n_fs) {
|
||||||
atomic_read(&p->sighand->count) > n_sighand)
|
|
||||||
bprm->unsafe |= LSM_UNSAFE_SHARE;
|
bprm->unsafe |= LSM_UNSAFE_SHARE;
|
||||||
|
} else {
|
||||||
|
if (p->fs->in_exec)
|
||||||
|
res = -EAGAIN;
|
||||||
|
p->fs->in_exec = 1;
|
||||||
|
}
|
||||||
|
|
||||||
unlock_task_sighand(p, &flags);
|
unlock_task_sighand(p, &flags);
|
||||||
|
write_unlock(&p->fs->lock);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1296,12 +1304,15 @@ int do_execve(char * filename,
|
||||||
bprm->cred = prepare_exec_creds();
|
bprm->cred = prepare_exec_creds();
|
||||||
if (!bprm->cred)
|
if (!bprm->cred)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
check_unsafe_exec(bprm);
|
|
||||||
|
retval = check_unsafe_exec(bprm);
|
||||||
|
if (retval)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
file = open_exec(filename);
|
file = open_exec(filename);
|
||||||
retval = PTR_ERR(file);
|
retval = PTR_ERR(file);
|
||||||
if (IS_ERR(file))
|
if (IS_ERR(file))
|
||||||
goto out_unlock;
|
goto out_unmark;
|
||||||
|
|
||||||
sched_exec();
|
sched_exec();
|
||||||
|
|
||||||
|
@ -1344,6 +1355,9 @@ int do_execve(char * filename,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* execve succeeded */
|
/* execve succeeded */
|
||||||
|
write_lock(¤t->fs->lock);
|
||||||
|
current->fs->in_exec = 0;
|
||||||
|
write_unlock(¤t->fs->lock);
|
||||||
current->in_execve = 0;
|
current->in_execve = 0;
|
||||||
mutex_unlock(¤t->cred_exec_mutex);
|
mutex_unlock(¤t->cred_exec_mutex);
|
||||||
acct_update_integrals(current);
|
acct_update_integrals(current);
|
||||||
|
@ -1362,6 +1376,11 @@ out_file:
|
||||||
fput(bprm->file);
|
fput(bprm->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_unmark:
|
||||||
|
write_lock(¤t->fs->lock);
|
||||||
|
current->fs->in_exec = 0;
|
||||||
|
write_unlock(¤t->fs->lock);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
current->in_execve = 0;
|
current->in_execve = 0;
|
||||||
mutex_unlock(¤t->cred_exec_mutex);
|
mutex_unlock(¤t->cred_exec_mutex);
|
||||||
|
|
|
@ -318,7 +318,7 @@ ext2_init_acl(struct inode *inode, struct inode *dir)
|
||||||
return PTR_ERR(acl);
|
return PTR_ERR(acl);
|
||||||
}
|
}
|
||||||
if (!acl)
|
if (!acl)
|
||||||
inode->i_mode &= ~current->fs->umask;
|
inode->i_mode &= ~current_umask();
|
||||||
}
|
}
|
||||||
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
|
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
|
||||||
struct posix_acl *clone;
|
struct posix_acl *clone;
|
||||||
|
|
|
@ -323,7 +323,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
|
||||||
return PTR_ERR(acl);
|
return PTR_ERR(acl);
|
||||||
}
|
}
|
||||||
if (!acl)
|
if (!acl)
|
||||||
inode->i_mode &= ~current->fs->umask;
|
inode->i_mode &= ~current_umask();
|
||||||
}
|
}
|
||||||
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
|
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
|
||||||
struct posix_acl *clone;
|
struct posix_acl *clone;
|
||||||
|
|
|
@ -323,7 +323,7 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
|
||||||
return PTR_ERR(acl);
|
return PTR_ERR(acl);
|
||||||
}
|
}
|
||||||
if (!acl)
|
if (!acl)
|
||||||
inode->i_mode &= ~current->fs->umask;
|
inode->i_mode &= ~current_umask();
|
||||||
}
|
}
|
||||||
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
|
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
|
||||||
struct posix_acl *clone;
|
struct posix_acl *clone;
|
||||||
|
|
|
@ -934,7 +934,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
|
||||||
|
|
||||||
opts->fs_uid = current_uid();
|
opts->fs_uid = current_uid();
|
||||||
opts->fs_gid = current_gid();
|
opts->fs_gid = current_gid();
|
||||||
opts->fs_fmask = opts->fs_dmask = current->fs->umask;
|
opts->fs_fmask = current_umask();
|
||||||
opts->allow_utime = -1;
|
opts->allow_utime = -1;
|
||||||
opts->codepage = fat_default_codepage;
|
opts->codepage = fat_default_codepage;
|
||||||
opts->iocharset = fat_default_iocharset;
|
opts->iocharset = fat_default_iocharset;
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/path.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
|
||||||
|
* It can block.
|
||||||
|
*/
|
||||||
|
void set_fs_root(struct fs_struct *fs, struct path *path)
|
||||||
|
{
|
||||||
|
struct path old_root;
|
||||||
|
|
||||||
|
write_lock(&fs->lock);
|
||||||
|
old_root = fs->root;
|
||||||
|
fs->root = *path;
|
||||||
|
path_get(path);
|
||||||
|
write_unlock(&fs->lock);
|
||||||
|
if (old_root.dentry)
|
||||||
|
path_put(&old_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
|
||||||
|
* It can block.
|
||||||
|
*/
|
||||||
|
void set_fs_pwd(struct fs_struct *fs, struct path *path)
|
||||||
|
{
|
||||||
|
struct path old_pwd;
|
||||||
|
|
||||||
|
write_lock(&fs->lock);
|
||||||
|
old_pwd = fs->pwd;
|
||||||
|
fs->pwd = *path;
|
||||||
|
path_get(path);
|
||||||
|
write_unlock(&fs->lock);
|
||||||
|
|
||||||
|
if (old_pwd.dentry)
|
||||||
|
path_put(&old_pwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void chroot_fs_refs(struct path *old_root, struct path *new_root)
|
||||||
|
{
|
||||||
|
struct task_struct *g, *p;
|
||||||
|
struct fs_struct *fs;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
read_lock(&tasklist_lock);
|
||||||
|
do_each_thread(g, p) {
|
||||||
|
task_lock(p);
|
||||||
|
fs = p->fs;
|
||||||
|
if (fs) {
|
||||||
|
write_lock(&fs->lock);
|
||||||
|
if (fs->root.dentry == old_root->dentry
|
||||||
|
&& fs->root.mnt == old_root->mnt) {
|
||||||
|
path_get(new_root);
|
||||||
|
fs->root = *new_root;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (fs->pwd.dentry == old_root->dentry
|
||||||
|
&& fs->pwd.mnt == old_root->mnt) {
|
||||||
|
path_get(new_root);
|
||||||
|
fs->pwd = *new_root;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
write_unlock(&fs->lock);
|
||||||
|
}
|
||||||
|
task_unlock(p);
|
||||||
|
} while_each_thread(g, p);
|
||||||
|
read_unlock(&tasklist_lock);
|
||||||
|
while (count--)
|
||||||
|
path_put(old_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_fs_struct(struct fs_struct *fs)
|
||||||
|
{
|
||||||
|
path_put(&fs->root);
|
||||||
|
path_put(&fs->pwd);
|
||||||
|
kmem_cache_free(fs_cachep, fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit_fs(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
struct fs_struct *fs = tsk->fs;
|
||||||
|
|
||||||
|
if (fs) {
|
||||||
|
int kill;
|
||||||
|
task_lock(tsk);
|
||||||
|
write_lock(&fs->lock);
|
||||||
|
tsk->fs = NULL;
|
||||||
|
kill = !--fs->users;
|
||||||
|
write_unlock(&fs->lock);
|
||||||
|
task_unlock(tsk);
|
||||||
|
if (kill)
|
||||||
|
free_fs_struct(fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_struct *copy_fs_struct(struct fs_struct *old)
|
||||||
|
{
|
||||||
|
struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
|
||||||
|
/* We don't need to lock fs - think why ;-) */
|
||||||
|
if (fs) {
|
||||||
|
fs->users = 1;
|
||||||
|
fs->in_exec = 0;
|
||||||
|
rwlock_init(&fs->lock);
|
||||||
|
fs->umask = old->umask;
|
||||||
|
read_lock(&old->lock);
|
||||||
|
fs->root = old->root;
|
||||||
|
path_get(&old->root);
|
||||||
|
fs->pwd = old->pwd;
|
||||||
|
path_get(&old->pwd);
|
||||||
|
read_unlock(&old->lock);
|
||||||
|
}
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unshare_fs_struct(void)
|
||||||
|
{
|
||||||
|
struct fs_struct *fs = current->fs;
|
||||||
|
struct fs_struct *new_fs = copy_fs_struct(fs);
|
||||||
|
int kill;
|
||||||
|
|
||||||
|
if (!new_fs)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
task_lock(current);
|
||||||
|
write_lock(&fs->lock);
|
||||||
|
kill = !--fs->users;
|
||||||
|
current->fs = new_fs;
|
||||||
|
write_unlock(&fs->lock);
|
||||||
|
task_unlock(current);
|
||||||
|
|
||||||
|
if (kill)
|
||||||
|
free_fs_struct(fs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(unshare_fs_struct);
|
||||||
|
|
||||||
|
int current_umask(void)
|
||||||
|
{
|
||||||
|
return current->fs->umask;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(current_umask);
|
||||||
|
|
||||||
|
/* to be mentioned only in INIT_TASK */
|
||||||
|
struct fs_struct init_fs = {
|
||||||
|
.users = 1,
|
||||||
|
.lock = __RW_LOCK_UNLOCKED(init_fs.lock),
|
||||||
|
.umask = 0022,
|
||||||
|
};
|
||||||
|
|
||||||
|
void daemonize_fs_struct(void)
|
||||||
|
{
|
||||||
|
struct fs_struct *fs = current->fs;
|
||||||
|
|
||||||
|
if (fs) {
|
||||||
|
int kill;
|
||||||
|
|
||||||
|
task_lock(current);
|
||||||
|
|
||||||
|
write_lock(&init_fs.lock);
|
||||||
|
init_fs.users++;
|
||||||
|
write_unlock(&init_fs.lock);
|
||||||
|
|
||||||
|
write_lock(&fs->lock);
|
||||||
|
current->fs = &init_fs;
|
||||||
|
kill = !--fs->users;
|
||||||
|
write_unlock(&fs->lock);
|
||||||
|
|
||||||
|
task_unlock(current);
|
||||||
|
if (kill)
|
||||||
|
free_fs_struct(fs);
|
||||||
|
}
|
||||||
|
}
|
|
@ -134,7 +134,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
|
||||||
mode_t mode = inode->i_mode;
|
mode_t mode = inode->i_mode;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
inode->i_mode = mode & ~current->fs->umask;
|
inode->i_mode = mode & ~current_umask();
|
||||||
if (!S_ISLNK(inode->i_mode))
|
if (!S_ISLNK(inode->i_mode))
|
||||||
acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
|
acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
|
||||||
if (acl) {
|
if (acl) {
|
||||||
|
|
|
@ -215,7 +215,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
if (!acl) {
|
if (!acl) {
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
if (mode != ip->i_inode.i_mode)
|
if (mode != ip->i_inode.i_mode)
|
||||||
error = munge_mode(ip, mode);
|
error = munge_mode(ip, mode);
|
||||||
return error;
|
return error;
|
||||||
|
|
|
@ -48,7 +48,7 @@ void hfsplus_fill_defaults(struct hfsplus_sb_info *opts)
|
||||||
|
|
||||||
opts->creator = HFSPLUS_DEF_CR_TYPE;
|
opts->creator = HFSPLUS_DEF_CR_TYPE;
|
||||||
opts->type = HFSPLUS_DEF_CR_TYPE;
|
opts->type = HFSPLUS_DEF_CR_TYPE;
|
||||||
opts->umask = current->fs->umask;
|
opts->umask = current_umask();
|
||||||
opts->uid = current_uid();
|
opts->uid = current_uid();
|
||||||
opts->gid = current_gid();
|
opts->gid = current_gid();
|
||||||
opts->part = -1;
|
opts->part = -1;
|
||||||
|
|
|
@ -480,7 +480,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||||
|
|
||||||
uid = current_uid();
|
uid = current_uid();
|
||||||
gid = current_gid();
|
gid = current_gid();
|
||||||
umask = current->fs->umask;
|
umask = current_umask();
|
||||||
lowercase = 0;
|
lowercase = 0;
|
||||||
conv = CONV_BINARY;
|
conv = CONV_BINARY;
|
||||||
eas = 2;
|
eas = 2;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
struct super_block;
|
struct super_block;
|
||||||
struct linux_binprm;
|
struct linux_binprm;
|
||||||
|
struct path;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* block_dev.c
|
* block_dev.c
|
||||||
|
@ -43,7 +44,7 @@ extern void __init chrdev_init(void);
|
||||||
/*
|
/*
|
||||||
* exec.c
|
* exec.c
|
||||||
*/
|
*/
|
||||||
extern void check_unsafe_exec(struct linux_binprm *);
|
extern int check_unsafe_exec(struct linux_binprm *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* namespace.c
|
* namespace.c
|
||||||
|
@ -60,3 +61,8 @@ extern void umount_tree(struct vfsmount *, int, struct list_head *);
|
||||||
extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
|
extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
|
||||||
|
|
||||||
extern void __init mnt_init(void);
|
extern void __init mnt_init(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fs_struct.c
|
||||||
|
*/
|
||||||
|
extern void chroot_fs_refs(struct path *, struct path *);
|
||||||
|
|
|
@ -336,7 +336,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
|
||||||
return PTR_ERR(acl);
|
return PTR_ERR(acl);
|
||||||
|
|
||||||
if (!acl) {
|
if (!acl) {
|
||||||
*i_mode &= ~current->fs->umask;
|
*i_mode &= ~current_umask();
|
||||||
} else {
|
} else {
|
||||||
if (S_ISDIR(*i_mode))
|
if (S_ISDIR(*i_mode))
|
||||||
jffs2_iset_acl(inode, &f->i_acl_default, acl);
|
jffs2_iset_acl(inode, &f->i_acl_default, acl);
|
||||||
|
|
|
@ -182,7 +182,7 @@ int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
|
||||||
cleanup:
|
cleanup:
|
||||||
posix_acl_release(acl);
|
posix_acl_release(acl);
|
||||||
} else
|
} else
|
||||||
inode->i_mode &= ~current->fs->umask;
|
inode->i_mode &= ~current_umask();
|
||||||
|
|
||||||
JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
|
JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
|
||||||
inode->i_mode;
|
inode->i_mode;
|
||||||
|
|
13
fs/mpage.c
13
fs/mpage.c
|
@ -82,7 +82,7 @@ static void mpage_end_io_write(struct bio *bio, int err)
|
||||||
bio_put(bio);
|
bio_put(bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bio *mpage_bio_submit(int rw, struct bio *bio)
|
static struct bio *mpage_bio_submit(int rw, struct bio *bio)
|
||||||
{
|
{
|
||||||
bio->bi_end_io = mpage_end_io_read;
|
bio->bi_end_io = mpage_end_io_read;
|
||||||
if (rw == WRITE)
|
if (rw == WRITE)
|
||||||
|
@ -90,7 +90,6 @@ struct bio *mpage_bio_submit(int rw, struct bio *bio)
|
||||||
submit_bio(rw, bio);
|
submit_bio(rw, bio);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mpage_bio_submit);
|
|
||||||
|
|
||||||
static struct bio *
|
static struct bio *
|
||||||
mpage_alloc(struct block_device *bdev,
|
mpage_alloc(struct block_device *bdev,
|
||||||
|
@ -439,7 +438,14 @@ EXPORT_SYMBOL(mpage_readpage);
|
||||||
* just allocate full-size (16-page) BIOs.
|
* just allocate full-size (16-page) BIOs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int __mpage_writepage(struct page *page, struct writeback_control *wbc,
|
struct mpage_data {
|
||||||
|
struct bio *bio;
|
||||||
|
sector_t last_block_in_bio;
|
||||||
|
get_block_t *get_block;
|
||||||
|
unsigned use_writepage;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct mpage_data *mpd = data;
|
struct mpage_data *mpd = data;
|
||||||
|
@ -648,7 +654,6 @@ out:
|
||||||
mpd->bio = bio;
|
mpd->bio = bio;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__mpage_writepage);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them
|
* mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them
|
||||||
|
|
14
fs/namei.c
14
fs/namei.c
|
@ -32,6 +32,7 @@
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fcntl.h>
|
#include <linux/fcntl.h>
|
||||||
#include <linux/device_cgroup.h>
|
#include <linux/device_cgroup.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
|
#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
|
||||||
|
@ -1578,7 +1579,7 @@ static int __open_namei_create(struct nameidata *nd, struct path *path,
|
||||||
struct dentry *dir = nd->path.dentry;
|
struct dentry *dir = nd->path.dentry;
|
||||||
|
|
||||||
if (!IS_POSIXACL(dir->d_inode))
|
if (!IS_POSIXACL(dir->d_inode))
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
error = security_path_mknod(&nd->path, path->dentry, mode, 0);
|
error = security_path_mknod(&nd->path, path->dentry, mode, 0);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -1989,7 +1990,7 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode,
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
if (!IS_POSIXACL(nd.path.dentry->d_inode))
|
if (!IS_POSIXACL(nd.path.dentry->d_inode))
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
error = may_mknod(mode);
|
error = may_mknod(mode);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_dput;
|
goto out_dput;
|
||||||
|
@ -2067,7 +2068,7 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (!IS_POSIXACL(nd.path.dentry->d_inode))
|
if (!IS_POSIXACL(nd.path.dentry->d_inode))
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
error = mnt_want_write(nd.path.mnt);
|
error = mnt_want_write(nd.path.mnt);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_dput;
|
goto out_dput;
|
||||||
|
@ -2897,10 +2898,3 @@ EXPORT_SYMBOL(vfs_symlink);
|
||||||
EXPORT_SYMBOL(vfs_unlink);
|
EXPORT_SYMBOL(vfs_unlink);
|
||||||
EXPORT_SYMBOL(dentry_unhash);
|
EXPORT_SYMBOL(dentry_unhash);
|
||||||
EXPORT_SYMBOL(generic_readlink);
|
EXPORT_SYMBOL(generic_readlink);
|
||||||
|
|
||||||
/* to be mentioned only in INIT_TASK */
|
|
||||||
struct fs_struct init_fs = {
|
|
||||||
.count = ATOMIC_INIT(1),
|
|
||||||
.lock = __RW_LOCK_UNLOCKED(init_fs.lock),
|
|
||||||
.umask = 0022,
|
|
||||||
};
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/ramfs.h>
|
#include <linux/ramfs.h>
|
||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
#include <linux/idr.h>
|
#include <linux/idr.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
#include "pnode.h"
|
#include "pnode.h"
|
||||||
|
@ -2092,66 +2093,6 @@ out1:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
|
|
||||||
* It can block. Requires the big lock held.
|
|
||||||
*/
|
|
||||||
void set_fs_root(struct fs_struct *fs, struct path *path)
|
|
||||||
{
|
|
||||||
struct path old_root;
|
|
||||||
|
|
||||||
write_lock(&fs->lock);
|
|
||||||
old_root = fs->root;
|
|
||||||
fs->root = *path;
|
|
||||||
path_get(path);
|
|
||||||
write_unlock(&fs->lock);
|
|
||||||
if (old_root.dentry)
|
|
||||||
path_put(&old_root);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
|
|
||||||
* It can block. Requires the big lock held.
|
|
||||||
*/
|
|
||||||
void set_fs_pwd(struct fs_struct *fs, struct path *path)
|
|
||||||
{
|
|
||||||
struct path old_pwd;
|
|
||||||
|
|
||||||
write_lock(&fs->lock);
|
|
||||||
old_pwd = fs->pwd;
|
|
||||||
fs->pwd = *path;
|
|
||||||
path_get(path);
|
|
||||||
write_unlock(&fs->lock);
|
|
||||||
|
|
||||||
if (old_pwd.dentry)
|
|
||||||
path_put(&old_pwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void chroot_fs_refs(struct path *old_root, struct path *new_root)
|
|
||||||
{
|
|
||||||
struct task_struct *g, *p;
|
|
||||||
struct fs_struct *fs;
|
|
||||||
|
|
||||||
read_lock(&tasklist_lock);
|
|
||||||
do_each_thread(g, p) {
|
|
||||||
task_lock(p);
|
|
||||||
fs = p->fs;
|
|
||||||
if (fs) {
|
|
||||||
atomic_inc(&fs->count);
|
|
||||||
task_unlock(p);
|
|
||||||
if (fs->root.dentry == old_root->dentry
|
|
||||||
&& fs->root.mnt == old_root->mnt)
|
|
||||||
set_fs_root(fs, new_root);
|
|
||||||
if (fs->pwd.dentry == old_root->dentry
|
|
||||||
&& fs->pwd.mnt == old_root->mnt)
|
|
||||||
set_fs_pwd(fs, new_root);
|
|
||||||
put_fs_struct(fs);
|
|
||||||
} else
|
|
||||||
task_unlock(p);
|
|
||||||
} while_each_thread(g, p);
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pivot_root Semantics:
|
* pivot_root Semantics:
|
||||||
* Moves the root file system of the current process to the directory put_old,
|
* Moves the root file system of the current process to the directory put_old,
|
||||||
|
|
|
@ -328,7 +328,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
||||||
data->arg.create.verifier[1] = current->pid;
|
data->arg.create.verifier[1] = current->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
sattr->ia_mode &= ~current->fs->umask;
|
sattr->ia_mode &= ~current_umask();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
status = nfs3_do_create(dir, dentry, data);
|
status = nfs3_do_create(dir, dentry, data);
|
||||||
|
@ -528,7 +528,7 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
|
||||||
|
|
||||||
dprintk("NFS call mkdir %s\n", dentry->d_name.name);
|
dprintk("NFS call mkdir %s\n", dentry->d_name.name);
|
||||||
|
|
||||||
sattr->ia_mode &= ~current->fs->umask;
|
sattr->ia_mode &= ~current_umask();
|
||||||
|
|
||||||
data = nfs3_alloc_createdata();
|
data = nfs3_alloc_createdata();
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
|
@ -639,7 +639,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
||||||
dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
|
dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
|
||||||
MAJOR(rdev), MINOR(rdev));
|
MAJOR(rdev), MINOR(rdev));
|
||||||
|
|
||||||
sattr->ia_mode &= ~current->fs->umask;
|
sattr->ia_mode &= ~current_umask();
|
||||||
|
|
||||||
data = nfs3_alloc_createdata();
|
data = nfs3_alloc_createdata();
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
|
|
|
@ -1501,7 +1501,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
|
||||||
attr.ia_mode = nd->intent.open.create_mode;
|
attr.ia_mode = nd->intent.open.create_mode;
|
||||||
attr.ia_valid = ATTR_MODE;
|
attr.ia_valid = ATTR_MODE;
|
||||||
if (!IS_POSIXACL(dir))
|
if (!IS_POSIXACL(dir))
|
||||||
attr.ia_mode &= ~current->fs->umask;
|
attr.ia_mode &= ~current_umask();
|
||||||
} else {
|
} else {
|
||||||
attr.ia_valid = 0;
|
attr.ia_valid = 0;
|
||||||
BUG_ON(nd->intent.open.flags & O_CREAT);
|
BUG_ON(nd->intent.open.flags & O_CREAT);
|
||||||
|
|
|
@ -403,7 +403,6 @@ static int
|
||||||
nfsd(void *vrqstp)
|
nfsd(void *vrqstp)
|
||||||
{
|
{
|
||||||
struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
|
struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
|
||||||
struct fs_struct *fsp;
|
|
||||||
int err, preverr = 0;
|
int err, preverr = 0;
|
||||||
|
|
||||||
/* Lock module and set up kernel thread */
|
/* Lock module and set up kernel thread */
|
||||||
|
@ -412,13 +411,11 @@ nfsd(void *vrqstp)
|
||||||
/* At this point, the thread shares current->fs
|
/* At this point, the thread shares current->fs
|
||||||
* with the init process. We need to create files with a
|
* with the init process. We need to create files with a
|
||||||
* umask of 0 instead of init's umask. */
|
* umask of 0 instead of init's umask. */
|
||||||
fsp = copy_fs_struct(current->fs);
|
if (unshare_fs_struct() < 0) {
|
||||||
if (!fsp) {
|
|
||||||
printk("Unable to start nfsd thread: out of memory\n");
|
printk("Unable to start nfsd thread: out of memory\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
exit_fs(current);
|
|
||||||
current->fs = fsp;
|
|
||||||
current->fs->umask = 0;
|
current->fs->umask = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -296,7 +296,7 @@ int ocfs2_init_acl(handle_t *handle,
|
||||||
return PTR_ERR(acl);
|
return PTR_ERR(acl);
|
||||||
}
|
}
|
||||||
if (!acl)
|
if (!acl)
|
||||||
inode->i_mode &= ~current->fs->umask;
|
inode->i_mode &= ~current_umask();
|
||||||
}
|
}
|
||||||
if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
|
if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
|
||||||
struct posix_acl *clone;
|
struct posix_acl *clone;
|
||||||
|
|
|
@ -426,7 +426,7 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
|
|
||||||
sbi->s_uid = current_uid();
|
sbi->s_uid = current_uid();
|
||||||
sbi->s_gid = current_gid();
|
sbi->s_gid = current_gid();
|
||||||
sbi->s_dmask = sbi->s_fmask = current->fs->umask;
|
sbi->s_dmask = sbi->s_fmask = current_umask();
|
||||||
|
|
||||||
if (!parse_options((char *) data, sbi))
|
if (!parse_options((char *) data, sbi))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <linux/rcupdate.h>
|
#include <linux/rcupdate.h>
|
||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
#include <linux/falloc.h>
|
#include <linux/falloc.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
#include <linux/oom.h>
|
#include <linux/oom.h>
|
||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
#include <linux/pid_namespace.h>
|
#include <linux/pid_namespace.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
/* NOTE:
|
/* NOTE:
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
#include <linux/fdtable.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
@ -49,7 +50,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
|
||||||
else
|
else
|
||||||
bytes += kobjsize(mm);
|
bytes += kobjsize(mm);
|
||||||
|
|
||||||
if (current->fs && atomic_read(¤t->fs->count) > 1)
|
if (current->fs && current->fs->users > 1)
|
||||||
sbytes += kobjsize(current->fs);
|
sbytes += kobjsize(current->fs);
|
||||||
else
|
else
|
||||||
bytes += kobjsize(current->fs);
|
bytes += kobjsize(current->fs);
|
||||||
|
|
|
@ -428,7 +428,7 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
||||||
} else {
|
} else {
|
||||||
apply_umask:
|
apply_umask:
|
||||||
/* no ACL, apply umask */
|
/* no ACL, apply umask */
|
||||||
inode->i_mode &= ~current->fs->umask;
|
inode->i_mode &= ~current_umask();
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -227,7 +227,7 @@ xfs_vn_mknod(
|
||||||
xfs_dentry_to_name(&name, dentry);
|
xfs_dentry_to_name(&name, dentry);
|
||||||
|
|
||||||
if (IS_POSIXACL(dir) && !default_acl)
|
if (IS_POSIXACL(dir) && !default_acl)
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
|
|
||||||
switch (mode & S_IFMT) {
|
switch (mode & S_IFMT) {
|
||||||
case S_IFCHR:
|
case S_IFCHR:
|
||||||
|
@ -416,7 +416,7 @@ xfs_vn_symlink(
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
|
|
||||||
mode = S_IFLNK |
|
mode = S_IFLNK |
|
||||||
(irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
|
(irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO);
|
||||||
xfs_dentry_to_name(&name, dentry);
|
xfs_dentry_to_name(&name, dentry);
|
||||||
|
|
||||||
error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL);
|
error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL);
|
||||||
|
|
|
@ -332,22 +332,10 @@ extern int __set_page_dirty_buffers(struct page *page);
|
||||||
|
|
||||||
static inline void buffer_init(void) {}
|
static inline void buffer_init(void) {}
|
||||||
static inline int try_to_free_buffers(struct page *page) { return 1; }
|
static inline int try_to_free_buffers(struct page *page) { return 1; }
|
||||||
static inline int sync_blockdev(struct block_device *bdev) { return 0; }
|
|
||||||
static inline int inode_has_buffers(struct inode *inode) { return 0; }
|
static inline int inode_has_buffers(struct inode *inode) { return 0; }
|
||||||
static inline void invalidate_inode_buffers(struct inode *inode) {}
|
static inline void invalidate_inode_buffers(struct inode *inode) {}
|
||||||
static inline int remove_inode_buffers(struct inode *inode) { return 1; }
|
static inline int remove_inode_buffers(struct inode *inode) { return 1; }
|
||||||
static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; }
|
static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; }
|
||||||
static inline void invalidate_bdev(struct block_device *bdev) {}
|
|
||||||
|
|
||||||
static inline struct super_block *freeze_bdev(struct block_device *sb)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_BLOCK */
|
#endif /* CONFIG_BLOCK */
|
||||||
#endif /* _LINUX_BUFFER_HEAD_H */
|
#endif /* _LINUX_BUFFER_HEAD_H */
|
||||||
|
|
|
@ -1741,6 +1741,8 @@ extern void drop_collected_mounts(struct vfsmount *);
|
||||||
|
|
||||||
extern int vfs_statfs(struct dentry *, struct kstatfs *);
|
extern int vfs_statfs(struct dentry *, struct kstatfs *);
|
||||||
|
|
||||||
|
extern int current_umask(void);
|
||||||
|
|
||||||
/* /sys/fs */
|
/* /sys/fs */
|
||||||
extern struct kobject *fs_kobj;
|
extern struct kobject *fs_kobj;
|
||||||
|
|
||||||
|
@ -1885,6 +1887,18 @@ extern int fsync_super(struct super_block *);
|
||||||
extern int fsync_no_super(struct block_device *);
|
extern int fsync_no_super(struct block_device *);
|
||||||
#else
|
#else
|
||||||
static inline void bd_forget(struct inode *inode) {}
|
static inline void bd_forget(struct inode *inode) {}
|
||||||
|
static inline int sync_blockdev(struct block_device *bdev) { return 0; }
|
||||||
|
static inline void invalidate_bdev(struct block_device *bdev) {}
|
||||||
|
|
||||||
|
static inline struct super_block *freeze_bdev(struct block_device *sb)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
extern const struct file_operations def_blk_fops;
|
extern const struct file_operations def_blk_fops;
|
||||||
extern const struct file_operations def_chr_fops;
|
extern const struct file_operations def_chr_fops;
|
||||||
|
|
|
@ -4,12 +4,10 @@
|
||||||
#include <linux/path.h>
|
#include <linux/path.h>
|
||||||
|
|
||||||
struct fs_struct {
|
struct fs_struct {
|
||||||
atomic_t count; /* This usage count is used by check_unsafe_exec() for
|
int users;
|
||||||
* security checking purposes - therefore it may not be
|
|
||||||
* incremented, except by clone(CLONE_FS).
|
|
||||||
*/
|
|
||||||
rwlock_t lock;
|
rwlock_t lock;
|
||||||
int umask;
|
int umask;
|
||||||
|
int in_exec;
|
||||||
struct path root, pwd;
|
struct path root, pwd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,6 +17,8 @@ extern void exit_fs(struct task_struct *);
|
||||||
extern void set_fs_root(struct fs_struct *, struct path *);
|
extern void set_fs_root(struct fs_struct *, struct path *);
|
||||||
extern void set_fs_pwd(struct fs_struct *, struct path *);
|
extern void set_fs_pwd(struct fs_struct *, struct path *);
|
||||||
extern struct fs_struct *copy_fs_struct(struct fs_struct *);
|
extern struct fs_struct *copy_fs_struct(struct fs_struct *);
|
||||||
extern void put_fs_struct(struct fs_struct *);
|
extern void free_fs_struct(struct fs_struct *);
|
||||||
|
extern void daemonize_fs_struct(void);
|
||||||
|
extern int unshare_fs_struct(void);
|
||||||
|
|
||||||
#endif /* _LINUX_FS_STRUCT_H */
|
#endif /* _LINUX_FS_STRUCT_H */
|
||||||
|
|
|
@ -22,6 +22,8 @@ struct proc_mounts {
|
||||||
int event;
|
int event;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fs_struct;
|
||||||
|
|
||||||
extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
|
extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
|
||||||
struct fs_struct *);
|
struct fs_struct *);
|
||||||
extern void __put_mnt_ns(struct mnt_namespace *ns);
|
extern void __put_mnt_ns(struct mnt_namespace *ns);
|
||||||
|
|
|
@ -11,21 +11,11 @@
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_BLOCK
|
#ifdef CONFIG_BLOCK
|
||||||
|
|
||||||
struct mpage_data {
|
|
||||||
struct bio *bio;
|
|
||||||
sector_t last_block_in_bio;
|
|
||||||
get_block_t *get_block;
|
|
||||||
unsigned use_writepage;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct writeback_control;
|
struct writeback_control;
|
||||||
|
|
||||||
struct bio *mpage_bio_submit(int rw, struct bio *bio);
|
|
||||||
int mpage_readpages(struct address_space *mapping, struct list_head *pages,
|
int mpage_readpages(struct address_space *mapping, struct list_head *pages,
|
||||||
unsigned nr_pages, get_block_t get_block);
|
unsigned nr_pages, get_block_t get_block);
|
||||||
int mpage_readpage(struct page *page, get_block_t get_block);
|
int mpage_readpage(struct page *page, get_block_t get_block);
|
||||||
int __mpage_writepage(struct page *page, struct writeback_control *wbc,
|
|
||||||
void *data);
|
|
||||||
int mpage_writepages(struct address_space *mapping,
|
int mpage_writepages(struct address_space *mapping,
|
||||||
struct writeback_control *wbc, get_block_t get_block);
|
struct writeback_control *wbc, get_block_t get_block);
|
||||||
int mpage_writepage(struct page *page, get_block_t *get_block,
|
int mpage_writepage(struct page *page, get_block_t *get_block,
|
||||||
|
|
|
@ -8,6 +8,7 @@ struct mnt_namespace;
|
||||||
struct uts_namespace;
|
struct uts_namespace;
|
||||||
struct ipc_namespace;
|
struct ipc_namespace;
|
||||||
struct pid_namespace;
|
struct pid_namespace;
|
||||||
|
struct fs_struct;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A structure to contain pointers to all per-process
|
* A structure to contain pointers to all per-process
|
||||||
|
|
|
@ -68,7 +68,7 @@ struct sched_param {
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/sem.h>
|
#include <linux/sem.h>
|
||||||
#include <linux/signal.h>
|
#include <linux/signal.h>
|
||||||
#include <linux/fs_struct.h>
|
#include <linux/path.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/pid.h>
|
#include <linux/pid.h>
|
||||||
|
@ -97,6 +97,7 @@ struct futex_pi_state;
|
||||||
struct robust_list_head;
|
struct robust_list_head;
|
||||||
struct bio;
|
struct bio;
|
||||||
struct bts_tracer;
|
struct bts_tracer;
|
||||||
|
struct fs_struct;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of flags we want to share for kernel threads,
|
* List of flags we want to share for kernel threads,
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/initrd.h>
|
#include <linux/initrd.h>
|
||||||
#include <linux/async.h>
|
#include <linux/async.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
#include <linux/nfs_fs.h>
|
#include <linux/nfs_fs.h>
|
||||||
#include <linux/nfs_fs_sb.h>
|
#include <linux/nfs_fs_sb.h>
|
||||||
|
|
|
@ -602,7 +602,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
|
||||||
dentry->d_fsdata = attr;
|
dentry->d_fsdata = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current_umask();
|
||||||
ret = mnt_want_write(mqueue_mnt);
|
ret = mnt_want_write(mqueue_mnt);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include <linux/inotify.h>
|
#include <linux/inotify.h>
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
#include "audit.h"
|
#include "audit.h"
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include <linux/sysctl.h>
|
#include <linux/sysctl.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
|
|
||||||
static void default_handler(int, struct pt_regs *);
|
static void default_handler(int, struct pt_regs *);
|
||||||
|
@ -145,28 +146,6 @@ __set_personality(u_long personality)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(¤t->fs->count) != 1) {
|
|
||||||
struct fs_struct *fsp, *ofsp;
|
|
||||||
|
|
||||||
fsp = copy_fs_struct(current->fs);
|
|
||||||
if (fsp == NULL) {
|
|
||||||
module_put(ep->module);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
task_lock(current);
|
|
||||||
ofsp = current->fs;
|
|
||||||
current->fs = fsp;
|
|
||||||
task_unlock(current);
|
|
||||||
|
|
||||||
put_fs_struct(ofsp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At that point we are guaranteed to be the sole owner of
|
|
||||||
* current->fs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
current->personality = personality;
|
current->personality = personality;
|
||||||
oep = current_thread_info()->exec_domain;
|
oep = current_thread_info()->exec_domain;
|
||||||
current_thread_info()->exec_domain = ep;
|
current_thread_info()->exec_domain = ep;
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/task_io_accounting_ops.h>
|
#include <linux/task_io_accounting_ops.h>
|
||||||
#include <linux/tracehook.h>
|
#include <linux/tracehook.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
#include <linux/init_task.h>
|
#include <linux/init_task.h>
|
||||||
#include <trace/sched.h>
|
#include <trace/sched.h>
|
||||||
|
|
||||||
|
@ -420,7 +421,6 @@ EXPORT_SYMBOL(disallow_signal);
|
||||||
void daemonize(const char *name, ...)
|
void daemonize(const char *name, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
struct fs_struct *fs;
|
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
va_start(args, name);
|
va_start(args, name);
|
||||||
|
@ -453,11 +453,7 @@ void daemonize(const char *name, ...)
|
||||||
|
|
||||||
/* Become as one with the init task */
|
/* Become as one with the init task */
|
||||||
|
|
||||||
exit_fs(current); /* current->fs->count--; */
|
daemonize_fs_struct();
|
||||||
fs = init_task.fs;
|
|
||||||
current->fs = fs;
|
|
||||||
atomic_inc(&fs->count);
|
|
||||||
|
|
||||||
exit_files(current);
|
exit_files(current);
|
||||||
current->files = init_task.files;
|
current->files = init_task.files;
|
||||||
atomic_inc(¤t->files->count);
|
atomic_inc(¤t->files->count);
|
||||||
|
@ -556,30 +552,6 @@ void exit_files(struct task_struct *tsk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_fs_struct(struct fs_struct *fs)
|
|
||||||
{
|
|
||||||
/* No need to hold fs->lock if we are killing it */
|
|
||||||
if (atomic_dec_and_test(&fs->count)) {
|
|
||||||
path_put(&fs->root);
|
|
||||||
path_put(&fs->pwd);
|
|
||||||
kmem_cache_free(fs_cachep, fs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void exit_fs(struct task_struct *tsk)
|
|
||||||
{
|
|
||||||
struct fs_struct * fs = tsk->fs;
|
|
||||||
|
|
||||||
if (fs) {
|
|
||||||
task_lock(tsk);
|
|
||||||
tsk->fs = NULL;
|
|
||||||
task_unlock(tsk);
|
|
||||||
put_fs_struct(fs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(exit_fs);
|
|
||||||
|
|
||||||
#ifdef CONFIG_MM_OWNER
|
#ifdef CONFIG_MM_OWNER
|
||||||
/*
|
/*
|
||||||
* Task p is exiting and it owned mm, lets find a new owner for it
|
* Task p is exiting and it owned mm, lets find a new owner for it
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
#include <trace/sched.h>
|
#include <trace/sched.h>
|
||||||
#include <linux/magic.h>
|
#include <linux/magic.h>
|
||||||
|
|
||||||
|
@ -681,38 +682,21 @@ fail_nomem:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fs_struct *__copy_fs_struct(struct fs_struct *old)
|
|
||||||
{
|
|
||||||
struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
|
|
||||||
/* We don't need to lock fs - think why ;-) */
|
|
||||||
if (fs) {
|
|
||||||
atomic_set(&fs->count, 1);
|
|
||||||
rwlock_init(&fs->lock);
|
|
||||||
fs->umask = old->umask;
|
|
||||||
read_lock(&old->lock);
|
|
||||||
fs->root = old->root;
|
|
||||||
path_get(&old->root);
|
|
||||||
fs->pwd = old->pwd;
|
|
||||||
path_get(&old->pwd);
|
|
||||||
read_unlock(&old->lock);
|
|
||||||
}
|
|
||||||
return fs;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct fs_struct *copy_fs_struct(struct fs_struct *old)
|
|
||||||
{
|
|
||||||
return __copy_fs_struct(old);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(copy_fs_struct);
|
|
||||||
|
|
||||||
static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
|
static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
|
||||||
{
|
{
|
||||||
|
struct fs_struct *fs = current->fs;
|
||||||
if (clone_flags & CLONE_FS) {
|
if (clone_flags & CLONE_FS) {
|
||||||
atomic_inc(¤t->fs->count);
|
/* tsk->fs is already what we want */
|
||||||
|
write_lock(&fs->lock);
|
||||||
|
if (fs->in_exec) {
|
||||||
|
write_unlock(&fs->lock);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
fs->users++;
|
||||||
|
write_unlock(&fs->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
tsk->fs = __copy_fs_struct(current->fs);
|
tsk->fs = copy_fs_struct(fs);
|
||||||
if (!tsk->fs)
|
if (!tsk->fs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1544,12 +1528,16 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
|
||||||
{
|
{
|
||||||
struct fs_struct *fs = current->fs;
|
struct fs_struct *fs = current->fs;
|
||||||
|
|
||||||
if ((unshare_flags & CLONE_FS) &&
|
if (!(unshare_flags & CLONE_FS) || !fs)
|
||||||
(fs && atomic_read(&fs->count) > 1)) {
|
return 0;
|
||||||
*new_fsp = __copy_fs_struct(current->fs);
|
|
||||||
|
/* don't need lock here; in the worst case we'll do useless copy */
|
||||||
|
if (fs->users == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*new_fsp = copy_fs_struct(fs);
|
||||||
if (!*new_fsp)
|
if (!*new_fsp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1665,8 +1653,13 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
|
||||||
|
|
||||||
if (new_fs) {
|
if (new_fs) {
|
||||||
fs = current->fs;
|
fs = current->fs;
|
||||||
|
write_lock(&fs->lock);
|
||||||
current->fs = new_fs;
|
current->fs = new_fs;
|
||||||
|
if (--fs->users)
|
||||||
|
new_fs = NULL;
|
||||||
|
else
|
||||||
new_fs = fs;
|
new_fs = fs;
|
||||||
|
write_unlock(&fs->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_mm) {
|
if (new_mm) {
|
||||||
|
@ -1705,7 +1698,7 @@ bad_unshare_cleanup_sigh:
|
||||||
|
|
||||||
bad_unshare_cleanup_fs:
|
bad_unshare_cleanup_fs:
|
||||||
if (new_fs)
|
if (new_fs)
|
||||||
put_fs_struct(new_fs);
|
free_fs_struct(new_fs);
|
||||||
|
|
||||||
bad_unshare_cleanup_thread:
|
bad_unshare_cleanup_thread:
|
||||||
bad_unshare_out:
|
bad_unshare_out:
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <linux/seccomp.h>
|
#include <linux/seccomp.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
|
|
|
@ -832,7 +832,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||||
* All right, let's create it.
|
* All right, let's create it.
|
||||||
*/
|
*/
|
||||||
mode = S_IFSOCK |
|
mode = S_IFSOCK |
|
||||||
(SOCK_INODE(sock)->i_mode & ~current->fs->umask);
|
(SOCK_INODE(sock)->i_mode & ~current_umask());
|
||||||
err = mnt_want_write(nd.path.mnt);
|
err = mnt_want_write(nd.path.mnt);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_mknod_dput;
|
goto out_mknod_dput;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/mnt_namespace.h>
|
#include <linux/mnt_namespace.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "realpath.h"
|
#include "realpath.h"
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче