Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
707c5960
Commit
707c5960
authored
Dec 10, 2014
by
Al Viro
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'nsfs' into for-next
parents
ba00410b
3d3d35b1
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
353 additions
and
297 deletions
+353
-297
fs/Makefile
fs/Makefile
+1
-1
fs/internal.h
fs/internal.h
+5
-0
fs/mount.h
fs/mount.h
+2
-1
fs/namespace.c
fs/namespace.c
+22
-29
fs/nsfs.c
fs/nsfs.c
+161
-0
fs/proc/inode.c
fs/proc/inode.c
+1
-9
fs/proc/internal.h
fs/proc/internal.h
+1
-1
fs/proc/namespaces.c
fs/proc/namespaces.c
+14
-139
include/linux/ipc_namespace.h
include/linux/ipc_namespace.h
+2
-1
include/linux/ns_common.h
include/linux/ns_common.h
+12
-0
include/linux/pid_namespace.h
include/linux/pid_namespace.h
+2
-1
include/linux/proc_ns.h
include/linux/proc_ns.h
+23
-20
include/linux/user_namespace.h
include/linux/user_namespace.h
+2
-1
include/linux/utsname.h
include/linux/utsname.h
+2
-1
include/net/net_namespace.h
include/net/net_namespace.h
+2
-1
include/uapi/linux/magic.h
include/uapi/linux/magic.h
+1
-0
init/main.c
init/main.c
+2
-0
init/version.c
init/version.c
+4
-1
ipc/msgutil.c
ipc/msgutil.c
+4
-1
ipc/namespace.c
ipc/namespace.c
+15
-17
kernel/nsproxy.c
kernel/nsproxy.c
+4
-6
kernel/pid.c
kernel/pid.c
+4
-1
kernel/pid_namespace.c
kernel/pid_namespace.c
+14
-15
kernel/user.c
kernel/user.c
+4
-1
kernel/user_namespace.c
kernel/user_namespace.c
+14
-15
kernel/utsname.c
kernel/utsname.c
+15
-16
net/core/net_namespace.c
net/core/net_namespace.c
+20
-19
No files found.
fs/Makefile
View file @
707c5960
...
...
@@ -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
\
seq_file.o xattr.o libfs.o fs-writeback.o
\
pnode.o splice.o sync.o utimes.o
\
stack.o fs_struct.o statfs.o fs_pin.o
stack.o fs_struct.o statfs.o fs_pin.o
nsfs.o
ifeq
($(CONFIG_BLOCK),y)
obj-y
+=
buffer.o block_dev.o direct-io.o mpage.o
...
...
fs/internal.h
View file @
707c5960
...
...
@@ -147,3 +147,8 @@ extern const struct file_operations pipefifo_fops;
*/
extern
void
sb_pin_kill
(
struct
super_block
*
sb
);
extern
void
mnt_pin_kill
(
struct
mount
*
m
);
/*
* fs/nsfs.c
*/
extern
struct
dentry_operations
ns_dentry_operations
;
fs/mount.h
View file @
707c5960
#include <linux/mount.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/ns_common.h>
struct
mnt_namespace
{
atomic_t
count
;
unsigned
int
proc_inum
;
struct
ns_common
ns
;
struct
mount
*
root
;
struct
list_head
list
;
struct
user_namespace
*
user_ns
;
...
...
fs/namespace.c
View file @
707c5960
...
...
@@ -1569,17 +1569,13 @@ SYSCALL_DEFINE1(oldumount, char __user *, name)
static
bool
is_mnt_ns_file
(
struct
dentry
*
dentry
)
{
/* Is this a proxy for a mount namespace? */
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
proc_ns
*
ei
;
if
(
!
proc_ns_inode
(
inode
))
return
false
;
ei
=
get_proc_ns
(
inode
);
if
(
ei
->
ns_ops
!=
&
mntns_operations
)
return
false
;
return
dentry
->
d_op
==
&
ns_dentry_operations
&&
dentry
->
d_fsdata
==
&
mntns_operations
;
}
return
true
;
struct
mnt_namespace
*
to_mnt_ns
(
struct
ns_common
*
ns
)
{
return
container_of
(
ns
,
struct
mnt_namespace
,
ns
);
}
static
bool
mnt_ns_loop
(
struct
dentry
*
dentry
)
...
...
@@ -1591,7 +1587,7 @@ static bool mnt_ns_loop(struct dentry *dentry)
if
(
!
is_mnt_ns_file
(
dentry
))
return
false
;
mnt_ns
=
get_proc_ns
(
dentry
->
d_inode
)
->
ns
;
mnt_ns
=
to_mnt_ns
(
get_proc_ns
(
dentry
->
d_inode
))
;
return
current
->
nsproxy
->
mnt_ns
->
seq
>=
mnt_ns
->
seq
;
}
...
...
@@ -2020,7 +2016,10 @@ static int do_loopback(struct path *path, const char *old_name,
if
(
IS_MNT_UNBINDABLE
(
old
))
goto
out2
;
if
(
!
check_mnt
(
parent
)
||
!
check_mnt
(
old
))
if
(
!
check_mnt
(
parent
))
goto
out2
;
if
(
!
check_mnt
(
old
)
&&
old_path
.
dentry
->
d_op
!=
&
ns_dentry_operations
)
goto
out2
;
if
(
!
recurse
&&
has_locked_children
(
old
,
old_path
.
dentry
))
...
...
@@ -2640,7 +2639,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
static
void
free_mnt_ns
(
struct
mnt_namespace
*
ns
)
{
proc_free_inum
(
ns
->
proc_inum
);
ns_free_inum
(
&
ns
->
ns
);
put_user_ns
(
ns
->
user_ns
);
kfree
(
ns
);
}
...
...
@@ -2662,11 +2661,12 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
new_ns
=
kmalloc
(
sizeof
(
struct
mnt_namespace
),
GFP_KERNEL
);
if
(
!
new_ns
)
return
ERR_PTR
(
-
ENOMEM
);
ret
=
proc_alloc_inum
(
&
new_ns
->
proc_inum
);
ret
=
ns_alloc_inum
(
&
new_ns
->
ns
);
if
(
ret
)
{
kfree
(
new_ns
);
return
ERR_PTR
(
ret
);
}
new_ns
->
ns
.
ops
=
&
mntns_operations
;
new_ns
->
seq
=
atomic64_add_return
(
1
,
&
mnt_ns_seq
);
atomic_set
(
&
new_ns
->
count
,
1
);
new_ns
->
root
=
NULL
;
...
...
@@ -3144,31 +3144,31 @@ bool fs_fully_visible(struct file_system_type *type)
return
visible
;
}
static
void
*
mntns_get
(
struct
task_struct
*
task
)
static
struct
ns_common
*
mntns_get
(
struct
task_struct
*
task
)
{
struct
mnt_namespace
*
ns
=
NULL
;
struct
ns_common
*
ns
=
NULL
;
struct
nsproxy
*
nsproxy
;
task_lock
(
task
);
nsproxy
=
task
->
nsproxy
;
if
(
nsproxy
)
{
ns
=
nsproxy
->
mnt_
ns
;
get_mnt_ns
(
ns
);
ns
=
&
nsproxy
->
mnt_ns
->
ns
;
get_mnt_ns
(
to_mnt_ns
(
ns
)
);
}
task_unlock
(
task
);
return
ns
;
}
static
void
mntns_put
(
void
*
ns
)
static
void
mntns_put
(
struct
ns_common
*
ns
)
{
put_mnt_ns
(
ns
);
put_mnt_ns
(
to_mnt_ns
(
ns
)
);
}
static
int
mntns_install
(
struct
nsproxy
*
nsproxy
,
void
*
ns
)
static
int
mntns_install
(
struct
nsproxy
*
nsproxy
,
struct
ns_common
*
ns
)
{
struct
fs_struct
*
fs
=
current
->
fs
;
struct
mnt_namespace
*
mnt_ns
=
ns
;
struct
mnt_namespace
*
mnt_ns
=
to_mnt_ns
(
ns
)
;
struct
path
root
;
if
(
!
ns_capable
(
mnt_ns
->
user_ns
,
CAP_SYS_ADMIN
)
||
...
...
@@ -3198,17 +3198,10 @@ static int mntns_install(struct nsproxy *nsproxy, void *ns)
return
0
;
}
static
unsigned
int
mntns_inum
(
void
*
ns
)
{
struct
mnt_namespace
*
mnt_ns
=
ns
;
return
mnt_ns
->
proc_inum
;
}
const
struct
proc_ns_operations
mntns_operations
=
{
.
name
=
"mnt"
,
.
type
=
CLONE_NEWNS
,
.
get
=
mntns_get
,
.
put
=
mntns_put
,
.
install
=
mntns_install
,
.
inum
=
mntns_inum
,
};
fs/nsfs.c
0 → 100644
View file @
707c5960
#include <linux/mount.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/proc_ns.h>
#include <linux/magic.h>
#include <linux/ktime.h>
static
struct
vfsmount
*
nsfs_mnt
;
static
const
struct
file_operations
ns_file_operations
=
{
.
llseek
=
no_llseek
,
};
static
char
*
ns_dname
(
struct
dentry
*
dentry
,
char
*
buffer
,
int
buflen
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
const
struct
proc_ns_operations
*
ns_ops
=
dentry
->
d_fsdata
;
return
dynamic_dname
(
dentry
,
buffer
,
buflen
,
"%s:[%lu]"
,
ns_ops
->
name
,
inode
->
i_ino
);
}
static
void
ns_prune_dentry
(
struct
dentry
*
dentry
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
if
(
inode
)
{
struct
ns_common
*
ns
=
inode
->
i_private
;
atomic_long_set
(
&
ns
->
stashed
,
0
);
}
}
const
struct
dentry_operations
ns_dentry_operations
=
{
.
d_prune
=
ns_prune_dentry
,
.
d_delete
=
always_delete_dentry
,
.
d_dname
=
ns_dname
,
};
static
void
nsfs_evict
(
struct
inode
*
inode
)
{
struct
ns_common
*
ns
=
inode
->
i_private
;
clear_inode
(
inode
);
ns
->
ops
->
put
(
ns
);
}
void
*
ns_get_path
(
struct
path
*
path
,
struct
task_struct
*
task
,
const
struct
proc_ns_operations
*
ns_ops
)
{
struct
vfsmount
*
mnt
=
mntget
(
nsfs_mnt
);
struct
qstr
qname
=
{
.
name
=
""
,
};
struct
dentry
*
dentry
;
struct
inode
*
inode
;
struct
ns_common
*
ns
;
unsigned
long
d
;
again:
ns
=
ns_ops
->
get
(
task
);
if
(
!
ns
)
{
mntput
(
mnt
);
return
ERR_PTR
(
-
ENOENT
);
}
rcu_read_lock
();
d
=
atomic_long_read
(
&
ns
->
stashed
);
if
(
!
d
)
goto
slow
;
dentry
=
(
struct
dentry
*
)
d
;
if
(
!
lockref_get_not_dead
(
&
dentry
->
d_lockref
))
goto
slow
;
rcu_read_unlock
();
ns_ops
->
put
(
ns
);
got_it:
path
->
mnt
=
mnt
;
path
->
dentry
=
dentry
;
return
NULL
;
slow:
rcu_read_unlock
();
inode
=
new_inode_pseudo
(
mnt
->
mnt_sb
);
if
(
!
inode
)
{
ns_ops
->
put
(
ns
);
mntput
(
mnt
);
return
ERR_PTR
(
-
ENOMEM
);
}
inode
->
i_ino
=
ns
->
inum
;
inode
->
i_mtime
=
inode
->
i_atime
=
inode
->
i_ctime
=
CURRENT_TIME
;
inode
->
i_flags
|=
S_IMMUTABLE
;
inode
->
i_mode
=
S_IFREG
|
S_IRUGO
;
inode
->
i_fop
=
&
ns_file_operations
;
inode
->
i_private
=
ns
;
dentry
=
d_alloc_pseudo
(
mnt
->
mnt_sb
,
&
qname
);
if
(
!
dentry
)
{
iput
(
inode
);
mntput
(
mnt
);
return
ERR_PTR
(
-
ENOMEM
);
}
d_instantiate
(
dentry
,
inode
);
dentry
->
d_fsdata
=
(
void
*
)
ns_ops
;
d
=
atomic_long_cmpxchg
(
&
ns
->
stashed
,
0
,
(
unsigned
long
)
dentry
);
if
(
d
)
{
d_delete
(
dentry
);
/* make sure ->d_prune() does nothing */
dput
(
dentry
);
cpu_relax
();
goto
again
;
}
goto
got_it
;
}
int
ns_get_name
(
char
*
buf
,
size_t
size
,
struct
task_struct
*
task
,
const
struct
proc_ns_operations
*
ns_ops
)
{
struct
ns_common
*
ns
;
int
res
=
-
ENOENT
;
ns
=
ns_ops
->
get
(
task
);
if
(
ns
)
{
res
=
snprintf
(
buf
,
size
,
"%s:[%u]"
,
ns_ops
->
name
,
ns
->
inum
);
ns_ops
->
put
(
ns
);
}
return
res
;
}
struct
file
*
proc_ns_fget
(
int
fd
)
{
struct
file
*
file
;
file
=
fget
(
fd
);
if
(
!
file
)
return
ERR_PTR
(
-
EBADF
);
if
(
file
->
f_op
!=
&
ns_file_operations
)
goto
out_invalid
;
return
file
;
out_invalid:
fput
(
file
);
return
ERR_PTR
(
-
EINVAL
);
}
static
const
struct
super_operations
nsfs_ops
=
{
.
statfs
=
simple_statfs
,
.
evict_inode
=
nsfs_evict
,
};
static
struct
dentry
*
nsfs_mount
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
void
*
data
)
{
return
mount_pseudo
(
fs_type
,
"nsfs:"
,
&
nsfs_ops
,
&
ns_dentry_operations
,
NSFS_MAGIC
);
}
static
struct
file_system_type
nsfs
=
{
.
name
=
"nsfs"
,
.
mount
=
nsfs_mount
,
.
kill_sb
=
kill_anon_super
,
};
void
__init
nsfs_init
(
void
)
{
nsfs_mnt
=
kern_mount
(
&
nsfs
);
if
(
IS_ERR
(
nsfs_mnt
))
panic
(
"can't set nsfs up
\n
"
);
nsfs_mnt
->
mnt_sb
->
s_flags
&=
~
MS_NOUSER
;
}
fs/proc/inode.c
View file @
707c5960
...
...
@@ -32,8 +32,6 @@ static void proc_evict_inode(struct inode *inode)
{
struct
proc_dir_entry
*
de
;
struct
ctl_table_header
*
head
;
const
struct
proc_ns_operations
*
ns_ops
;
void
*
ns
;
truncate_inode_pages_final
(
&
inode
->
i_data
);
clear_inode
(
inode
);
...
...
@@ -50,11 +48,6 @@ static void proc_evict_inode(struct inode *inode)
RCU_INIT_POINTER
(
PROC_I
(
inode
)
->
sysctl
,
NULL
);
sysctl_head_put
(
head
);
}
/* Release any associated namespace */
ns_ops
=
PROC_I
(
inode
)
->
ns
.
ns_ops
;
ns
=
PROC_I
(
inode
)
->
ns
.
ns
;
if
(
ns_ops
&&
ns
)
ns_ops
->
put
(
ns
);
}
static
struct
kmem_cache
*
proc_inode_cachep
;
...
...
@@ -73,8 +66,7 @@ static struct inode *proc_alloc_inode(struct super_block *sb)
ei
->
pde
=
NULL
;
ei
->
sysctl
=
NULL
;
ei
->
sysctl_entry
=
NULL
;
ei
->
ns
.
ns
=
NULL
;
ei
->
ns
.
ns_ops
=
NULL
;
ei
->
ns_ops
=
NULL
;
inode
=
&
ei
->
vfs_inode
;
inode
->
i_mtime
=
inode
->
i_atime
=
inode
->
i_ctime
=
CURRENT_TIME
;
return
inode
;
...
...
fs/proc/internal.h
View file @
707c5960
...
...
@@ -64,7 +64,7 @@ struct proc_inode {
struct
proc_dir_entry
*
pde
;
struct
ctl_table_header
*
sysctl
;
struct
ctl_table
*
sysctl_entry
;
struct
proc_ns
n
s
;
const
struct
proc_ns_operations
*
ns_op
s
;
struct
inode
vfs_inode
;
};
...
...
fs/proc/namespaces.c
View file @
707c5960
#include <linux/proc_fs.h>
#include <linux/nsproxy.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/fs_struct.h>
#include <linux/mount.h>
#include <linux/path.h>
#include <linux/namei.h>
#include <linux/file.h>
#include <linux/utsname.h>
...
...
@@ -34,138 +30,45 @@ static const struct proc_ns_operations *ns_entries[] = {
&
mntns_operations
,
};
static
const
struct
file_operations
ns_file_operations
=
{
.
llseek
=
no_llseek
,
};
static
const
struct
inode_operations
ns_inode_operations
=
{
.
setattr
=
proc_setattr
,
};
static
char
*
ns_dname
(
struct
dentry
*
dentry
,
char
*
buffer
,
int
buflen
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
const
struct
proc_ns_operations
*
ns_ops
=
PROC_I
(
inode
)
->
ns
.
ns_ops
;
return
dynamic_dname
(
dentry
,
buffer
,
buflen
,
"%s:[%lu]"
,
ns_ops
->
name
,
inode
->
i_ino
);
}
const
struct
dentry_operations
ns_dentry_operations
=
{
.
d_delete
=
always_delete_dentry
,
.
d_dname
=
ns_dname
,
};
static
struct
dentry
*
proc_ns_get_dentry
(
struct
super_block
*
sb
,
struct
task_struct
*
task
,
const
struct
proc_ns_operations
*
ns_ops
)
{
struct
dentry
*
dentry
,
*
result
;
struct
inode
*
inode
;
struct
proc_inode
*
ei
;
struct
qstr
qname
=
{
.
name
=
""
,
};
void
*
ns
;
ns
=
ns_ops
->
get
(
task
);
if
(
!
ns
)
return
ERR_PTR
(
-
ENOENT
);
dentry
=
d_alloc_pseudo
(
sb
,
&
qname
);
if
(
!
dentry
)
{
ns_ops
->
put
(
ns
);
return
ERR_PTR
(
-
ENOMEM
);
}
inode
=
iget_locked
(
sb
,
ns_ops
->
inum
(
ns
));
if
(
!
inode
)
{
dput
(
dentry
);
ns_ops
->
put
(
ns
);
return
ERR_PTR
(
-
ENOMEM
);
}
ei
=
PROC_I
(
inode
);
if
(
inode
->
i_state
&
I_NEW
)
{
inode
->
i_mtime
=
inode
->
i_atime
=
inode
->
i_ctime
=
CURRENT_TIME
;
inode
->
i_op
=
&
ns_inode_operations
;
inode
->
i_mode
=
S_IFREG
|
S_IRUGO
;
inode
->
i_fop
=
&
ns_file_operations
;
ei
->
ns
.
ns_ops
=
ns_ops
;
ei
->
ns
.
ns
=
ns
;
unlock_new_inode
(
inode
);
}
else
{
ns_ops
->
put
(
ns
);
}
d_set_d_op
(
dentry
,
&
ns_dentry_operations
);
result
=
d_instantiate_unique
(
dentry
,
inode
);
if
(
result
)
{
dput
(
dentry
);
dentry
=
result
;
}
return
dentry
;
}
static
void
*
proc_ns_follow_link
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
proc_inode
*
ei
=
PROC_I
(
inode
);
const
struct
proc_ns_operations
*
ns_ops
=
PROC_I
(
inode
)
->
ns_ops
;
struct
task_struct
*
task
;
struct
path
ns_path
;
void
*
error
=
ERR_PTR
(
-
EACCES
);
task
=
get_proc_task
(
inode
);
if
(
!
task
)
goto
out
;
return
error
;
if
(
!
ptrace_may_access
(
task
,
PTRACE_MODE_READ
))
goto
out_put_task
;
ns_path
.
dentry
=
proc_ns_get_dentry
(
sb
,
task
,
ei
->
ns
.
ns_ops
);
if
(
IS_ERR
(
ns_path
.
dentry
))
{
error
=
ERR_CAST
(
ns_path
.
dentry
);
goto
out_put_task
;
if
(
ptrace_may_access
(
task
,
PTRACE_MODE_READ
))
{
error
=
ns_get_path
(
&
ns_path
,
task
,
ns_ops
);
if
(
!
error
)
nd_jump_link
(
nd
,
&
ns_path
);
}
ns_path
.
mnt
=
mntget
(
nd
->
path
.
mnt
);
nd_jump_link
(
nd
,
&
ns_path
);
error
=
NULL
;
out_put_task:
put_task_struct
(
task
);
out:
return
error
;
}
static
int
proc_ns_readlink
(
struct
dentry
*
dentry
,
char
__user
*
buffer
,
int
buflen
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
proc_inode
*
ei
=
PROC_I
(
inode
);
const
struct
proc_ns_operations
*
ns_ops
=
ei
->
ns
.
ns_ops
;
const
struct
proc_ns_operations
*
ns_ops
=
PROC_I
(
inode
)
->
ns_ops
;
struct
task_struct
*
task
;
void
*
ns
;
char
name
[
50
];
int
res
=
-
EACCES
;
task
=
get_proc_task
(
inode
);
if
(
!
task
)
goto
out
;
if
(
!
ptrace_may_access
(
task
,
PTRACE_MODE_READ
))
goto
out_put_task
;
return
res
;
res
=
-
ENOENT
;
ns
=
ns_ops
->
get
(
task
);
if
(
!
ns
)
goto
out_put_task
;
snprintf
(
name
,
sizeof
(
name
),
"%s:[%u]"
,
ns_ops
->
name
,
ns_ops
->
inum
(
ns
));
res
=
readlink_copy
(
buffer
,
buflen
,
name
);
ns_ops
->
put
(
ns
);
out_put_task:
if
(
ptrace_may_access
(
task
,
PTRACE_MODE_READ
))
{
res
=
ns_get_name
(
name
,
sizeof
(
name
),
task
,
ns_ops
);
if
(
res
>=
0
)
res
=
readlink_copy
(
buffer
,
buflen
,
name
);
}
put_task_struct
(
task
);
out:
return
res
;
}
...
...
@@ -189,7 +92,7 @@ static int proc_ns_instantiate(struct inode *dir,
ei
=
PROC_I
(
inode
);
inode
->
i_mode
=
S_IFLNK
|
S_IRWXUGO
;
inode
->
i_op
=
&
proc_ns_link_inode_operations
;
ei
->
ns
.
ns
_ops
=
ns_ops
;
ei
->
ns_ops
=
ns_ops
;
d_set_d_op
(
dentry
,
&
pid_dentry_operations
);
d_add
(
dentry
,
inode
);
...
...
@@ -267,31 +170,3 @@ const struct inode_operations proc_ns_dir_inode_operations = {
.
getattr
=
pid_getattr
,
.
setattr
=
proc_setattr
,
};
struct
file
*
proc_ns_fget
(
int
fd
)
{
struct
file
*
file
;
file
=
fget
(
fd
);
if
(
!
file
)
return
ERR_PTR
(
-
EBADF
);
if
(
file
->
f_op
!=
&
ns_file_operations
)
goto
out_invalid
;
return
file
;
out_invalid:
fput
(
file
);
return
ERR_PTR
(
-
EINVAL
);
}
struct
proc_ns
*
get_proc_ns
(
struct
inode
*
inode
)
{
return
&
PROC_I
(
inode
)
->
ns
;
}
bool
proc_ns_inode
(
struct
inode
*
inode
)
{
return
inode
->
i_fop
==
&
ns_file_operations
;
}
include/linux/ipc_namespace.h
View file @
707c5960
...
...
@@ -6,6 +6,7 @@
#include <linux/rwsem.h>
#include <linux/notifier.h>
#include <linux/nsproxy.h>
#include <linux/ns_common.h>
/*
* ipc namespace events
...
...
@@ -68,7 +69,7 @@ struct ipc_namespace {
/* user_ns which owns the ipc ns */
struct
user_namespace
*
user_ns
;
unsigned
int
proc_inum
;
struct
ns_common
ns
;
};
extern
struct
ipc_namespace
init_ipc_ns
;
...
...
include/linux/ns_common.h
0 → 100644
View file @
707c5960
#ifndef _LINUX_NS_COMMON_H
#define _LINUX_NS_COMMON_H
struct
proc_ns_operations
;
struct
ns_common
{
atomic_long_t
stashed
;
const
struct
proc_ns_operations
*
ops
;
unsigned
int
inum
;
};
#endif
include/linux/pid_namespace.h
View file @
707c5960
...
...
@@ -8,6 +8,7 @@
#include <linux/threads.h>
#include <linux/nsproxy.h>
#include <linux/kref.h>
#include <linux/ns_common.h>
struct
pidmap
{
atomic_t
nr_free
;
...
...
@@ -43,7 +44,7 @@ struct pid_namespace {
kgid_t
pid_gid
;
int
hide_pid
;
int
reboot
;
/* group exit code if this pidns was rebooted */
unsigned
int
proc_inum
;
struct
ns_common
ns
;
};
extern
struct
pid_namespace
init_pid_ns
;
...
...
include/linux/proc_ns.h
View file @
707c5960
...
...
@@ -4,21 +4,18 @@
#ifndef _LINUX_PROC_NS_H
#define _LINUX_PROC_NS_H
#include <linux/ns_common.h>
struct
pid_namespace
;
struct
nsproxy
;
struct
path
;
struct
proc_ns_operations
{
const
char
*
name
;
int
type
;
void
*
(
*
get
)(
struct
task_struct
*
task
);
void
(
*
put
)(
void
*
ns
);
int
(
*
install
)(
struct
nsproxy
*
nsproxy
,
void
*
ns
);
unsigned
int
(
*
inum
)(
void
*
ns
);
};
struct
proc_ns
{
void
*
ns
;
const
struct
proc_ns_operations
*
ns_ops
;
struct
ns_common
*
(
*
get
)(
struct
task_struct
*
task
);
void
(
*
put
)(
struct
ns_common
*
ns
);
int
(
*
install
)(
struct
nsproxy
*
nsproxy
,
struct
ns_common
*
ns
);
};
extern
const
struct
proc_ns_operations
netns_operations
;
...
...
@@ -43,32 +40,38 @@ enum {
extern
int
pid_ns_prepare_proc
(
struct
pid_namespace
*
ns
);
extern
void
pid_ns_release_proc
(
struct
pid_namespace
*
ns
);
extern
struct
file
*
proc_ns_fget
(
int
fd
);
extern
struct
proc_ns
*
get_proc_ns
(
struct
inode
*
);
extern
int
proc_alloc_inum
(
unsigned
int
*
pino
);
extern
void
proc_free_inum
(
unsigned
int
inum
);
extern
bool
proc_ns_inode
(
struct
inode
*
inode
);
#else
/* CONFIG_PROC_FS */
static
inline
int
pid_ns_prepare_proc
(
struct
pid_namespace
*
ns
)
{
return
0
;
}
static
inline
void
pid_ns_release_proc
(
struct
pid_namespace
*
ns
)
{}
static
inline
struct
file
*
proc_ns_fget
(
int
fd
)
{
return
ERR_PTR
(
-
EINVAL
);
}
static
inline
struct
proc_ns
*
get_proc_ns
(
struct
inode
*
inode
)
{
return
NULL
;
}
static
inline
int
proc_alloc_inum
(
unsigned
int
*
inum
)
{
*
inum
=
1
;
return
0
;
}
static
inline
void
proc_free_inum
(
unsigned
int
inum
)
{}
static
inline
bool
proc_ns_inode
(
struct
inode
*
inode
)
{
return
false
;
}
#endif
/* CONFIG_PROC_FS */
static
inline
int
ns_alloc_inum
(
struct
ns_common
*
ns
)
{
atomic_long_set
(
&
ns
->
stashed
,
0
);
return
proc_alloc_inum
(
&
ns
->
inum
);
}
#define ns_free_inum(ns) proc_free_inum((ns)->inum)
extern
struct
file
*
proc_ns_fget
(
int
fd
);
#define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
extern
void
*
ns_get_path
(
struct
path
*
path
,
struct
task_struct
*
task
,
const
struct
proc_ns_operations
*
ns_ops
);
extern
int
ns_get_name
(
char
*
buf
,
size_t
size
,
struct
task_struct
*
task
,
const
struct
proc_ns_operations
*
ns_ops
);
extern
void
nsfs_init
(
void
);
#endif
/* _LINUX_PROC_NS_H */
include/linux/user_namespace.h
View file @
707c5960
...
...
@@ -3,6 +3,7 @@
#include <linux/kref.h>
#include <linux/nsproxy.h>
#include <linux/ns_common.h>
#include <linux/sched.h>
#include <linux/err.h>
...
...
@@ -26,7 +27,7 @@ struct user_namespace {
int
level
;
kuid_t
owner
;
kgid_t
group
;
unsigned
int
proc_inum
;
struct
ns_common
ns
;
/* Register of per-UID persistent keyrings for this namespace */
#ifdef CONFIG_PERSISTENT_KEYRINGS
...
...
include/linux/utsname.h
View file @
707c5960
...
...
@@ -5,6 +5,7 @@
#include <linux/sched.h>
#include <linux/kref.h>
#include <linux/nsproxy.h>
#include <linux/ns_common.h>
#include <linux/err.h>
#include <uapi/linux/utsname.h>
...
...
@@ -23,7 +24,7 @@ struct uts_namespace {
struct
kref
kref
;
struct
new_utsname
name
;
struct
user_namespace
*
user_ns
;
unsigned
int
proc_inum
;
struct
ns_common
ns
;
};
extern
struct
uts_namespace
init_uts_ns
;
...
...
include/net/net_namespace.h
View file @
707c5960
...
...
@@ -26,6 +26,7 @@
#endif
#include <net/netns/nftables.h>
#include <net/netns/xfrm.h>
#include <linux/ns_common.h>
struct
user_namespace
;
struct
proc_dir_entry
;
...
...
@@ -60,7 +61,7 @@ struct net {
struct
user_namespace
*
user_ns
;
/* Owning user namespace */
unsigned
int
proc_inum
;
struct
ns_common
ns
;
struct
proc_dir_entry
*
proc_net
;
struct
proc_dir_entry
*
proc_net_stat
;
...
...
include/uapi/linux/magic.h
View file @
707c5960
...
...
@@ -72,5 +72,6 @@
#define MTD_INODE_FS_MAGIC 0x11307854
#define ANON_INODE_FS_MAGIC 0x09041934
#define BTRFS_TEST_MAGIC 0x73727279
#define NSFS_MAGIC 0x6e736673
#endif
/* __LINUX_MAGIC_H__ */
init/main.c
View file @
707c5960
...
...
@@ -78,6 +78,7 @@
#include <linux/context_tracking.h>
#include <linux/random.h>
#include <linux/list.h>
#include <linux/proc_ns.h>
#include <asm/io.h>
#include <asm/bugs.h>
...
...
@@ -660,6 +661,7 @@ asmlinkage __visible void __init start_kernel(void)
/* rootfs populating might need page-writeback */
page_writeback_init
();
proc_root_init
();
nsfs_init
();
cgroup_init
();
cpuset_init
();
taskstats_init_early
();
...
...
init/version.c
View file @
707c5960
...
...
@@ -35,7 +35,10 @@ struct uts_namespace init_uts_ns = {
.
domainname
=
UTS_DOMAINNAME
,
},
.
user_ns
=
&
init_user_ns
,
.
proc_inum
=
PROC_UTS_INIT_INO
,
.
ns
.
inum
=
PROC_UTS_INIT_INO
,
#ifdef CONFIG_UTS_NS
.
ns
.
ops
=
&
utsns_operations
,
#endif
};
EXPORT_SYMBOL_GPL
(
init_uts_ns
);
...
...
ipc/msgutil.c
View file @
707c5960
...
...
@@ -31,7 +31,10 @@ DEFINE_SPINLOCK(mq_lock);
struct
ipc_namespace
init_ipc_ns
=
{
.
count
=
ATOMIC_INIT
(
1
),
.
user_ns
=
&
init_user_ns
,
.
proc_inum
=
PROC_IPC_INIT_INO
,
.
ns
.
inum
=
PROC_IPC_INIT_INO
,
#ifdef CONFIG_IPC_NS
.
ns
.
ops
=
&
ipcns_operations
,
#endif
};
atomic_t
nr_ipc_ns
=
ATOMIC_INIT
(
1
);
...
...
ipc/namespace.c
View file @
707c5960
...
...
@@ -26,16 +26,17 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
if
(
ns
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
err
=
proc_alloc_inum
(
&
ns
->
proc_inum
);
err
=
ns_alloc_inum
(
&
ns
->
ns
);
if
(
err
)
{
kfree
(
ns
);
return
ERR_PTR
(
err
);
}
ns
->
ns
.
ops
=
&
ipcns_operations
;
atomic_set
(
&
ns
->
count
,
1
);
err
=
mq_init_ns
(
ns
);
if
(
err
)
{
proc_free_inum
(
ns
->
proc_inum
);
ns_free_inum
(
&
ns
->
ns
);
kfree
(
ns
);
return
ERR_PTR
(
err
);
}
...
...
@@ -119,7 +120,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
*/
ipcns_notify
(
IPCNS_REMOVED
);
put_user_ns
(
ns
->
user_ns
);
proc_free_inum
(
ns
->
proc_inum
);
ns_free_inum
(
&
ns
->
ns
);
kfree
(
ns
);
}
...
...
@@ -149,7 +150,12 @@ void put_ipc_ns(struct ipc_namespace *ns)
}
}
static
void
*
ipcns_get
(
struct
task_struct
*
task
)
static
inline
struct
ipc_namespace
*
to_ipc_ns
(
struct
ns_common
*
ns
)
{
return
container_of
(
ns
,
struct
ipc_namespace
,
ns
);
}
static
struct
ns_common
*
ipcns_get
(
struct
task_struct
*
task
)
{
struct
ipc_namespace
*
ns
=
NULL
;
struct
nsproxy
*
nsproxy
;
...
...
@@ -160,17 +166,17 @@ static void *ipcns_get(struct task_struct *task)
ns
=
get_ipc_ns
(
nsproxy
->
ipc_ns
);
task_unlock
(
task
);
return
ns
;
return
ns
?
&
ns
->
ns
:
NULL
;
}
static
void
ipcns_put
(
void
*
ns
)
static
void
ipcns_put
(
struct
ns_common
*
ns
)
{
return
put_ipc_ns
(
ns
);
return
put_ipc_ns
(
to_ipc_ns
(
ns
)
);
}
static
int
ipcns_install
(
struct
nsproxy
*
nsproxy
,
void
*
new
)
static
int
ipcns_install
(
struct
nsproxy
*
nsproxy
,
struct
ns_common
*
new
)
{
struct
ipc_namespace
*
ns
=
new
;
struct
ipc_namespace
*
ns
=
to_ipc_ns
(
new
)
;
if
(
!
ns_capable
(
ns
->
user_ns
,
CAP_SYS_ADMIN
)
||
!
ns_capable
(
current_user_ns
(),
CAP_SYS_ADMIN
))
return
-
EPERM
;
...
...
@@ -182,18 +188,10 @@ static int ipcns_install(struct nsproxy *nsproxy, void *new)
return
0
;
}
static
unsigned
int
ipcns_inum
(
void
*
vp
)
{
struct
ipc_namespace
*
ns
=
vp
;
return
ns
->
proc_inum
;
}
const
struct
proc_ns_operations
ipcns_operations
=
{
.
name
=
"ipc"
,
.
type
=
CLONE_NEWIPC
,
.
get
=
ipcns_get
,
.
put
=
ipcns_put
,
.
install
=
ipcns_install
,
.
inum
=
ipcns_inum
,
};
kernel/nsproxy.c
View file @
707c5960
...
...
@@ -220,11 +220,10 @@ void exit_task_namespaces(struct task_struct *p)
SYSCALL_DEFINE2
(
setns
,
int
,
fd
,
int
,
nstype
)
{
const
struct
proc_ns_operations
*
ops
;
struct
task_struct
*
tsk
=
current
;
struct
nsproxy
*
new_nsproxy
;
struct
proc_ns
*
ei
;
struct
file
*
file
;
struct
ns_common
*
ns
;
int
err
;
file
=
proc_ns_fget
(
fd
);
...
...
@@ -232,9 +231,8 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
return
PTR_ERR
(
file
);
err
=
-
EINVAL
;
ei
=
get_proc_ns
(
file_inode
(
file
));
ops
=
ei
->
ns_ops
;
if
(
nstype
&&
(
ops
->
type
!=
nstype
))
ns
=
get_proc_ns
(
file_inode
(
file
));
if
(
nstype
&&
(
ns
->
ops
->
type
!=
nstype
))
goto
out
;
new_nsproxy
=
create_new_namespaces
(
0
,
tsk
,
current_user_ns
(),
tsk
->
fs
);
...
...
@@ -243,7 +241,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
goto
out
;
}
err
=
ops
->
install
(
new_nsproxy
,
ei
->
ns
);
err
=
ns
->
ops
->
install
(
new_nsproxy
,
ns
);
if
(
err
)
{
free_nsproxy
(
new_nsproxy
);
goto
out
;
...
...
kernel/pid.c
View file @
707c5960
...
...
@@ -79,7 +79,10 @@ struct pid_namespace init_pid_ns = {
.
level
=
0
,
.
child_reaper
=
&
init_task
,
.
user_ns
=
&
init_user_ns
,
.
proc_inum
=
PROC_PID_INIT_INO
,
.
ns
.
inum
=
PROC_PID_INIT_INO
,
#ifdef CONFIG_PID_NS
.
ns
.
ops
=
&
pidns_operations
,
#endif
};
EXPORT_SYMBOL_GPL
(
init_pid_ns
);
...
...
kernel/pid_namespace.c
View file @
707c5960
...
...
@@ -105,9 +105,10 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
if
(
ns
->
pid_cachep
==
NULL
)
goto
out_free_map
;
err
=
proc_alloc_inum
(
&
ns
->
proc_inum
);
err
=
ns_alloc_inum
(
&
ns
->
ns
);
if
(
err
)
goto
out_free_map
;
ns
->
ns
.
ops
=
&
pidns_operations
;
kref_init
(
&
ns
->
kref
);
ns
->
level
=
level
;
...
...
@@ -142,7 +143,7 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
{
int
i
;
proc_free_inum
(
ns
->
proc_inum
);
ns_free_inum
(
&
ns
->
ns
);
for
(
i
=
0
;
i
<
PIDMAP_ENTRIES
;
i
++
)
kfree
(
ns
->
pidmap
[
i
].
page
);
put_user_ns
(
ns
->
user_ns
);
...
...
@@ -313,7 +314,12 @@ int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
return
0
;
}
static
void
*
pidns_get
(
struct
task_struct
*
task
)
static
inline
struct
pid_namespace
*
to_pid_ns
(
struct
ns_common
*
ns
)
{
return
container_of
(
ns
,
struct
pid_namespace
,
ns
);
}
static
struct
ns_common
*
pidns_get
(
struct
task_struct
*
task
)
{
struct
pid_namespace
*
ns
;
...
...
@@ -323,18 +329,18 @@ static void *pidns_get(struct task_struct *task)
get_pid_ns
(
ns
);
rcu_read_unlock
();
return
ns
;
return
ns
?
&
ns
->
ns
:
NULL
;
}
static
void
pidns_put
(
void
*
ns
)
static
void
pidns_put
(
struct
ns_common
*
ns
)
{
put_pid_ns
(
ns
);
put_pid_ns
(
to_pid_ns
(
ns
)
);
}
static
int
pidns_install
(
struct
nsproxy
*
nsproxy
,
void
*
ns
)
static
int
pidns_install
(
struct
nsproxy
*
nsproxy
,
struct
ns_common
*
ns
)
{
struct
pid_namespace
*
active
=
task_active_pid_ns
(
current
);
struct
pid_namespace
*
ancestor
,
*
new
=
ns
;
struct
pid_namespace
*
ancestor
,
*
new
=
to_pid_ns
(
ns
)
;
if
(
!
ns_capable
(
new
->
user_ns
,
CAP_SYS_ADMIN
)
||
!
ns_capable
(
current_user_ns
(),
CAP_SYS_ADMIN
))
...
...
@@ -362,19 +368,12 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns)
return
0
;
}
static
unsigned
int
pidns_inum
(
void
*
ns
)
{
struct
pid_namespace
*
pid_ns
=
ns
;
return
pid_ns
->
proc_inum
;
}
const
struct
proc_ns_operations
pidns_operations
=
{
.
name
=
"pid"
,
.
type
=
CLONE_NEWPID
,
.
get
=
pidns_get
,
.
put
=
pidns_put
,
.
install
=
pidns_install
,
.
inum
=
pidns_inum
,
};
static
__init
int
pid_namespaces_init
(
void
)
...
...
kernel/user.c
View file @
707c5960
...
...
@@ -50,7 +50,10 @@ struct user_namespace init_user_ns = {
.
count
=
ATOMIC_INIT
(
3
),
.
owner
=
GLOBAL_ROOT_UID
,
.
group
=
GLOBAL_ROOT_GID
,
.
proc_inum
=
PROC_USER_INIT_INO
,
.
ns
.
inum
=
PROC_USER_INIT_INO
,
#ifdef CONFIG_USER_NS
.
ns
.
ops
=
&
userns_operations
,
#endif
#ifdef CONFIG_PERSISTENT_KEYRINGS
.
persistent_keyring_register_sem
=
__RWSEM_INITIALIZER
(
init_user_ns
.
persistent_keyring_register_sem
),
...
...
kernel/user_namespace.c
View file @
707c5960
...
...
@@ -86,11 +86,12 @@ int create_user_ns(struct cred *new)
if
(
!
ns
)
return
-
ENOMEM
;
ret
=
proc_alloc_inum
(
&
ns
->
proc_inum
);
ret
=
ns_alloc_inum
(
&
ns
->
ns
);
if
(
ret
)
{
kmem_cache_free
(
user_ns_cachep
,
ns
);
return
ret
;
}
ns
->
ns
.
ops
=
&
userns_operations
;
atomic_set
(
&
ns
->
count
,
1
);
/* Leave the new->user_ns reference with the new user namespace. */
...
...
@@ -136,7 +137,7 @@ void free_user_ns(struct user_namespace *ns)
#ifdef CONFIG_PERSISTENT_KEYRINGS
key_put
(
ns
->
persistent_keyring_register
);
#endif
proc_free_inum
(
ns
->
proc_inum
);
ns_free_inum
(
&
ns
->
ns
);
kmem_cache_free
(
user_ns_cachep
,
ns
);
ns
=
parent
;
}
while
(
atomic_dec_and_test
(
&
parent
->
count
));
...
...
@@ -841,7 +842,12 @@ static bool new_idmap_permitted(const struct file *file,
return
false
;
}
static
void
*
userns_get
(
struct
task_struct
*
task
)
static
inline
struct
user_namespace
*
to_user_ns
(
struct
ns_common
*
ns
)
{
return
container_of
(
ns
,
struct
user_namespace
,
ns
);
}
static
struct
ns_common
*
userns_get
(
struct
task_struct
*
task
)
{
struct
user_namespace
*
user_ns
;
...
...
@@ -849,17 +855,17 @@ static void *userns_get(struct task_struct *task)
user_ns
=
get_user_ns
(
__task_cred
(
task
)
->
user_ns
);
rcu_read_unlock
();
return
user_ns
;
return
user_ns
?
&
user_ns
->
ns
:
NULL
;
}
static
void
userns_put
(
void
*
ns
)
static
void
userns_put
(
struct
ns_common
*
ns
)
{
put_user_ns
(
ns
);
put_user_ns
(
to_user_ns
(
ns
)
);
}
static
int
userns_install
(
struct
nsproxy
*
nsproxy
,
void
*
ns
)
static
int
userns_install
(
struct
nsproxy
*
nsproxy
,
struct
ns_common
*
ns
)
{
struct
user_namespace
*
user_ns
=
ns
;
struct
user_namespace
*
user_ns
=
to_user_ns
(
ns
)
;
struct
cred
*
cred
;
/* Don't allow gaining capabilities by reentering
...
...
@@ -888,19 +894,12 @@ static int userns_install(struct nsproxy *nsproxy, void *ns)
return
commit_creds
(
cred
);
}
static
unsigned
int
userns_inum
(
void
*
ns
)
{
struct
user_namespace
*
user_ns
=
ns
;
return
user_ns
->
proc_inum
;
}
const
struct
proc_ns_operations
userns_operations
=
{
.
name
=
"user"
,
.
type
=
CLONE_NEWUSER
,
.
get
=
userns_get
,
.
put
=
userns_put
,
.
install
=
userns_install
,
.
inum
=
userns_inum
,
};
static
__init
int
user_namespaces_init
(
void
)
...
...
kernel/utsname.c
View file @
707c5960
...
...
@@ -42,12 +42,14 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
if
(
!
ns
)
return
ERR_PTR
(
-
ENOMEM
);
err
=
proc_alloc_inum
(
&
ns
->
proc_inum
);
err
=
ns_alloc_inum
(
&
ns
->
ns
);
if
(
err
)
{
kfree
(
ns
);
return
ERR_PTR
(
err
);
}
ns
->
ns
.
ops
=
&
utsns_operations
;
down_read
(
&
uts_sem
);
memcpy
(
&
ns
->
name
,
&
old_ns
->
name
,
sizeof
(
ns
->
name
));
ns
->
user_ns
=
get_user_ns
(
user_ns
);
...
...
@@ -84,11 +86,16 @@ void free_uts_ns(struct kref *kref)
ns
=
container_of
(
kref
,
struct
uts_namespace
,
kref
);
put_user_ns
(
ns
->
user_ns
);
proc_free_inum
(
ns
->
proc_inum
);
ns_free_inum
(
&
ns
->
ns
);
kfree
(
ns
);
}
static
void
*
utsns_get
(
struct
task_struct
*
task
)
static
inline
struct
uts_namespace
*
to_uts_ns
(
struct
ns_common
*
ns
)
{
return
container_of
(
ns
,
struct
uts_namespace
,
ns
);
}
static
struct
ns_common
*
utsns_get
(
struct
task_struct
*
task
)
{
struct
uts_namespace
*
ns
=
NULL
;
struct
nsproxy
*
nsproxy
;
...
...
@@ -101,17 +108,17 @@ static void *utsns_get(struct task_struct *task)
}
task_unlock
(
task
);
return
ns
;
return
ns
?
&
ns
->
ns
:
NULL
;
}
static
void
utsns_put
(
void
*
ns
)
static
void
utsns_put
(
struct
ns_common
*
ns
)
{
put_uts_ns
(
ns
);
put_uts_ns
(
to_uts_ns
(
ns
)
);
}
static
int
utsns_install
(
struct
nsproxy
*
nsproxy
,
void
*
new
)
static
int
utsns_install
(
struct
nsproxy
*
nsproxy
,
struct
ns_common
*
new
)
{
struct
uts_namespace
*
ns
=
new
;
struct
uts_namespace
*
ns
=
to_uts_ns
(
new
)
;
if
(
!
ns_capable
(
ns
->
user_ns
,
CAP_SYS_ADMIN
)
||
!
ns_capable
(
current_user_ns
(),
CAP_SYS_ADMIN
))
...
...
@@ -123,18 +130,10 @@ static int utsns_install(struct nsproxy *nsproxy, void *new)
return
0
;
}
static
unsigned
int
utsns_inum
(
void
*
vp
)
{
struct
uts_namespace
*
ns
=
vp
;
return
ns
->
proc_inum
;
}
const
struct
proc_ns_operations
utsns_operations
=
{
.
name
=
"uts"
,
.
type
=
CLONE_NEWUTS
,
.
get
=
utsns_get
,
.
put
=
utsns_put
,
.
install
=
utsns_install
,
.
inum
=
utsns_inum
,
};
net/core/net_namespace.c
View file @
707c5960
...
...
@@ -337,17 +337,17 @@ EXPORT_SYMBOL_GPL(__put_net);
struct
net
*
get_net_ns_by_fd
(
int
fd
)
{
struct
proc_ns
*
ei
;
struct
file
*
file
;
struct
ns_common
*
ns
;
struct
net
*
net
;
file
=
proc_ns_fget
(
fd
);
if
(
IS_ERR
(
file
))
return
ERR_CAST
(
file
);
ei
=
get_proc_ns
(
file_inode
(
file
));
if
(
ei
->
ns_
ops
==
&
netns_operations
)
net
=
get_net
(
ei
->
ns
);
ns
=
get_proc_ns
(
file_inode
(
file
));
if
(
ns
->
ops
==
&
netns_operations
)
net
=
get_net
(
container_of
(
ns
,
struct
net
,
ns
)
);
else
net
=
ERR_PTR
(
-
EINVAL
);
...
...
@@ -386,12 +386,15 @@ EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
static
__net_init
int
net_ns_net_init
(
struct
net
*
net
)
{
return
proc_alloc_inum
(
&
net
->
proc_inum
);
#ifdef CONFIG_NET_NS
net
->
ns
.
ops
=
&
netns_operations
;
#endif
return
ns_alloc_inum
(
&
net
->
ns
);
}
static
__net_exit
void
net_ns_net_exit
(
struct
net
*
net
)
{
proc_free_inum
(
net
->
proc_inum
);
ns_free_inum
(
&
net
->
ns
);
}
static
struct
pernet_operations
__net_initdata
net_ns_ops
=
{
...
...
@@ -629,7 +632,7 @@ void unregister_pernet_device(struct pernet_operations *ops)
EXPORT_SYMBOL_GPL
(
unregister_pernet_device
);
#ifdef CONFIG_NET_NS
static
void
*
netns_get
(
struct
task_struct
*
task
)
static
struct
ns_common
*
netns_get
(
struct
task_struct
*
task
)
{
struct
net
*
net
=
NULL
;
struct
nsproxy
*
nsproxy
;
...
...
@@ -640,17 +643,22 @@ static void *netns_get(struct task_struct *task)
net
=
get_net
(
nsproxy
->
net_ns
);
task_unlock
(
task
);
return
net
;
return
net
?
&
net
->
ns
:
NULL
;
}
static
void
netns_put
(
void
*
ns
)
static
inline
struct
net
*
to_net_ns
(
struct
ns_common
*
ns
)
{
put_net
(
ns
);
return
container_of
(
ns
,
struct
net
,
ns
);
}
static
int
netns_install
(
struct
nsproxy
*
nsproxy
,
void
*
ns
)
static
void
netns_put
(
struct
ns_common
*
ns
)
{
struct
net
*
net
=
ns
;
put_net
(
to_net_ns
(
ns
));
}
static
int
netns_install
(
struct
nsproxy
*
nsproxy
,
struct
ns_common
*
ns
)
{
struct
net
*
net
=
to_net_ns
(
ns
);
if
(
!
ns_capable
(
net
->
user_ns
,
CAP_SYS_ADMIN
)
||
!
ns_capable
(
current_user_ns
(),
CAP_SYS_ADMIN
))
...
...
@@ -661,18 +669,11 @@ static int netns_install(struct nsproxy *nsproxy, void *ns)
return
0
;
}
static
unsigned
int
netns_inum
(
void
*
ns
)
{
struct
net
*
net
=
ns
;
return
net
->
proc_inum
;
}
const
struct
proc_ns_operations
netns_operations
=
{
.
name
=
"net"
,
.
type
=
CLONE_NEWNET
,
.
get
=
netns_get
,
.
put
=
netns_put
,
.
install
=
netns_install
,
.
inum
=
netns_inum
,
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment