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
2ed797da
Unverified
Commit
2ed797da
authored
Nov 04, 2017
by
Serge Hallyn
Committed by
GitHub
Nov 04, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1884 from brauner/2017-10-28/move_tools_to_api_only
confile: add lxc.namespace.<namespace-key> + add user namespace sharing + rework start logic
parents
190f9aee
686dd5d1
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
338 additions
and
212 deletions
+338
-212
commands.c
src/lxc/commands.c
+1
-1
conf.c
src/lxc/conf.c
+13
-10
conf.h
src/lxc/conf.h
+2
-2
confile.c
src/lxc/confile.c
+58
-0
confile_utils.c
src/lxc/confile_utils.c
+76
-1
confile_utils.h
src/lxc/confile_utils.h
+2
-0
monitor.c
src/lxc/monitor.c
+2
-2
namespace.c
src/lxc/namespace.c
+14
-3
namespace.h
src/lxc/namespace.h
+2
-1
network.c
src/lxc/network.c
+15
-16
network.h
src/lxc/network.h
+2
-2
start.c
src/lxc/start.c
+126
-97
start.h
src/lxc/start.h
+3
-6
lxc_start.c
src/lxc/tools/lxc_start.c
+22
-71
No files found.
src/lxc/commands.c
View file @
2ed797da
...
...
@@ -835,7 +835,7 @@ static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
rsp
.
data
=
handler
->
name
;
rsp
.
data
=
(
char
*
)
handler
->
name
;
rsp
.
datalen
=
strlen
(
handler
->
name
)
+
1
;
rsp
.
ret
=
0
;
...
...
src/lxc/conf.c
View file @
2ed797da
...
...
@@ -2461,21 +2461,19 @@ struct lxc_conf *lxc_conf_init(void)
lxc_list_init
(
&
new
->
aliens
);
lxc_list_init
(
&
new
->
environment
);
lxc_list_init
(
&
new
->
limits
);
for
(
i
=
0
;
i
<
NUM_LXC_HOOKS
;
i
++
)
for
(
i
=
0
;
i
<
NUM_LXC_HOOKS
;
i
++
)
lxc_list_init
(
&
new
->
hooks
[
i
]);
lxc_list_init
(
&
new
->
groups
);
new
->
lsm_aa_profile
=
NULL
;
new
->
lsm_se_context
=
NULL
;
new
->
tmp_umount_proc
=
0
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
new
->
inherit_ns_fd
[
i
]
=
-
1
;
/* if running in a new user namespace, init and COMMAND
* default to running as UID/GID 0 when using lxc-execute */
new
->
init_uid
=
0
;
new
->
init_gid
=
0
;
memset
(
&
new
->
cgroup_meta
,
0
,
sizeof
(
struct
lxc_cgroup
));
memset
(
&
new
->
inherit_ns
,
0
,
sizeof
(
char
*
)
*
LXC_NS_MAX
);
return
new
;
}
...
...
@@ -3155,7 +3153,7 @@ int lxc_setup_child(struct lxc_handler *handler)
return
-
1
;
}
if
(
lxc_conf
->
inherit_ns_
fd
[
LXC_NS_UTS
]
==
-
1
)
{
if
(
handler
->
ns
fd
[
LXC_NS_UTS
]
==
-
1
)
{
if
(
setup_utsname
(
lxc_conf
->
utsname
))
{
ERROR
(
"failed to setup the utsname for '%s'"
,
name
);
return
-
1
;
...
...
@@ -3674,7 +3672,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
struct
lxc_list
*
it
;
struct
id_map
*
map
;
char
c
=
'1'
;
int
ret
=
-
1
;
int
ret
=
-
1
,
status
=
-
1
;
struct
lxc_list
*
idmap
=
NULL
,
*
tmplist
=
NULL
;
struct
id_map
*
container_root_uid
=
NULL
,
*
container_root_gid
=
NULL
,
*
host_uid_map
=
NULL
,
*
host_gid_map
=
NULL
;
...
...
@@ -3844,10 +3842,11 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
goto
on_error
;
}
on_error:
/* Wait for child to finish. */
ret
=
wait_for_pid
(
pid
);
if
(
pid
>
0
)
status
=
wait_for_pid
(
pid
);
on_error:
if
(
idmap
)
lxc_free_idmap
(
idmap
);
if
(
container_root_uid
)
...
...
@@ -3863,6 +3862,9 @@ on_error:
close
(
p
[
0
]);
close
(
p
[
1
]);
if
(
status
<
0
)
ret
=
-
1
;
return
ret
;
}
...
...
@@ -4026,10 +4028,11 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
goto
on_error
;
}
on_error:
/* Wait for child to finish. */
ret
=
wait_for_pid
(
pid
);
if
(
pid
>
0
)
ret
=
wait_for_pid
(
pid
);
on_error:
if
(
idmap
)
lxc_free_idmap
(
idmap
);
if
(
host_uid_map
&&
(
host_uid_map
!=
container_root_uid
))
...
...
src/lxc/conf.h
View file @
2ed797da
...
...
@@ -285,8 +285,6 @@ struct lxc_conf {
int
loglevel
;
/* loglevel as specifed in config (if any) */
int
logfd
;
int
inherit_ns_fd
[
LXC_NS_MAX
];
unsigned
int
start_auto
;
unsigned
int
start_delay
;
int
start_order
;
...
...
@@ -348,6 +346,8 @@ struct lxc_conf {
* that union.
*/
struct
lxc_cgroup
cgroup_meta
;
char
*
inherit_ns
[
LXC_NS_MAX
];
};
#ifdef HAVE_TLS
...
...
src/lxc/confile.c
View file @
2ed797da
...
...
@@ -102,6 +102,7 @@ lxc_config_define(monitor);
lxc_config_define
(
mount
);
lxc_config_define
(
mount_auto
);
lxc_config_define
(
mount_fstab
);
lxc_config_define
(
namespace
);
lxc_config_define
(
net
);
lxc_config_define
(
net_flags
);
lxc_config_define
(
net_hwaddr
);
...
...
@@ -178,6 +179,7 @@ static struct lxc_config_t config[] = {
{
"lxc.mount.auto"
,
false
,
set_config_mount_auto
,
get_config_mount_auto
,
clr_config_mount_auto
,
},
{
"lxc.mount.entry"
,
false
,
set_config_mount
,
get_config_mount
,
clr_config_mount
,
},
{
"lxc.mount.fstab"
,
false
,
set_config_mount_fstab
,
get_config_mount_fstab
,
clr_config_mount_fstab
,
},
{
"lxc.namespace"
,
false
,
set_config_namespace
,
get_config_namespace
,
clr_config_namespace
,
},
/* [START]: REMOVE IN LXC 3.0 */
{
"lxc.network.type"
,
true
,
set_config_network_legacy_type
,
get_config_network_legacy_item
,
clr_config_network_legacy_item
,
},
...
...
@@ -1976,6 +1978,23 @@ static int set_config_uts_name(const char *key, const char *value,
return
0
;
}
static
int
set_config_namespace
(
const
char
*
key
,
const
char
*
value
,
struct
lxc_conf
*
lxc_conf
,
void
*
data
)
{
int
ns_idx
;
const
char
*
namespace
;
if
(
lxc_config_value_empty
(
value
))
return
clr_config_namespace
(
key
,
lxc_conf
,
data
);
namespace
=
key
+
sizeof
(
"lxc.namespace."
)
-
1
;
ns_idx
=
lxc_namespace_2_ns_idx
(
namespace
);
if
(
ns_idx
<
0
)
return
ns_idx
;
return
set_config_string_item
(
&
lxc_conf
->
inherit_ns
[
ns_idx
],
value
);
}
struct
parse_line_conf
{
struct
lxc_conf
*
conf
;
bool
from_include
;
...
...
@@ -3268,6 +3287,28 @@ static int get_config_noop(const char *key, char *retv, int inlen,
return
0
;
}
static
int
get_config_namespace
(
const
char
*
key
,
char
*
retv
,
int
inlen
,
struct
lxc_conf
*
c
,
void
*
data
)
{
int
len
,
ns_idx
;
const
char
*
namespace
;
int
fulllen
=
0
;
if
(
!
retv
)
inlen
=
0
;
else
memset
(
retv
,
0
,
inlen
);
namespace
=
key
+
sizeof
(
"lxc.namespace."
)
-
1
;
ns_idx
=
lxc_namespace_2_ns_idx
(
namespace
);
if
(
ns_idx
<
0
)
return
ns_idx
;
strprint
(
retv
,
inlen
,
"%s"
,
c
->
inherit_ns
[
ns_idx
]);
return
fulllen
;
}
/* Callbacks to clear config items. */
static
inline
int
clr_config_personality
(
const
char
*
key
,
struct
lxc_conf
*
c
,
void
*
data
)
...
...
@@ -3606,6 +3647,23 @@ static inline int clr_config_noop(const char *key, struct lxc_conf *c,
return
0
;
}
static
int
clr_config_namespace
(
const
char
*
key
,
struct
lxc_conf
*
lxc_conf
,
void
*
data
)
{
int
ns_idx
;
const
char
*
namespace
;
namespace
=
key
+
sizeof
(
"lxc.namespace."
)
-
1
;
ns_idx
=
lxc_namespace_2_ns_idx
(
namespace
);
if
(
ns_idx
<
0
)
return
ns_idx
;
free
(
lxc_conf
->
inherit_ns
[
ns_idx
]);
lxc_conf
->
inherit_ns
[
ns_idx
]
=
NULL
;
return
0
;
}
static
int
get_config_includefiles
(
const
char
*
key
,
char
*
retv
,
int
inlen
,
struct
lxc_conf
*
c
,
void
*
data
)
{
...
...
src/lxc/confile_utils.c
View file @
2ed797da
...
...
@@ -29,8 +29,9 @@
#include "confile.h"
#include "confile_utils.h"
#include "error.h"
#include "log.h"
#include "list.h"
#include "log.h"
#include "lxccontainer.h"
#include "network.h"
#include "parse.h"
#include "utils.h"
...
...
@@ -700,3 +701,77 @@ bool parse_limit_value(const char **value, rlim_t *res)
return
true
;
}
static
int
lxc_container_name_to_pid
(
const
char
*
lxcname_or_pid
,
const
char
*
lxcpath
)
{
int
ret
;
signed
long
int
pid
;
char
*
err
=
NULL
;
pid
=
strtol
(
lxcname_or_pid
,
&
err
,
10
);
if
(
*
err
!=
'\0'
||
pid
<
1
)
{
struct
lxc_container
*
c
;
c
=
lxc_container_new
(
lxcname_or_pid
,
lxcpath
);
if
(
!
c
)
{
ERROR
(
"
\"
%s
\"
is not a valid pid nor a container name"
,
lxcname_or_pid
);
return
-
1
;
}
if
(
!
c
->
may_control
(
c
))
{
ERROR
(
"Insufficient privileges to control container "
"
\"
%s
\"
"
,
c
->
name
);
lxc_container_put
(
c
);
return
-
1
;
}
pid
=
c
->
init_pid
(
c
);
if
(
pid
<
1
)
{
ERROR
(
"Container
\"
%s
\"
is not running"
,
c
->
name
);
lxc_container_put
(
c
);
return
-
1
;
}
lxc_container_put
(
c
);
}
ret
=
kill
(
pid
,
0
);
if
(
ret
<
0
)
{
ERROR
(
"%s - Failed to send signal to pid %d"
,
strerror
(
errno
),
(
int
)
pid
);
return
-
EPERM
;
}
return
pid
;
}
int
lxc_inherit_namespace
(
const
char
*
lxcname_or_pid
,
const
char
*
lxcpath
,
const
char
*
namespace
)
{
int
fd
,
pid
;
char
*
dup
,
*
lastslash
;
lastslash
=
strrchr
(
lxcname_or_pid
,
'/'
);
if
(
lastslash
)
{
dup
=
strdup
(
lxcname_or_pid
);
if
(
!
dup
)
return
-
ENOMEM
;
*
lastslash
=
'\0'
;
pid
=
lxc_container_name_to_pid
(
lastslash
,
dup
);
free
(
dup
);
}
else
{
pid
=
lxc_container_name_to_pid
(
lxcname_or_pid
,
lxcpath
);
}
if
(
pid
<
0
)
return
-
EINVAL
;
fd
=
lxc_preserve_ns
(
pid
,
namespace
);
if
(
fd
<
0
)
return
-
EINVAL
;
return
fd
;
}
src/lxc/confile_utils.h
View file @
2ed797da
...
...
@@ -86,5 +86,7 @@ extern int lxc_get_conf_str(char *retv, int inlen, const char *value);
extern
int
lxc_get_conf_int
(
struct
lxc_conf
*
c
,
char
*
retv
,
int
inlen
,
int
v
);
extern
int
lxc_get_conf_uint64
(
struct
lxc_conf
*
c
,
char
*
retv
,
int
inlen
,
uint64_t
v
);
extern
bool
parse_limit_value
(
const
char
**
value
,
rlim_t
*
res
);
extern
int
lxc_inherit_namespace
(
const
char
*
lxcname_or_pid
,
const
char
*
lxcpath
,
const
char
*
namespace
);
#endif
/* __LXC_CONFILE_UTILS_H */
src/lxc/monitor.c
View file @
2ed797da
...
...
@@ -105,10 +105,10 @@ static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath)
/* It is normal for this open() to fail with ENXIO when there is
* no monitor running, so we don't log it.
*/
if
(
errno
==
ENXIO
)
if
(
errno
==
ENXIO
||
errno
==
ENOENT
)
return
;
WARN
(
"
Failed to open fifo to send message: %s.
"
,
strerror
(
errno
));
WARN
(
"
%s - Failed to open fifo to send message
"
,
strerror
(
errno
));
return
;
}
...
...
src/lxc/namespace.c
View file @
2ed797da
...
...
@@ -96,15 +96,26 @@ const struct ns_info ns_info[LXC_NS_MAX] = {
[
LXC_NS_CGROUP
]
=
{
"cgroup"
,
CLONE_NEWCGROUP
,
"CLONE_NEWCGROUP"
}
};
int
lxc_namespace_2_cloneflag
(
char
*
namespace
)
int
lxc_namespace_2_cloneflag
(
c
onst
c
har
*
namespace
)
{
int
i
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
if
(
!
strcasecmp
(
ns_info
[
i
].
proc_name
,
namespace
))
return
ns_info
[
i
].
clone_flag
;
ERROR
(
"Invalid namespace name: %s."
,
namespace
);
return
-
1
;
ERROR
(
"Invalid namespace name
\"
%s
\"
"
,
namespace
);
return
-
EINVAL
;
}
int
lxc_namespace_2_ns_idx
(
const
char
*
namespace
)
{
int
i
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
if
(
!
strcmp
(
ns_info
[
i
].
proc_name
,
namespace
))
return
i
;
ERROR
(
"Invalid namespace name
\"
%s
\"
"
,
namespace
);
return
-
EINVAL
;
}
int
lxc_fill_namespace_flags
(
char
*
flaglist
,
int
*
flags
)
...
...
src/lxc/namespace.h
View file @
2ed797da
...
...
@@ -81,7 +81,8 @@ int clone(int (*fn)(void *), void *child_stack,
extern
pid_t
lxc_clone
(
int
(
*
fn
)(
void
*
),
void
*
arg
,
int
flags
);
extern
int
lxc_namespace_2_cloneflag
(
char
*
namespace
);
extern
int
lxc_namespace_2_cloneflag
(
const
char
*
namespace
);
extern
int
lxc_namespace_2_ns_idx
(
const
char
*
namespace
);
extern
int
lxc_fill_namespace_flags
(
char
*
flaglist
,
int
*
flags
);
#endif
src/lxc/network.c
View file @
2ed797da
...
...
@@ -2050,7 +2050,7 @@ int lxc_find_gateway_addresses(struct lxc_handler *handler)
}
#define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
static
int
lxc_create_network_unpriv_exec
(
const
char
*
lxcpath
,
char
*
lxcname
,
static
int
lxc_create_network_unpriv_exec
(
const
char
*
lxcpath
,
c
onst
c
har
*
lxcname
,
struct
lxc_netdev
*
netdev
,
pid_t
pid
)
{
int
ret
;
...
...
@@ -2126,13 +2126,13 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname,
if
(
bytes
<
0
)
{
SYSERROR
(
"Failed to read from pipe file descriptor"
);
close
(
pipefd
[
0
]);
return
-
1
;
}
else
{
buffer
[
bytes
-
1
]
=
'\0'
;
}
buffer
[
bytes
-
1
]
=
'\0'
;
ret
=
wait_for_pid
(
child
);
close
(
pipefd
[
0
]);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
||
bytes
<
0
)
{
ERROR
(
"lxc-user-nic failed to configure requested network: %s"
,
buffer
[
0
]
!=
'\0'
?
buffer
:
"(null)"
);
return
-
1
;
...
...
@@ -2194,7 +2194,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname,
return
0
;
}
static
int
lxc_delete_network_unpriv_exec
(
const
char
*
lxcpath
,
char
*
lxcname
,
static
int
lxc_delete_network_unpriv_exec
(
const
char
*
lxcpath
,
c
onst
c
har
*
lxcname
,
struct
lxc_netdev
*
netdev
,
const
char
*
netns_path
)
{
...
...
@@ -2267,19 +2267,18 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, char *lxcname,
if
(
bytes
<
0
)
{
SYSERROR
(
"Failed to read from pipe file descriptor."
);
close
(
pipefd
[
0
]);
return
-
1
;
}
else
{
buffer
[
bytes
-
1
]
=
'\0'
;
}
buffer
[
bytes
-
1
]
=
'\0'
;
if
(
wait_for_pid
(
child
)
!=
0
)
{
ret
=
wait_for_pid
(
child
);
close
(
pipefd
[
0
]);
if
(
ret
!=
0
||
bytes
<
0
)
{
ERROR
(
"lxc-user-nic failed to delete requested network: %s"
,
buffer
[
0
]
!=
'\0'
?
buffer
:
"(null)"
);
close
(
pipefd
[
0
]);
return
-
1
;
}
close
(
pipefd
[
0
]);
return
0
;
}
...
...
@@ -2302,14 +2301,14 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler)
*
netns_path
=
'\0'
;
if
(
handler
->
n
etnsfd
<
0
)
{
if
(
handler
->
n
sfd
[
LXC_NS_NET
]
<
0
)
{
DEBUG
(
"Cannot not guarantee safe deletion of network devices. "
"Manual cleanup maybe needed"
);
return
false
;
}
ret
=
snprintf
(
netns_path
,
sizeof
(
netns_path
),
"/proc/%d/fd/%d"
,
getpid
(),
handler
->
n
etnsfd
);
getpid
(),
handler
->
n
sfd
[
LXC_NS_NET
]
);
if
(
ret
<
0
||
ret
>=
sizeof
(
netns_path
))
return
false
;
...
...
@@ -2408,7 +2407,7 @@ int lxc_create_network_priv(struct lxc_handler *handler)
return
0
;
}
int
lxc_network_move_created_netdev_priv
(
const
char
*
lxcpath
,
char
*
lxcname
,
int
lxc_network_move_created_netdev_priv
(
const
char
*
lxcpath
,
c
onst
c
har
*
lxcname
,
struct
lxc_list
*
network
,
pid_t
pid
)
{
int
ret
;
...
...
@@ -2448,7 +2447,7 @@ int lxc_network_move_created_netdev_priv(const char *lxcpath, char *lxcname,
return
0
;
}
int
lxc_create_network_unpriv
(
const
char
*
lxcpath
,
char
*
lxcname
,
int
lxc_create_network_unpriv
(
const
char
*
lxcpath
,
c
onst
c
har
*
lxcname
,
struct
lxc_list
*
network
,
pid_t
pid
)
{
struct
lxc_list
*
iterator
;
...
...
@@ -2621,7 +2620,7 @@ int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler)
int
oldfd
;
char
ifname
[
IFNAMSIZ
];
struct
lxc_list
*
iterator
;
int
netnsfd
=
handler
->
n
etnsfd
;
int
netnsfd
=
handler
->
n
sfd
[
LXC_NS_NET
]
;
struct
lxc_conf
*
conf
=
handler
->
conf
;
/* We need CAP_NET_ADMIN in the parent namespace in order to setns() to
...
...
src/lxc/network.h
View file @
2ed797da
...
...
@@ -263,12 +263,12 @@ extern int setup_private_host_hw_addr(char *veth1);
extern
int
netdev_get_mtu
(
int
ifindex
);
extern
int
lxc_create_network_priv
(
struct
lxc_handler
*
handler
);
extern
int
lxc_network_move_created_netdev_priv
(
const
char
*
lxcpath
,
char
*
lxcname
,
c
onst
c
har
*
lxcname
,
struct
lxc_list
*
network
,
pid_t
pid
);
extern
void
lxc_delete_network
(
struct
lxc_handler
*
handler
);
extern
int
lxc_find_gateway_addresses
(
struct
lxc_handler
*
handler
);
extern
int
lxc_create_network_unpriv
(
const
char
*
lxcpath
,
char
*
lxcname
,
extern
int
lxc_create_network_unpriv
(
const
char
*
lxcpath
,
c
onst
c
har
*
lxcname
,
struct
lxc_list
*
network
,
pid_t
pid
);
extern
int
lxc_requests_empty_network
(
struct
lxc_handler
*
handler
);
extern
int
lxc_restore_phys_nics_to_netns
(
struct
lxc_handler
*
handler
);
...
...
src/lxc/start.c
View file @
2ed797da
...
...
@@ -155,9 +155,12 @@ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid)
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
((
clone_flags
&
ns_info
[
i
].
clone_flag
)
==
0
)
continue
;
ns_fd
[
i
]
=
lxc_preserve_ns
(
pid
,
ns_info
[
i
].
proc_name
);
if
(
ns_fd
[
i
]
<
0
)
goto
error
;
DEBUG
(
"Preserved %s namespace via fd %d"
,
ns_info
[
i
].
proc_name
,
ns_fd
[
i
]);
}
return
true
;
...
...
@@ -171,23 +174,6 @@ error:
return
false
;
}
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 attach %s namespace."
,
ns_info
[
i
].
proc_name
);
return
-
1
;
}
static
int
match_fd
(
int
fd
)
{
return
(
fd
==
0
||
fd
==
1
||
fd
==
2
);
...
...
@@ -236,15 +222,6 @@ restart:
(
i
<
len_fds
&&
fd
==
fds_to_ignore
[
i
]))
continue
;
if
(
conf
)
{
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
if
(
conf
->
inherit_ns_fd
[
i
]
==
fd
)
break
;
if
(
i
<
LXC_NS_MAX
)
continue
;
}
if
(
current_config
&&
fd
==
current_config
->
logfd
)
continue
;
...
...
@@ -254,10 +231,10 @@ restart:
if
(
closeall
)
{
close
(
fd
);
closedir
(
dir
);
INFO
(
"Closed inherited fd
: %d.
"
,
fd
);
INFO
(
"Closed inherited fd
%d
"
,
fd
);
goto
restart
;
}
WARN
(
"Inherited fd
: %d.
"
,
fd
);
WARN
(
"Inherited fd
%d
"
,
fd
);
}
/* Only enable syslog at this point to avoid the above logging function
...
...
@@ -525,9 +502,6 @@ void lxc_free_handler(struct lxc_handler *handler)
if
(
handler
->
state_socket_pair
[
1
]
>=
0
)
close
(
handler
->
state_socket_pair
[
1
]);
if
(
handler
->
name
)
free
(
handler
->
name
);
handler
->
conf
=
NULL
;
free
(
handler
);
}
...
...
@@ -561,11 +535,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
handler
->
nsfd
[
i
]
=
-
1
;
handler
->
name
=
strdup
(
name
);
if
(
!
handler
->
name
)
{
ERROR
(
"failed to allocate memory"
);
goto
on_error
;
}
handler
->
name
=
name
;
if
(
daemonize
&&
!
handler
->
conf
->
reboot
)
{
/* Create socketpair() to synchronize on daemonized startup.
...
...
@@ -729,16 +699,13 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
while
(
namespace_count
--
)
free
(
namespaces
[
namespace_count
]);
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
(
handler
->
nsfd
[
i
]
!=
-
1
)
{
close
(
handler
->
nsfd
[
i
]);
handler
->
nsfd
[
i
]
=
-
1
;
}
}
if
(
handler
->
nsfd
[
i
]
<
0
)
continue
;
if
(
handler
->
netnsfd
>=
0
)
{
close
(
handler
->
netnsfd
);
handler
->
netnsfd
=
-
1
;
close
(
handler
->
nsfd
[
i
]);
handler
->
nsfd
[
i
]
=
-
1
;
}
cgroup_destroy
(
handler
);
...
...
@@ -786,7 +753,6 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
if
(
handler
->
conf
->
ephemeral
==
1
&&
handler
->
conf
->
reboot
!=
1
)
lxc_destroy_container_on_signal
(
handler
,
name
);
free
(
handler
->
name
);
free
(
handler
);
}
...
...
@@ -804,10 +770,11 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
static
int
do_start
(
void
*
data
)
{
int
ret
;
struct
lxc_list
*
iterator
;
struct
lxc_handler
*
handler
=
data
;
int
devnull_fd
=
-
1
,
ret
;
char
path
[
PATH_MAX
];
int
devnull_fd
=
-
1
;
struct
lxc_handler
*
handler
=
data
;
if
(
sigprocmask
(
SIG_SETMASK
,
&
handler
->
oldmask
,
NULL
))
{
SYSERROR
(
"Failed to set signal mask."
);
...
...
@@ -1128,30 +1095,73 @@ void resolve_clone_flags(struct lxc_handler *handler)
{
handler
->
clone_flags
=
CLONE_NEWNS
;
if
(
!
lxc_list_empty
(
&
handler
->
conf
->
id_map
))
handler
->
clone_flags
|=
CLONE_NEWUSER
;
if
(
!
handler
->
conf
->
inherit_ns
[
LXC_NS_USER
])
{
if
(
!
lxc_list_empty
(
&
handler
->
conf
->
id_map
))
handler
->
clone_flags
|=
CLONE_NEWUSER
;
}
else
{
INFO
(
"Inheriting user namespace"
);
}
if
(
handler
->
conf
->
inherit_ns_fd
[
LXC_NS_NET
]
==
-
1
)
{
if
(
!
handler
->
conf
->
inherit_ns
[
LXC_NS_NET
]
)
{
if
(
!
lxc_requests_empty_network
(
handler
))
handler
->
clone_flags
|=
CLONE_NEWNET
;
}
else
{
INFO
(
"Inheriting
a NET namespace.
"
);
INFO
(
"Inheriting
net namespace
"
);
}
if
(
handler
->
conf
->
inherit_ns_fd
[
LXC_NS_IPC
]
==
-
1
)
if
(
!
handler
->
conf
->
inherit_ns
[
LXC_NS_IPC
]
)
handler
->
clone_flags
|=
CLONE_NEWIPC
;
else
INFO
(
"Inheriting
an IPC namespace.
"
);
INFO
(
"Inheriting
ipc namespace
"
);
if
(
handler
->
conf
->
inherit_ns_fd
[
LXC_NS_UTS
]
==
-
1
)
if
(
!
handler
->
conf
->
inherit_ns
[
LXC_NS_UTS
]
)
handler
->
clone_flags
|=
CLONE_NEWUTS
;
else
INFO
(
"Inheriting
a UTS namespace.
"
);
INFO
(
"Inheriting
uts namespace
"
);
if
(
handler
->
conf
->
inherit_ns_fd
[
LXC_NS_PID
]
==
-
1
)
if
(
!
handler
->
conf
->
inherit_ns
[
LXC_NS_PID
]
)
handler
->
clone_flags
|=
CLONE_NEWPID
;
else
INFO
(
"Inheriting a PID namespace."
);
INFO
(
"Inheriting pid namespace"
);
}
static
pid_t
lxc_fork_attach_clone
(
int
(
*
fn
)(
void
*
),
void
*
arg
,
int
flags
)
{
int
i
,
r
,
ret
;
pid_t
pid
,
init_pid
;
struct
lxc_handler
*
handler
=
arg
;
pid
=
fork
();
if
(
pid
<
0
)
return
-
1
;
if
(
!
pid
)
{
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
(
handler
->
nsfd
[
i
]
<
0
)
continue
;
ret
=
setns
(
handler
->
nsfd
[
i
],
0
);
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
DEBUG
(
"Inherited %s namespace"
,
ns_info
[
i
].
proc_name
);
}
init_pid
=
lxc_clone
(
do_start
,
handler
,
flags
);
ret
=
lxc_write_nointr
(
handler
->
data_sock
[
1
],
&
init_pid
,
sizeof
(
init_pid
));
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
exit
(
EXIT_SUCCESS
);
}
r
=
lxc_read_nointr
(
handler
->
data_sock
[
0
],
&
init_pid
,
sizeof
(
init_pid
));
ret
=
wait_for_pid
(
pid
);
if
(
ret
<
0
||
r
<
0
)
return
-
1
;
return
init_pid
;
}
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which
...
...
@@ -1164,20 +1174,27 @@ void resolve_clone_flags(struct lxc_handler *handler)
static
int
lxc_spawn
(
struct
lxc_handler
*
handler
)
{
int
i
,
flags
,
ret
;
const
char
*
name
=
handler
->
name
;
char
pidstr
[
20
];
bool
wants_to_map_ids
;
int
saved_ns_fd
[
LXC_NS_MAX
];
struct
lxc_list
*
id_map
;
int
preserve_mask
=
0
;
bool
cgroups_connected
=
false
;
const
char
*
name
=
handler
->
name
;
const
char
*
lxcpath
=
handler
->
lxcpath
;
bool
cgroups_connected
=
false
,
fork_before_clone
=
false
;
struct
lxc_conf
*
conf
=
handler
->
conf
;
id_map
=
&
handler
->
conf
->
id_map
;
id_map
=
&
conf
->
id_map
;
wants_to_map_ids
=
!
lxc_list_empty
(
id_map
);
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
if
(
handler
->
conf
->
inherit_ns_fd
[
i
]
!=
-
1
)
preserve_mask
|=
ns_info
[
i
].
clone_flag
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
(
!
conf
->
inherit_ns
[
i
])
continue
;
handler
->
nsfd
[
i
]
=
lxc_inherit_namespace
(
conf
->
inherit_ns
[
i
],
lxcpath
,
ns_info
[
i
].
proc_name
);
if
(
handler
->
nsfd
[
i
]
<
0
)
return
-
1
;
fork_before_clone
=
true
;
}
if
(
lxc_sync_init
(
handler
))
return
-
1
;
...
...
@@ -1192,7 +1209,7 @@ static int lxc_spawn(struct lxc_handler *handler)
resolve_clone_flags
(
handler
);
if
(
handler
->
clone_flags
&
CLONE_NEWNET
)
{
if
(
!
lxc_list_empty
(
&
handler
->
conf
->
network
))
{
if
(
!
lxc_list_empty
(
&
conf
->
network
))
{
/* Find gateway addresses from the link device, which is
* no longer accessible inside the container. Do this
...
...
@@ -1233,17 +1250,11 @@ static int lxc_spawn(struct lxc_handler *handler)
* If the container is unprivileged then skip rootfs pinning.
*/
if
(
!
wants_to_map_ids
)
{
handler
->
pinfd
=
pin_rootfs
(
handler
->
conf
->
rootfs
.
path
);
handler
->
pinfd
=
pin_rootfs
(
conf
->
rootfs
.
path
);
if
(
handler
->
pinfd
==
-
1
)
INFO
(
"Failed to pin the rootfs for container
\"
%s
\"
."
,
handler
->
name
);
}
if
(
!
preserve_ns
(
saved_ns_fd
,
preserve_mask
,
getpid
()))
goto
out_delete_net
;
if
(
attach_ns
(
handler
->
conf
->
inherit_ns_fd
)
<
0
)
goto
out_delete_net
;
/* Create a process in a new set of namespaces. */
flags
=
handler
->
clone_flags
;
if
(
handler
->
clone_flags
&
CLONE_NEWUSER
)
{
...
...
@@ -1259,21 +1270,24 @@ static int lxc_spawn(struct lxc_handler *handler)
if
(
ret
<
0
)
goto
out_delete_net
;
handler
->
pid
=
lxc_clone
(
do_start
,
handler
,
flags
);
if
(
fork_before_clone
)
handler
->
pid
=
lxc_fork_attach_clone
(
do_start
,
handler
,
flags
|
CLONE_PARENT
);
else
handler
->
pid
=
lxc_clone
(
do_start
,
handler
,
flags
);
if
(
handler
->
pid
<
0
)
{
SYSERROR
(
"Failed to clone a new set of namespaces."
);
goto
out_delete_net
;
}
TRACE
(
"Cloned child process %d"
,
handler
->
pid
);
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
if
(
flags
&
ns_info
[
i
].
clone_flag
)
INFO
(
"Cloned %s
.
"
,
ns_info
[
i
].
flag_name
);
INFO
(
"Cloned %s"
,
ns_info
[
i
].
flag_name
);
if
(
!
preserve_ns
(
handler
->
nsfd
,
handler
->
clone_flags
|
preserve_mask
,
handler
->
pid
))
INFO
(
"Failed to preserve namespace for lxc.hook.stop."
);
if
(
attach_ns
(
saved_ns_fd
))
WARN
(
"Failed to restore saved namespaces."
);
if
(
!
preserve_ns
(
handler
->
nsfd
,
handler
->
clone_flags
&
~
CLONE_NEWNET
,
handler
->
pid
))
{
ERROR
(
"Failed to preserve cloned namespaces for lxc.hook.stop"
);
goto
out_delete_net
;
}
lxc_sync_fini_child
(
handler
);
...
...
@@ -1283,9 +1297,14 @@ static int lxc_spawn(struct lxc_handler *handler)
* mapped to something else on the host.) later to become a valid uid
* again.
*/
if
(
wants_to_map_ids
&&
lxc_map_ids
(
id_map
,
handler
->
pid
))
{
ERROR
(
"Failed to set up id mapping."
);
goto
out_delete_net
;
if
(
wants_to_map_ids
)
{
if
(
!
handler
->
conf
->
inherit_ns
[
LXC_NS_USER
])
{
ret
=
lxc_map_ids
(
id_map
,
handler
->
pid
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to set up id mapping."
);
goto
out_delete_net
;
}
}
}
if
(
lxc_sync_wake_child
(
handler
,
LXC_SYNC_STARTUP
))
...
...
@@ -1309,24 +1328,27 @@ static int lxc_spawn(struct lxc_handler *handler)
if
(
!
cgroup_chown
(
handler
))
goto
out_delete_net
;
handler
->
netnsfd
=
lxc_preserve_ns
(
handler
->
pid
,
"net"
);
if
(
handler
->
netnsfd
<
0
)
{
ERROR
(
"Failed to preserve network namespace"
);
/* Now we're ready to preserve the network namespace */
ret
=
lxc_preserve_ns
(
handler
->
pid
,
"net"
);
if
(
ret
<
0
)
{
ERROR
(
"%s - Failed to preserve net namespace"
,
strerror
(
errno
));
goto
out_delete_net
;
}
handler
->
nsfd
[
LXC_NS_NET
]
=
ret
;
DEBUG
(
"Preserved net namespace via fd %d"
,
ret
);
/* Create the network configuration. */
if
(
handler
->
clone_flags
&
CLONE_NEWNET
)
{
if
(
lxc_network_move_created_netdev_priv
(
handler
->
lxcpath
,
handler
->
name
,
&
handler
->
conf
->
network
,
&
conf
->
network
,
handler
->
pid
))
{
ERROR
(
"Failed to create the configured network."
);
goto
out_delete_net
;
}
if
(
lxc_create_network_unpriv
(
handler
->
lxcpath
,
handler
->
name
,
&
handler
->
conf
->
network
,
&
conf
->
network
,
handler
->
pid
))
{
ERROR
(
"Failed to create the configured network."
);
goto
out_delete_net
;
...
...
@@ -1344,7 +1366,7 @@ static int lxc_spawn(struct lxc_handler *handler)
if
(
lxc_sync_barrier_child
(
handler
,
LXC_SYNC_POST_CONFIGURE
))
goto
out_delete_net
;
if
(
!
lxc_list_empty
(
&
handler
->
conf
->
limits
)
&&
setup_resource_limits
(
&
handler
->
conf
->
limits
,
handler
->
pid
))
{
if
(
!
lxc_list_empty
(
&
conf
->
limits
)
&&
setup_resource_limits
(
&
conf
->
limits
,
handler
->
pid
))
{
ERROR
(
"failed to setup resource limits for '%s'"
,
name
);
goto
out_delete_net
;
}
...
...
@@ -1366,7 +1388,7 @@ static int lxc_spawn(struct lxc_handler *handler)
SYSERROR
(
"Failed to set environment variable: LXC_PID=%s."
,
pidstr
);
/* Run any host-side start hooks */
if
(
run_lxc_hooks
(
name
,
"start-host"
,
handler
->
conf
,
handler
->
lxcpath
,
NULL
))
{
if
(
run_lxc_hooks
(
name
,
"start-host"
,
conf
,
handler
->
lxcpath
,
NULL
))
{
ERROR
(
"Failed to run lxc.hook.start-host for container
\"
%s
\"
."
,
name
);
return
-
1
;
}
...
...
@@ -1380,6 +1402,14 @@ static int lxc_spawn(struct lxc_handler *handler)
if
(
lxc_sync_barrier_child
(
handler
,
LXC_SYNC_READY_START
))
return
-
1
;
ret
=
lxc_preserve_ns
(
handler
->
pid
,
"cgroup"
);
if
(
ret
<
0
)
{
ERROR
(
"%s - Failed to preserve cgroup namespace"
,
strerror
(
errno
));
goto
out_delete_net
;
}
handler
->
nsfd
[
LXC_NS_CGROUP
]
=
ret
;
DEBUG
(
"Preserved cgroup namespace via fd %d"
,
ret
);
if
(
lxc_network_recv_name_and_ifindex_from_child
(
handler
)
<
0
)
{
ERROR
(
"Failed to receive names and ifindices for network "
"devices from child"
);
...
...
@@ -1391,7 +1421,7 @@ static int lxc_spawn(struct lxc_handler *handler)
* been recorded. The corresponding structs have now all been filled. So
* log them for debugging purposes.
*/
lxc_log_configured_netdevs
(
handler
->
conf
);
lxc_log_configured_netdevs
(
conf
);
/* Read tty fds allocated by child. */
if
(
lxc_recv_ttys_from_child
(
handler
)
<
0
)
{
...
...
@@ -1427,11 +1457,6 @@ out_abort:
handler
->
pinfd
=
-
1
;
}
if
(
handler
->
netnsfd
>=
0
)
{
close
(
handler
->
netnsfd
);
handler
->
netnsfd
=
-
1
;
}
return
-
1
;
}
...
...
@@ -1450,7 +1475,6 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
handler
->
ops
=
ops
;
handler
->
data
=
data
;
handler
->
backgrounded
=
backgrounded
;
handler
->
netnsfd
=
-
1
;
if
(
!
attach_block_device
(
handler
->
conf
))
{
ERROR
(
"Failed to attach block device."
);
...
...
@@ -1480,6 +1504,11 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
ERROR
(
"Failed to spawn container
\"
%s
\"
."
,
name
);
goto
out_detach_blockdev
;
}
/* close parent side of data socket */
close
(
handler
->
data_sock
[
0
]);
handler
->
data_sock
[
0
]
=
-
1
;
close
(
handler
->
data_sock
[
1
]);
handler
->
data_sock
[
1
]
=
-
1
;
handler
->
conf
->
reboot
=
0
;
...
...
src/lxc/start.h
View file @
2ed797da
...
...
@@ -40,9 +40,6 @@ struct lxc_handler {
/* The clone flags that were requested. */
int
clone_flags
;
/* File descriptors referring to the network namespace of the container. */
int
netnsfd
;
/* File descriptor to pin the rootfs for privileged containers. */
int
pinfd
;
...
...
@@ -67,10 +64,10 @@ struct lxc_handler {
/* Socketpair to synchronize processes during container creation. */
int
sync_sock
[
2
];
/*
The name of the container.
*/
char
*
name
;
/*
Pointer to the name of the container. Do not free!
*/
c
onst
c
har
*
name
;
/*
The path the container is running in.
*/
/*
Pointer to the path the container. Do not free!
*/
const
char
*
lxcpath
;
/* Whether the container's startup process euid is 0. */
...
...
src/lxc/tools/lxc_start.c
View file @
2ed797da
...
...
@@ -89,53 +89,6 @@ 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
)
{
...
...
@@ -201,16 +154,18 @@ Options :\n\
int
main
(
int
argc
,
char
*
argv
[])
{
int
err
=
EXIT_FAILURE
;
int
i
;
struct
lxc_conf
*
conf
;
struct
lxc_log
log
;
const
char
*
lxcpath
;
char
*
const
*
args
;
struct
lxc_container
*
c
;
int
err
=
EXIT_FAILURE
;
char
*
rcfile
=
NULL
;
char
*
const
default_args
[]
=
{
"/sbin/init"
,
NULL
,
};
struct
lxc_container
*
c
;
lxc_list_init
(
&
defines
);
...
...
@@ -236,14 +191,13 @@ int main(int argc, char *argv[])
exit
(
err
);
lxc_log_options_no_override
();
if
(
access
(
my_args
.
lxcpath
[
0
],
O_RDONLY
)
<
0
)
{
lxcpath
=
my_args
.
lxcpath
[
0
];
if
(
access
(
lxcpath
,
O_RDONLY
)
<
0
)
{
if
(
!
my_args
.
quiet
)
fprintf
(
stderr
,
"You lack access to %s
\n
"
,
my_args
.
lxcpath
[
0
]
);
fprintf
(
stderr
,
"You lack access to %s
\n
"
,
lxcpath
);
exit
(
err
);
}
const
char
*
lxcpath
=
my_args
.
lxcpath
[
0
];
/* REMOVE IN LXC 3.0 */
setenv
(
"LXC_UPDATE_CONFIG_FORMAT"
,
"1"
,
0
);
...
...
@@ -326,16 +280,6 @@ int main(int argc, char *argv[])
goto
out
;
}
if
(
ensure_path
(
&
conf
->
console
.
path
,
my_args
.
console
)
<
0
)
{
ERROR
(
"failed to ensure console path '%s'"
,
my_args
.
console
);
goto
out
;
}
if
(
ensure_path
(
&
conf
->
console
.
log_path
,
my_args
.
console_log
)
<
0
)
{
ERROR
(
"failed to ensure console log '%s'"
,
my_args
.
console_log
);
goto
out
;
}
if
(
my_args
.
pidfile
!=
NULL
)
{
if
(
ensure_path
(
&
c
->
pidfile
,
my_args
.
pidfile
)
<
0
)
{
ERROR
(
"failed to ensure pidfile '%s'"
,
my_args
.
pidfile
);
...
...
@@ -343,19 +287,26 @@ int main(int argc, char *argv[])
}
}
int
i
;
for
(
i
=
0
;
i
<
LXC_NS_MAX
;
i
++
)
{
if
(
my_args
.
share_ns
[
i
]
==
NULL
)
const
char
*
key
,
*
value
;
value
=
my_args
.
share_ns
[
i
];
if
(
!
value
)
continue
;
int
pid
=
pid_from_lxcname
(
my_args
.
share_ns
[
i
],
lxcpath
);
if
(
pid
<
1
)
goto
out
;
if
(
i
==
LXC_NS_NET
)
key
=
"lxc.namespace.net"
;
else
if
(
i
==
LXC_NS_IPC
)
key
=
"lxc.namespace.ipc"
;
else
if
(
i
==
LXC_NS_UTS
)
key
=
"lxc.namespace.uts"
;
else
if
(
i
==
LXC_NS_PID
)
key
=
"lxc.namespace.pid"
;
else
continue
;
int
fd
=
open_ns
(
pid
,
ns_info
[
i
].
proc_name
);
if
(
fd
<
0
)
if
(
!
c
->
set_config_item
(
c
,
key
,
value
))
goto
out
;
conf
->
inherit_ns_fd
[
i
]
=
fd
;
}
if
(
!
my_args
.
daemonize
)
{
...
...
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