Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
7faa7f52
Commit
7faa7f52
authored
Nov 25, 2013
by
hallyn
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #92 from majek/share-namespaces
Add options to `lxc-start` to inherit network, ipc and uts namespaces
parents
5266cf0a
304dc8b3
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
274 additions
and
26 deletions
+274
-26
lxc-start.sgml.in
doc/lxc-start.sgml.in
+45
-0
arguments.h
src/lxc/arguments.h
+3
-0
conf.c
src/lxc/conf.c
+8
-3
conf.h
src/lxc/conf.h
+2
-0
lxc_start.c
src/lxc/lxc_start.c
+75
-1
start.c
src/lxc/start.c
+123
-22
start.h
src/lxc/start.h
+18
-0
No files found.
doc/lxc-start.sgml.in
View file @
7faa7f52
...
...
@@ -57,6 +57,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<arg choice="opt">-p <replaceable>pid_file</replaceable></arg>
<arg choice="opt">-s KEY=VAL</arg>
<arg choice="opt">-C</arg>
<arg choice="opt">--share-[net|ipc|uts] <replaceable>name|pid</replaceable></arg>
<arg choice="opt">command</arg>
</cmdsynopsis>
</refsynopsisdiv>
...
...
@@ -186,6 +187,50 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--share-net <replaceable>name|pid</replaceable></option>
</term>
<listitem>
<para>
Inherit a network namespace from
a <replaceable>name</replaceable> container or
a <replaceable>pid</replaceable>. The network namespace
will continue to be managed by the original owner. The
network configuration of the starting container is ignored
and the up/down scripts won't be executed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--share-ipc <replaceable>name|pid</replaceable></option>
</term>
<listitem>
<para>
Inherit an IPC namespace from
a <replaceable>name</replaceable> container or
a <replaceable>pid</replaceable>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--share-uts <replaceable>name|pid</replaceable></option>
</term>
<listitem>
<para>
Inherit a UTS namespace from
a <replaceable>name</replaceable> container or
a <replaceable>pid</replaceable>. The starting LXC will
not set the hostname, but the container OS may do it
anyway.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
...
...
src/lxc/arguments.h
View file @
7faa7f52
...
...
@@ -53,6 +53,9 @@ struct lxc_arguments {
/* set to 0 to accept only 1 lxcpath, -1 for unlimited */
int
lxcpath_additional
;
/* for lxc-start */
const
char
*
share_ns
[
32
];
// size must be greater than LXC_NS_MAX
/* for lxc-checkpoint/restart */
const
char
*
statefile
;
int
statefd
;
...
...
src/lxc/conf.c
View file @
7faa7f52
...
...
@@ -2630,6 +2630,9 @@ struct lxc_conf *lxc_conf_init(void)
new
->
lsm_se_context
=
NULL
;
new
->
lsm_umount_proc
=
0
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
new
->
inherit_ns_fd
[
i
]
=
-
1
;
return
new
;
}
...
...
@@ -3461,9 +3464,11 @@ int check_autodev( const char *rootfs, void *data )
int
lxc_setup
(
const
char
*
name
,
struct
lxc_conf
*
lxc_conf
,
const
char
*
lxcpath
,
struct
cgroup_process_info
*
cgroup_info
,
void
*
data
)
{
if
(
setup_utsname
(
lxc_conf
->
utsname
))
{
ERROR
(
"failed to setup the utsname for '%s'"
,
name
);
return
-
1
;
if
(
lxc_conf
->
inherit_ns_fd
[
LXC_NS_UTS
]
==
-
1
)
{
if
(
setup_utsname
(
lxc_conf
->
utsname
))
{
ERROR
(
"failed to setup the utsname for '%s'"
,
name
);
return
-
1
;
}
}
if
(
setup_network
(
&
lxc_conf
->
network
))
{
...
...
src/lxc/conf.h
View file @
7faa7f52
...
...
@@ -320,6 +320,8 @@ struct lxc_conf {
// store the config file specified values here.
char
*
logfile
;
// the logfile as specifed in config
int
loglevel
;
// loglevel as specifed in config (if any)
int
inherit_ns_fd
[
LXC_NS_MAX
];
};
int
run_lxc_hooks
(
const
char
*
name
,
char
*
hook
,
struct
lxc_conf
*
conf
,
...
...
src/lxc/lxc_start.c
View file @
7faa7f52
...
...
@@ -51,6 +51,10 @@
#include "confile.h"
#include "arguments.h"
#define OPT_SHARE_NET OPT_USAGE+1
#define OPT_SHARE_IPC OPT_USAGE+2
#define OPT_SHARE_UTS OPT_USAGE+3
lxc_log_define
(
lxc_start_ui
,
lxc_start
);
static
struct
lxc_list
defines
;
...
...
@@ -91,6 +95,53 @@ err:
return
err
;
}
static
int
pid_from_lxcname
(
const
char
*
lxcname_or_pid
,
const
char
*
lxcpath
)
{
char
*
eptr
;
int
pid
=
strtol
(
lxcname_or_pid
,
&
eptr
,
10
);
if
(
*
eptr
!=
'\0'
||
pid
<
1
)
{
struct
lxc_container
*
s
;
s
=
lxc_container_new
(
lxcname_or_pid
,
lxcpath
);
if
(
!
s
)
{
SYSERROR
(
"'%s' is not a valid pid nor a container name"
,
lxcname_or_pid
);
return
-
1
;
}
if
(
!
s
->
may_control
(
s
))
{
SYSERROR
(
"Insufficient privileges to control container '%s'"
,
s
->
name
);
lxc_container_put
(
s
);
return
-
1
;
}
pid
=
s
->
init_pid
(
s
);
if
(
pid
<
1
)
{
SYSERROR
(
"Is container '%s' running?"
,
s
->
name
);
lxc_container_put
(
s
);
return
-
1
;
}
lxc_container_put
(
s
);
}
if
(
kill
(
pid
,
0
)
<
0
)
{
SYSERROR
(
"Can't send signal to pid %d"
,
pid
);
return
-
1
;
}
return
pid
;
}
static
int
open_ns
(
int
pid
,
const
char
*
ns_proc_name
)
{
int
fd
;
char
path
[
MAXPATHLEN
];
snprintf
(
path
,
MAXPATHLEN
,
"/proc/%d/ns/%s"
,
pid
,
ns_proc_name
);
fd
=
open
(
path
,
O_RDONLY
);
if
(
fd
<
0
)
{
SYSERROR
(
"failed to open %s"
,
path
);
return
-
1
;
}
return
fd
;
}
static
int
my_parser
(
struct
lxc_arguments
*
args
,
int
c
,
char
*
arg
)
{
switch
(
c
)
{
...
...
@@ -101,6 +152,9 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
case
'C'
:
args
->
close_all_fds
=
1
;
break
;
case
's'
:
return
lxc_config_define_add
(
&
defines
,
arg
);
case
'p'
:
args
->
pidfile
=
arg
;
break
;
case
OPT_SHARE_NET
:
args
->
share_ns
[
LXC_NS_NET
]
=
arg
;
break
;
case
OPT_SHARE_IPC
:
args
->
share_ns
[
LXC_NS_IPC
]
=
arg
;
break
;
case
OPT_SHARE_UTS
:
args
->
share_ns
[
LXC_NS_UTS
]
=
arg
;
break
;
}
return
0
;
}
...
...
@@ -113,6 +167,9 @@ static const struct option my_longopts[] = {
{
"console-log"
,
required_argument
,
0
,
'L'
},
{
"close-all-fds"
,
no_argument
,
0
,
'C'
},
{
"pidfile"
,
required_argument
,
0
,
'p'
},
{
"share-net"
,
required_argument
,
0
,
OPT_SHARE_NET
},
{
"share-ipc"
,
required_argument
,
0
,
OPT_SHARE_IPC
},
{
"share-uts"
,
required_argument
,
0
,
OPT_SHARE_UTS
},
LXC_COMMON_OPTIONS
};
...
...
@@ -133,7 +190,9 @@ Options :\n\
-C, --close-all-fds If any fds are inherited, close them
\n
\
If not specified, exit with failure instead
\n
\
Note: --daemon implies --close-all-fds
\n
\
-s, --define KEY=VAL Assign VAL to configuration variable KEY
\n
"
,
-s, --define KEY=VAL Assign VAL to configuration variable KEY
\n
\
--share-[net|ipc|uts]=NAME Share a namespace with another container or pid
\n
\
"
,
.
options
=
my_longopts
,
.
parser
=
my_parser
,
.
checker
=
NULL
,
...
...
@@ -250,6 +309,21 @@ int main(int argc, char *argv[])
}
}
int
i
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
(
my_args
.
share_ns
[
i
]
==
NULL
)
continue
;
int
pid
=
pid_from_lxcname
(
my_args
.
share_ns
[
i
],
lxcpath
);
if
(
pid
<
1
)
goto
out
;
int
fd
=
open_ns
(
pid
,
ns_info
[
i
].
proc_name
);
if
(
fd
<
0
)
goto
out
;
conf
->
inherit_ns_fd
[
i
]
=
fd
;
}
if
(
my_args
.
daemonize
)
{
c
->
want_daemonize
(
c
);
}
...
...
src/lxc/start.c
View file @
7faa7f52
...
...
@@ -75,6 +75,78 @@
lxc_log_define
(
lxc_start
,
lxc
);
const
struct
ns_info
ns_info
[
LXC_NS_MAX
]
=
{
[
LXC_NS_MNT
]
=
{
"mnt"
,
CLONE_NEWNS
},
[
LXC_NS_PID
]
=
{
"pid"
,
CLONE_NEWPID
},
[
LXC_NS_UTS
]
=
{
"uts"
,
CLONE_NEWUTS
},
[
LXC_NS_IPC
]
=
{
"ipc"
,
CLONE_NEWIPC
},
[
LXC_NS_USER
]
=
{
"user"
,
CLONE_NEWUSER
},
[
LXC_NS_NET
]
=
{
"net"
,
CLONE_NEWNET
}
};
static
void
close_ns
(
int
ns_fd
[
LXC_NS_MAX
])
{
int
i
;
process_lock
();
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
(
ns_fd
[
i
]
>
-
1
)
{
close
(
ns_fd
[
i
]);
ns_fd
[
i
]
=
-
1
;
}
}
process_unlock
();
}
static
int
preserve_ns
(
int
ns_fd
[
LXC_NS_MAX
],
int
clone_flags
)
{
int
i
,
saved_errno
;
char
path
[
MAXPATHLEN
];
if
(
access
(
"/proc/self/ns"
,
X_OK
))
{
ERROR
(
"Does this kernel version support 'attach'?"
);
return
-
1
;
}
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
ns_fd
[
i
]
=
-
1
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
((
clone_flags
&
ns_info
[
i
].
clone_flag
)
==
0
)
continue
;
snprintf
(
path
,
MAXPATHLEN
,
"/proc/self/ns/%s"
,
ns_info
[
i
].
proc_name
);
process_lock
();
ns_fd
[
i
]
=
open
(
path
,
O_RDONLY
|
O_CLOEXEC
);
process_unlock
();
if
(
ns_fd
[
i
]
<
0
)
goto
error
;
}
return
0
;
error:
saved_errno
=
errno
;
close_ns
(
ns_fd
);
errno
=
saved_errno
;
SYSERROR
(
"failed to open '%s'"
,
path
);
return
-
1
;
}
static
int
attach_ns
(
const
int
ns_fd
[
LXC_NS_MAX
])
{
int
i
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
(
ns_fd
[
i
]
<
0
)
continue
;
if
(
setns
(
ns_fd
[
i
],
0
)
!=
0
)
goto
error
;
}
return
0
;
error:
SYSERROR
(
"failed to set namespace '%s'"
,
ns_info
[
i
].
proc_name
);
return
-
1
;
}
static
int
match_fd
(
int
fd
)
{
return
(
fd
==
0
||
fd
==
1
||
fd
==
2
);
...
...
@@ -645,44 +717,68 @@ int lxc_spawn(struct lxc_handler *handler)
const
char
*
name
=
handler
->
name
;
struct
cgroup_meta_data
*
cgroup_meta
=
NULL
;
const
char
*
cgroup_pattern
=
NULL
;
int
saved_ns_fd
[
LXC_NS_MAX
];
int
preserve_mask
=
0
,
i
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
if
(
handler
->
conf
->
inherit_ns_fd
[
i
]
!=
-
1
)
preserve_mask
|=
ns_info
[
i
].
clone_flag
;
if
(
lxc_sync_init
(
handler
))
return
-
1
;
handler
->
clone_flags
=
CLONE_NEW
UTS
|
CLONE_NEWPID
|
CLONE_NEWIPC
|
CLONE_NEWNS
;
handler
->
clone_flags
=
CLONE_NEW
PID
|
CLONE_NEWNS
;
if
(
!
lxc_list_empty
(
&
handler
->
conf
->
id_map
))
{
INFO
(
"Cloning a new user namespace"
);
handler
->
clone_flags
|=
CLONE_NEWUSER
;
}
if
(
!
lxc_list_empty
(
&
handler
->
conf
->
network
))
{
handler
->
clone_flags
|=
CLONE_NEWNET
;
/* Find gateway addresses from the link device, which is
* no longer accessible inside the container. Do this
* before creating network interfaces, since goto
* out_delete_net does not work before lxc_clone. */
if
(
lxc_find_gateway_addresses
(
handler
))
{
ERROR
(
"failed to find gateway addresses"
);
lxc_sync_fini
(
handler
);
return
-
1
;
if
(
handler
->
conf
->
inherit_ns_fd
[
LXC_NS_NET
]
==
-
1
)
{
if
(
!
lxc_list_empty
(
&
handler
->
conf
->
network
))
{
handler
->
clone_flags
|=
CLONE_NEWNET
;
/* Find gateway addresses from the link device, which is
* no longer accessible inside the container. Do this
* before creating network interfaces, since goto
* out_delete_net does not work before lxc_clone. */
if
(
lxc_find_gateway_addresses
(
handler
))
{
ERROR
(
"failed to find gateway addresses"
);
lxc_sync_fini
(
handler
);
return
-
1
;
}
/* that should be done before the clone because we will
* fill the netdev index and use them in the child
*/
if
(
lxc_create_network
(
handler
))
{
ERROR
(
"failed to create the network"
);
lxc_sync_fini
(
handler
);
return
-
1
;
}
}
/* that should be done before the clone because we will
* fill the netdev index and use them in the child
*/
if
(
lxc_create_network
(
handler
))
{
ERROR
(
"failed to create the network"
);
lxc_sync_fini
(
handler
);
return
-
1
;
if
(
save_phys_nics
(
handler
->
conf
))
{
ERROR
(
"failed to save physical nic info"
);
goto
out_abort
;
}
}
else
{
INFO
(
"Inheriting a net namespace"
);
}
if
(
save_phys_nics
(
handler
->
conf
))
{
ERROR
(
"failed to save physical nic info"
);
goto
out_abort
;
if
(
handler
->
conf
->
inherit_ns_fd
[
LXC_NS_IPC
]
==
-
1
)
{
handler
->
clone_flags
|=
CLONE_NEWIPC
;
}
else
{
INFO
(
"Inheriting an IPC namespace"
);
}
if
(
handler
->
conf
->
inherit_ns_fd
[
LXC_NS_UTS
]
==
-
1
)
{
handler
->
clone_flags
|=
CLONE_NEWUTS
;
}
else
{
INFO
(
"Inheriting a UTS namespace"
);
}
cgroup_meta
=
lxc_cgroup_load_meta
();
if
(
!
cgroup_meta
)
{
ERROR
(
"failed to detect cgroup metadata"
);
...
...
@@ -716,6 +812,9 @@ int lxc_spawn(struct lxc_handler *handler)
if
(
handler
->
pinfd
==
-
1
)
INFO
(
"failed to pin the container's rootfs"
);
preserve_ns
(
saved_ns_fd
,
preserve_mask
);
attach_ns
(
handler
->
conf
->
inherit_ns_fd
);
/* Create a process in a new set of namespaces */
handler
->
pid
=
lxc_clone
(
do_start
,
handler
,
handler
->
clone_flags
);
if
(
handler
->
pid
<
0
)
{
...
...
@@ -723,6 +822,8 @@ int lxc_spawn(struct lxc_handler *handler)
goto
out_delete_net
;
}
attach_ns
(
saved_ns_fd
);
lxc_sync_fini_child
(
handler
);
if
(
lxc_sync_wait_child
(
handler
,
LXC_SYNC_CONFIGURE
))
...
...
src/lxc/start.h
View file @
7faa7f52
...
...
@@ -27,6 +27,7 @@
#include <lxc/state.h>
#include <sys/param.h>
#include "namespace.h"
struct
lxc_conf
;
...
...
@@ -39,6 +40,23 @@ struct lxc_operations {
struct
cgroup_desc
;
enum
{
LXC_NS_MNT
,
LXC_NS_PID
,
LXC_NS_UTS
,
LXC_NS_IPC
,
LXC_NS_USER
,
LXC_NS_NET
,
LXC_NS_MAX
};
struct
ns_info
{
const
char
*
proc_name
;
int
clone_flag
;
};
const
struct
ns_info
ns_info
[
LXC_NS_MAX
];
struct
lxc_handler
{
pid_t
pid
;
char
*
name
;
...
...
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