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:
Linus Torvalds 2009-04-02 21:09:10 -07:00
commit 8fe74cf053
57 changed files with 337 additions and 268 deletions

View File

@ -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>

View File

@ -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,

View File

@ -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 {

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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) {

View File

@ -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)

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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(&current->fs->lock);
current->fs->in_exec = 0;
write_unlock(&current->fs->lock);
current->in_execve = 0; current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex); mutex_unlock(&current->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(&current->fs->lock);
current->fs->in_exec = 0;
write_unlock(&current->fs->lock);
out_unlock: out_unlock:
current->in_execve = 0; current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex); mutex_unlock(&current->cred_exec_mutex);

View File

@ -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;

View File

@ -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(&current->fs->lock);
current->fs->in_exec = 0;
write_unlock(&current->fs->lock);
current->in_execve = 0; current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex); mutex_unlock(&current->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(&current->fs->lock);
current->fs->in_exec = 0;
write_unlock(&current->fs->lock);
out_unlock: out_unlock:
current->in_execve = 0; current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex); mutex_unlock(&current->cred_exec_mutex);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

177
fs/fs_struct.c Normal file
View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 *);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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,
};

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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;
/* /*

View File

@ -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;

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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:

View File

@ -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(&current->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);

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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>

View File

@ -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;

View File

@ -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"

View File

@ -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(&current->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;

View File

@ -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(&current->files->count); atomic_inc(&current->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

View File

@ -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(&current->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);
if (!*new_fsp) /* don't need lock here; in the worst case we'll do useless copy */
return -ENOMEM; if (fs->users == 1)
} return 0;
*new_fsp = copy_fs_struct(fs);
if (!*new_fsp)
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;
new_fs = fs; if (--fs->users)
new_fs = NULL;
else
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:

View File

@ -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>

View File

@ -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;

View File

@ -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"