git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
gfs: constify xattr_handler
[safe/jmp/linux-2.6]
/
fs
/
namespace.c
diff --git
a/fs/namespace.c
b/fs/namespace.c
index
277c28a
..
88058de
100644
(file)
--- a/
fs/namespace.c
+++ b/
fs/namespace.c
@@
-316,7
+316,8
@@
EXPORT_SYMBOL_GPL(mnt_clone_write);
*/
int mnt_want_write_file(struct file *file)
{
*/
int mnt_want_write_file(struct file *file)
{
- if (!(file->f_mode & FMODE_WRITE))
+ struct inode *inode = file->f_dentry->d_inode;
+ if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode))
return mnt_want_write(file->f_path.mnt);
else
return mnt_clone_write(file->f_path.mnt);
return mnt_want_write(file->f_path.mnt);
else
return mnt_clone_write(file->f_path.mnt);
@@
-572,7
+573,7
@@
static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
mnt->mnt_master = old;
CLEAR_MNT_SHARED(mnt);
} else if (!(flag & CL_PRIVATE)) {
mnt->mnt_master = old;
CLEAR_MNT_SHARED(mnt);
} else if (!(flag & CL_PRIVATE)) {
- if ((flag & CL_
PROPAGATION
) || IS_MNT_SHARED(old))
+ if ((flag & CL_
MAKE_SHARED
) || IS_MNT_SHARED(old))
list_add(&mnt->mnt_share, &old->mnt_share);
if (IS_MNT_SLAVE(old))
list_add(&mnt->mnt_slave, &old->mnt_slave);
list_add(&mnt->mnt_share, &old->mnt_share);
if (IS_MNT_SLAVE(old))
list_add(&mnt->mnt_slave, &old->mnt_slave);
@@
-627,7
+628,6
@@
repeat:
mnt->mnt_pinned = 0;
spin_unlock(&vfsmount_lock);
acct_auto_close_mnt(mnt);
mnt->mnt_pinned = 0;
spin_unlock(&vfsmount_lock);
acct_auto_close_mnt(mnt);
- security_sb_umount_close(mnt);
goto repeat;
}
}
goto repeat;
}
}
@@
-736,6
+736,21
@@
static void m_stop(struct seq_file *m, void *v)
up_read(&namespace_sem);
}
up_read(&namespace_sem);
}
+int mnt_had_events(struct proc_mounts *p)
+{
+ struct mnt_namespace *ns = p->ns;
+ int res = 0;
+
+ spin_lock(&vfsmount_lock);
+ if (p->event != ns->event) {
+ p->event = ns->event;
+ res = 1;
+ }
+ spin_unlock(&vfsmount_lock);
+
+ return res;
+}
+
struct proc_fs_info {
int flag;
const char *str;
struct proc_fs_info {
int flag;
const char *str;
@@
-964,10
+979,12
@@
EXPORT_SYMBOL(may_umount_tree);
int may_umount(struct vfsmount *mnt)
{
int ret = 1;
int may_umount(struct vfsmount *mnt)
{
int ret = 1;
+ down_read(&namespace_sem);
spin_lock(&vfsmount_lock);
if (propagate_mount_busy(mnt, 2))
ret = 0;
spin_unlock(&vfsmount_lock);
spin_lock(&vfsmount_lock);
if (propagate_mount_busy(mnt, 2))
ret = 0;
spin_unlock(&vfsmount_lock);
+ up_read(&namespace_sem);
return ret;
}
return ret;
}
@@
-1099,8
+1116,6
@@
static int do_umount(struct vfsmount *mnt, int flags)
retval = 0;
}
spin_unlock(&vfsmount_lock);
retval = 0;
}
spin_unlock(&vfsmount_lock);
- if (retval)
- security_sb_umount_busy(mnt);
up_write(&namespace_sem);
release_mounts(&umount_list);
return retval;
up_write(&namespace_sem);
release_mounts(&umount_list);
return retval;
@@
-1118,8
+1133,15
@@
SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
{
struct path path;
int retval;
{
struct path path;
int retval;
+ int lookup_flags = 0;
+
+ if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
+ return -EINVAL;
- retval = user_path(name, &path);
+ if (!(flags & UMOUNT_NOFOLLOW))
+ lookup_flags |= LOOKUP_FOLLOW;
+
+ retval = user_path_at(AT_FDCWD, name, lookup_flags, &path);
if (retval)
goto out;
retval = -EINVAL;
if (retval)
goto out;
retval = -EINVAL;
@@
-1243,6
+1265,21
@@
void drop_collected_mounts(struct vfsmount *mnt)
release_mounts(&umount_list);
}
release_mounts(&umount_list);
}
+int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
+ struct vfsmount *root)
+{
+ struct vfsmount *mnt;
+ int res = f(root, arg);
+ if (res)
+ return res;
+ list_for_each_entry(mnt, &root->mnt_list, mnt_list) {
+ res = f(mnt, arg);
+ if (res)
+ return res;
+ }
+ return 0;
+}
+
static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
{
struct vfsmount *p;
static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
{
struct vfsmount *p;
@@
-1351,12
+1388,12
@@
static int attach_recursive_mnt(struct vfsmount *source_mnt,
if (err)
goto out_cleanup_ids;
if (err)
goto out_cleanup_ids;
+ spin_lock(&vfsmount_lock);
+
if (IS_MNT_SHARED(dest_mnt)) {
for (p = source_mnt; p; p = next_mnt(p, source_mnt))
set_mnt_shared(p);
}
if (IS_MNT_SHARED(dest_mnt)) {
for (p = source_mnt; p; p = next_mnt(p, source_mnt))
set_mnt_shared(p);
}
-
- spin_lock(&vfsmount_lock);
if (parent_path) {
detach_mnt(source_mnt, parent_path);
attach_mnt(source_mnt, path);
if (parent_path) {
detach_mnt(source_mnt, parent_path);
attach_mnt(source_mnt, path);
@@
-1392,20
+1429,13
@@
static int graft_tree(struct vfsmount *mnt, struct path *path)
err = -ENOENT;
mutex_lock(&path->dentry->d_inode->i_mutex);
err = -ENOENT;
mutex_lock(&path->dentry->d_inode->i_mutex);
- if (IS_DEADDIR(path->dentry->d_inode))
- goto out_unlock;
-
- err = security_sb_check_sb(mnt, path);
- if (err)
+ if (cant_mount(path->dentry))
goto out_unlock;
goto out_unlock;
- err = -ENOENT;
if (!d_unlinked(path->dentry))
err = attach_recursive_mnt(mnt, path, NULL);
out_unlock:
mutex_unlock(&path->dentry->d_inode->i_mutex);
if (!d_unlinked(path->dentry))
err = attach_recursive_mnt(mnt, path, NULL);
out_unlock:
mutex_unlock(&path->dentry->d_inode->i_mutex);
- if (!err)
- security_sb_post_addmount(mnt, path);
return err;
}
return err;
}
@@
-1533,12
+1563,14
@@
static int do_remount(struct path *path, int flags, int mnt_flags,
err = change_mount_flags(path->mnt, flags);
else
err = do_remount_sb(sb, flags, data, 0);
err = change_mount_flags(path->mnt, flags);
else
err = do_remount_sb(sb, flags, data, 0);
- if (!err)
+ if (!err) {
+ spin_lock(&vfsmount_lock);
+ mnt_flags |= path->mnt->mnt_flags & MNT_PROPAGATION_MASK;
path->mnt->mnt_flags = mnt_flags;
path->mnt->mnt_flags = mnt_flags;
+ spin_unlock(&vfsmount_lock);
+ }
up_write(&sb->s_umount);
if (!err) {
up_write(&sb->s_umount);
if (!err) {
- security_sb_post_remount(path->mnt, flags, data);
-
spin_lock(&vfsmount_lock);
touch_mnt_namespace(path->mnt->mnt_ns);
spin_unlock(&vfsmount_lock);
spin_lock(&vfsmount_lock);
touch_mnt_namespace(path->mnt->mnt_ns);
spin_unlock(&vfsmount_lock);
@@
-1579,7
+1611,7
@@
static int do_move_mount(struct path *path, char *old_name)
err = -ENOENT;
mutex_lock(&path->dentry->d_inode->i_mutex);
err = -ENOENT;
mutex_lock(&path->dentry->d_inode->i_mutex);
- if (
IS_DEADDIR(path->dentry->d_inode
))
+ if (
cant_mount(path->dentry
))
goto out1;
if (d_unlinked(path->dentry))
goto out1;
if (d_unlinked(path->dentry))
@@
-1639,7
+1671,7
@@
static int do_new_mount(struct path *path, char *type, int flags,
{
struct vfsmount *mnt;
{
struct vfsmount *mnt;
- if (!type
|| !memchr(type, 0, PAGE_SIZE)
)
+ if (!type)
return -EINVAL;
/* we need capabilities... */
return -EINVAL;
/* we need capabilities... */
@@
-1664,6
+1696,8
@@
int do_add_mount(struct vfsmount *newmnt, struct path *path,
{
int err;
{
int err;
+ mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
+
down_write(&namespace_sem);
/* Something was mounted here while we slept */
while (d_mountpoint(path->dentry) &&
down_write(&namespace_sem);
/* Something was mounted here while we slept */
while (d_mountpoint(path->dentry) &&
@@
-1870,6
+1904,23
@@
int copy_mount_options(const void __user * data, unsigned long *where)
return 0;
}
return 0;
}
+int copy_mount_string(const void __user *data, char **where)
+{
+ char *tmp;
+
+ if (!data) {
+ *where = NULL;
+ return 0;
+ }
+
+ tmp = strndup_user(data, PAGE_SIZE);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ *where = tmp;
+ return 0;
+}
+
/*
* Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
* be given to the mount() call (ie: read-only, no-dev, no-suid etc).
/*
* Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
* be given to the mount() call (ie: read-only, no-dev, no-suid etc).
@@
-1899,12
+1950,20
@@
long do_mount(char *dev_name, char *dir_name, char *type_page,
if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
return -EINVAL;
if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
return -EINVAL;
- if (dev_name && !memchr(dev_name, 0, PAGE_SIZE))
- return -EINVAL;
if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;
if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;
+ /* ... and get the mountpoint */
+ retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
+ if (retval)
+ return retval;
+
+ retval = security_sb_mount(dev_name, &path,
+ type_page, flags, data_page);
+ if (retval)
+ goto dput_out;
+
/* Default to relatime unless overriden */
if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME;
/* Default to relatime unless overriden */
if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME;
@@
-1929,16
+1988,6
@@
long do_mount(char *dev_name, char *dir_name, char *type_page,
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);
- /* ... and get the mountpoint */
- retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
- if (retval)
- return retval;
-
- retval = security_sb_mount(dev_name, &path,
- type_page, flags, data_page);
- if (retval)
- goto dput_out;
-
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
data_page);
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
data_page);
@@
-2069,40
+2118,42
@@
EXPORT_SYMBOL(create_mnt_ns);
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)
{
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)
{
- int retval;
+ int ret;
+ char *kernel_type;
+ char *kernel_dir;
+ char *kernel_dev;
unsigned long data_page;
unsigned long data_page;
- unsigned long type_page;
- unsigned long dev_page;
- char *dir_page;
- ret
val = copy_mount_options(type, &type_pag
e);
- if (ret
val
< 0)
-
return retval
;
+ ret
= copy_mount_string(type, &kernel_typ
e);
+ if (ret < 0)
+
goto out_type
;
- dir_page = getname(dir_name);
- retval = PTR_ERR(dir_page);
- if (IS_ERR(dir_page))
- goto out1;
+ kernel_dir = getname(dir_name);
+ if (IS_ERR(kernel_dir)) {
+ ret = PTR_ERR(kernel_dir);
+ goto out_dir;
+ }
- ret
val = copy_mount_options(dev_name, &dev_page
);
- if (ret
val
< 0)
- goto out
2
;
+ ret
= copy_mount_string(dev_name, &kernel_dev
);
+ if (ret < 0)
+ goto out
_dev
;
- ret
val
= copy_mount_options(data, &data_page);
- if (ret
val
< 0)
- goto out
3
;
+ ret = copy_mount_options(data, &data_page);
+ if (ret < 0)
+ goto out
_data
;
- retval = do_mount((char *)dev_page, dir_page, (char *)type_page,
- flags, (void *)data_page);
- free_page(data_page);
+ ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
+ (void *) data_page);
-out3:
- free_page(dev_page);
-out2:
- putname(dir_page);
-out1:
- free_page(type_page);
- return retval;
+ free_page(data_page);
+out_data:
+ kfree(kernel_dev);
+out_dev:
+ putname(kernel_dir);
+out_dir:
+ kfree(kernel_type);
+out_type:
+ return ret;
}
/*
}
/*
@@
-2171,7
+2222,7
@@
SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
if (!check_mnt(root.mnt))
goto out2;
error = -ENOENT;
if (!check_mnt(root.mnt))
goto out2;
error = -ENOENT;
- if (
IS_DEADDIR(new.dentry->d_inode
))
+ if (
cant_mount(old.dentry
))
goto out2;
if (d_unlinked(new.dentry))
goto out2;
goto out2;
if (d_unlinked(new.dentry))
goto out2;
@@
-2214,7
+2265,6
@@
SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
touch_mnt_namespace(current->nsproxy->mnt_ns);
spin_unlock(&vfsmount_lock);
chroot_fs_refs(&root, &new);
touch_mnt_namespace(current->nsproxy->mnt_ns);
spin_unlock(&vfsmount_lock);
chroot_fs_refs(&root, &new);
- security_sb_post_pivotroot(&root, &new);
error = 0;
path_put(&root_parent);
path_put(&parent_path);
error = 0;
path_put(&root_parent);
path_put(&parent_path);
@@
-2288,17
+2338,13
@@
void __init mnt_init(void)
void put_mnt_ns(struct mnt_namespace *ns)
{
void put_mnt_ns(struct mnt_namespace *ns)
{
- struct vfsmount *root;
LIST_HEAD(umount_list);
LIST_HEAD(umount_list);
- if (!atomic_dec_and_
lock(&ns->count, &vfsmount_lock
))
+ if (!atomic_dec_and_
test(&ns->count
))
return;
return;
- root = ns->root;
- ns->root = NULL;
- spin_unlock(&vfsmount_lock);
down_write(&namespace_sem);
spin_lock(&vfsmount_lock);
down_write(&namespace_sem);
spin_lock(&vfsmount_lock);
- umount_tree(root, 0, &umount_list);
+ umount_tree(
ns->
root, 0, &umount_list);
spin_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umount_list);
spin_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umount_list);