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
c8a5adcd
Unverified
Commit
c8a5adcd
authored
Feb 25, 2018
by
Stéphane Graber
Committed by
GitHub
Feb 25, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2186 from brauner/2018-02-22/make_confile_reading_thread_safe
tree-wide: thread-safety improvements
parents
1401329e
106f1f38
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
521 additions
and
370 deletions
+521
-370
Makefile.am
src/lxc/Makefile.am
+1
-1
cgfsng.c
src/lxc/cgroups/cgfsng.c
+11
-5
lxc_user_nic.c
src/lxc/cmd/lxc_user_nic.c
+1
-0
confile.c
src/lxc/confile.c
+11
-7
confile.h
src/lxc/confile.h
+1
-1
criu.c
src/lxc/criu.c
+11
-11
error.h
src/lxc/error.h
+1
-0
lxccontainer.c
src/lxc/lxccontainer.c
+370
-285
lxclock.c
src/lxc/lxclock.c
+8
-7
network.c
src/lxc/network.c
+9
-9
parse.c
src/lxc/parse.c
+76
-3
parse.h
src/lxc/parse.h
+13
-0
utils.c
src/lxc/utils.c
+7
-34
utils.h
src/lxc/utils.h
+1
-7
No files found.
src/lxc/Makefile.am
View file @
c8a5adcd
...
@@ -278,7 +278,7 @@ lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c tools/tool_uti
...
@@ -278,7 +278,7 @@ lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c tools/tool_uti
# Binaries shipping with liblxc
# Binaries shipping with liblxc
init_lxc_SOURCES
=
cmd/lxc_init.c
init_lxc_SOURCES
=
cmd/lxc_init.c
lxc_monitord_SOURCES
=
cmd/lxc_monitord.c
lxc_monitord_SOURCES
=
cmd/lxc_monitord.c
lxc_user_nic_SOURCES
=
cmd/lxc_user_nic.c namespace.c network.c
lxc_user_nic_SOURCES
=
cmd/lxc_user_nic.c namespace.c network.c
parse.c
lxc_usernsexec_SOURCES
=
cmd/lxc_usernsexec.c
lxc_usernsexec_SOURCES
=
cmd/lxc_usernsexec.c
if
ENABLE_DEPRECATED
if
ENABLE_DEPRECATED
...
...
src/lxc/cgroups/cgfsng.c
View file @
c8a5adcd
...
@@ -327,7 +327,7 @@ struct hierarchy *get_hierarchy(const char *c)
...
@@ -327,7 +327,7 @@ struct hierarchy *get_hierarchy(const char *c)
!
hierarchies
[
i
]
->
controllers
[
0
])
!
hierarchies
[
i
]
->
controllers
[
0
])
return
hierarchies
[
i
];
return
hierarchies
[
i
];
return
NULL
;
continue
;
}
}
if
(
string_in_list
(
hierarchies
[
i
]
->
controllers
,
c
))
if
(
string_in_list
(
hierarchies
[
i
]
->
controllers
,
c
))
...
@@ -1306,8 +1306,11 @@ static bool cg_hybrid_init(void)
...
@@ -1306,8 +1306,11 @@ static bool cg_hybrid_init(void)
controller_list
=
cg_unified_get_controllers
(
cgv2_ctrl_path
);
controller_list
=
cg_unified_get_controllers
(
cgv2_ctrl_path
);
free
(
cgv2_ctrl_path
);
free
(
cgv2_ctrl_path
);
if
(
!
controller_list
)
if
(
!
controller_list
)
{
controller_list
=
cg_unified_make_empty_controller
();
controller_list
=
cg_unified_make_empty_controller
();
CGFSNG_DEBUG
(
"No controllers are enabled for "
"delegation in the unified hierarchy
\n
"
);
}
}
}
new
=
add_hierarchy
(
controller_list
,
mountpoint
,
base_cgroup
,
type
);
new
=
add_hierarchy
(
controller_list
,
mountpoint
,
base_cgroup
,
type
);
...
@@ -2365,13 +2368,16 @@ static bool cgfsng_unfreeze(void *hdata)
...
@@ -2365,13 +2368,16 @@ static bool cgfsng_unfreeze(void *hdata)
return
true
;
return
true
;
}
}
static
const
char
*
cgfsng_get_cgroup
(
void
*
hdata
,
const
char
*
subsystem
)
static
const
char
*
cgfsng_get_cgroup
(
void
*
hdata
,
const
char
*
controller
)
{
{
struct
hierarchy
*
h
;
struct
hierarchy
*
h
;
h
=
get_hierarchy
(
subsystem
);
h
=
get_hierarchy
(
controller
);
if
(
!
h
)
if
(
!
h
)
{
SYSERROR
(
"Failed to find hierarchy for controller
\"
%s
\"
"
,
controller
?
controller
:
"(null)"
);
return
NULL
;
return
NULL
;
}
return
h
->
fullcgpath
?
h
->
fullcgpath
+
strlen
(
h
->
mountpoint
)
:
NULL
;
return
h
->
fullcgpath
?
h
->
fullcgpath
+
strlen
(
h
->
mountpoint
)
:
NULL
;
}
}
...
...
src/lxc/cmd/lxc_user_nic.c
View file @
c8a5adcd
...
@@ -48,6 +48,7 @@
...
@@ -48,6 +48,7 @@
#include "config.h"
#include "config.h"
#include "namespace.h"
#include "namespace.h"
#include "network.h"
#include "network.h"
#include "parse.h"
#include "utils.h"
#include "utils.h"
#define usernic_debug_stream(stream, format, ...) \
#define usernic_debug_stream(stream, format, ...) \
...
...
src/lxc/confile.c
View file @
c8a5adcd
...
@@ -2334,7 +2334,7 @@ int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
...
@@ -2334,7 +2334,7 @@ int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include)
if
(
!
conf
->
rcfile
)
if
(
!
conf
->
rcfile
)
conf
->
rcfile
=
strdup
(
file
);
conf
->
rcfile
=
strdup
(
file
);
return
lxc_file_for_each_line
(
file
,
parse_line
,
&
c
);
return
lxc_file_for_each_line
_mmap
(
file
,
parse_line
,
&
c
);
}
}
int
lxc_config_define_add
(
struct
lxc_list
*
defines
,
char
*
arg
)
int
lxc_config_define_add
(
struct
lxc_list
*
defines
,
char
*
arg
)
...
@@ -2417,17 +2417,21 @@ signed long lxc_config_parse_arch(const char *arch)
...
@@ -2417,17 +2417,21 @@ signed long lxc_config_parse_arch(const char *arch)
}
}
/* Write out a configuration file. */
/* Write out a configuration file. */
void
write_config
(
FILE
*
fout
,
struct
lxc_conf
*
c
)
int
write_config
(
int
fd
,
const
struct
lxc_conf
*
conf
)
{
{
int
ret
;
int
ret
;
size_t
len
=
c
->
unexpanded_len
;
size_t
len
=
c
onf
->
unexpanded_len
;
if
(
!
len
)
if
(
len
==
0
)
return
;
return
0
;
ret
=
fwrite
(
c
->
unexpanded_config
,
1
,
len
,
fout
);
ret
=
lxc_write_nointr
(
fd
,
conf
->
unexpanded_config
,
len
);
if
(
ret
!=
len
)
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to write configuration file"
);
SYSERROR
(
"Failed to write configuration file"
);
return
-
1
;
}
return
0
;
}
}
bool
do_append_unexp_config_line
(
struct
lxc_conf
*
conf
,
const
char
*
key
,
bool
do_append_unexp_config_line
(
struct
lxc_conf
*
conf
,
const
char
*
key
,
...
...
src/lxc/confile.h
View file @
c8a5adcd
...
@@ -93,7 +93,7 @@ extern signed long lxc_config_parse_arch(const char *arch);
...
@@ -93,7 +93,7 @@ extern signed long lxc_config_parse_arch(const char *arch);
extern
int
lxc_clear_config_item
(
struct
lxc_conf
*
c
,
const
char
*
key
);
extern
int
lxc_clear_config_item
(
struct
lxc_conf
*
c
,
const
char
*
key
);
extern
void
write_config
(
FILE
*
fout
,
struct
lxc_conf
*
c
);
extern
int
write_config
(
int
fd
,
const
struct
lxc_conf
*
conf
);
extern
bool
do_append_unexp_config_line
(
struct
lxc_conf
*
conf
,
const
char
*
key
,
extern
bool
do_append_unexp_config_line
(
struct
lxc_conf
*
conf
,
const
char
*
key
,
const
char
*
v
);
const
char
*
v
);
...
...
src/lxc/criu.c
View file @
c8a5adcd
...
@@ -717,13 +717,13 @@ bool __criu_check_feature(uint64_t *features_to_check)
...
@@ -717,13 +717,13 @@ bool __criu_check_feature(uint64_t *features_to_check)
* LXC checking only for 'uffd' makes not much sense. */
* LXC checking only for 'uffd' makes not much sense. */
args
[
3
]
=
"uffd-noncoop"
;
args
[
3
]
=
"uffd-noncoop"
;
else
else
exit
(
1
);
_exit
(
EXIT_FAILURE
);
null_stdfds
();
null_stdfds
();
execvp
(
"criu"
,
args
);
execvp
(
"criu"
,
args
);
SYSERROR
(
"Failed to exec
\"
criu
\"
"
);
SYSERROR
(
"Failed to exec
\"
criu
\"
"
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
}
ret
=
wait_for_pid
(
pid
);
ret
=
wait_for_pid
(
pid
);
...
@@ -785,14 +785,14 @@ static bool criu_version_ok(char **version)
...
@@ -785,14 +785,14 @@ static bool criu_version_ok(char **version)
close
(
STDERR_FILENO
);
close
(
STDERR_FILENO
);
if
(
dup2
(
pipes
[
1
],
STDOUT_FILENO
)
<
0
)
if
(
dup2
(
pipes
[
1
],
STDOUT_FILENO
)
<
0
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
path
=
on_path
(
"criu"
,
NULL
);
path
=
on_path
(
"criu"
,
NULL
);
if
(
!
path
)
if
(
!
path
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
execv
(
path
,
args
);
execv
(
path
,
args
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
else
{
}
else
{
FILE
*
f
;
FILE
*
f
;
char
*
tmp
;
char
*
tmp
;
...
@@ -923,7 +923,7 @@ out_unlock:
...
@@ -923,7 +923,7 @@ out_unlock:
}
}
/* do_restore never returns, the calling process is used as the monitor process.
/* do_restore never returns, the calling process is used as the monitor process.
* do_restore calls exit() if it fails.
* do_restore calls
_
exit() if it fails.
*/
*/
static
void
do_restore
(
struct
lxc_container
*
c
,
int
status_pipe
,
struct
migrate_opts
*
opts
,
char
*
criu_version
)
static
void
do_restore
(
struct
lxc_container
*
c
,
int
status_pipe
,
struct
migrate_opts
*
opts
,
char
*
criu_version
)
{
{
...
@@ -1140,7 +1140,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
...
@@ -1140,7 +1140,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
if
(
ret
)
if
(
ret
)
lxc_abort
(
c
->
name
,
handler
);
lxc_abort
(
c
->
name
,
handler
);
lxc_fini
(
c
->
name
,
handler
);
lxc_fini
(
c
->
name
,
handler
);
exit
(
ret
);
_
exit
(
ret
);
}
}
out_fini_handler:
out_fini_handler:
...
@@ -1165,7 +1165,7 @@ out:
...
@@ -1165,7 +1165,7 @@ out:
close
(
status_pipe
);
close
(
status_pipe
);
}
}
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
}
static
int
save_tty_major_minor
(
char
*
directory
,
struct
lxc_container
*
c
,
char
*
tty_id
,
int
len
)
static
int
save_tty_major_minor
(
char
*
directory
,
struct
lxc_container
*
c
,
char
*
tty_id
,
int
len
)
...
@@ -1256,7 +1256,7 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
...
@@ -1256,7 +1256,7 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
h
.
name
=
c
->
name
;
h
.
name
=
c
->
name
;
if
(
!
cgroup_init
(
&
h
))
{
if
(
!
cgroup_init
(
&
h
))
{
ERROR
(
"failed to cgroup_init()"
);
ERROR
(
"failed to cgroup_init()"
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
}
os
.
pipefd
=
criuout
[
1
];
os
.
pipefd
=
criuout
[
1
];
...
@@ -1269,13 +1269,13 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
...
@@ -1269,13 +1269,13 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
ret
=
save_tty_major_minor
(
opts
->
directory
,
c
,
os
.
tty_id
,
sizeof
(
os
.
tty_id
));
ret
=
save_tty_major_minor
(
opts
->
directory
,
c
,
os
.
tty_id
,
sizeof
(
os
.
tty_id
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
free
(
criu_version
);
free
(
criu_version
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* exec_criu() returning is an error */
/* exec_criu() returning is an error */
exec_criu
(
&
os
);
exec_criu
(
&
os
);
free
(
criu_version
);
free
(
criu_version
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
else
{
}
else
{
int
status
;
int
status
;
ssize_t
n
;
ssize_t
n
;
...
...
src/lxc/error.h
View file @
c8a5adcd
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#define __LXC_ERROR_H
#define __LXC_ERROR_H
#define LXC_CLONE_ERROR "Failed to clone a new set of namespaces"
#define LXC_CLONE_ERROR "Failed to clone a new set of namespaces"
#define LXC_UNPRIV_EOPNOTSUPP "the requested function %s is not currently supported with unprivileged containers"
extern
int
lxc_error_set_and_log
(
int
pid
,
int
status
);
extern
int
lxc_error_set_and_log
(
int
pid
,
int
status
);
...
...
src/lxc/lxccontainer.c
View file @
c8a5adcd
...
@@ -49,6 +49,7 @@
...
@@ -49,6 +49,7 @@
#include "confile_utils.h"
#include "confile_utils.h"
#include "console.h"
#include "console.h"
#include "criu.h"
#include "criu.h"
#include "error.h"
#include "initutils.h"
#include "initutils.h"
#include "log.h"
#include "log.h"
#include "lxc.h"
#include "lxc.h"
...
@@ -57,6 +58,7 @@
...
@@ -57,6 +58,7 @@
#include "monitor.h"
#include "monitor.h"
#include "namespace.h"
#include "namespace.h"
#include "network.h"
#include "network.h"
#include "parse.h"
#include "start.h"
#include "start.h"
#include "state.h"
#include "state.h"
#include "storage.h"
#include "storage.h"
...
@@ -69,7 +71,7 @@
...
@@ -69,7 +71,7 @@
/* major()/minor() */
/* major()/minor() */
#ifdef MAJOR_IN_MKDEV
#ifdef MAJOR_IN_MKDEV
#
include <sys/mkdev.h>
#include <sys/mkdev.h>
#endif
#endif
#if HAVE_IFADDRS_H
#if HAVE_IFADDRS_H
...
@@ -84,19 +86,15 @@
...
@@ -84,19 +86,15 @@
#include <mntent.h>
#include <mntent.h>
#endif
#endif
#define MAX_BUFFER 4096
#define NOT_SUPPORTED_ERROR "the requested function %s is not currently supported with unprivileged containers"
/* Define faccessat() if missing from the C library */
/* Define faccessat() if missing from the C library */
#ifndef HAVE_FACCESSAT
#ifndef HAVE_FACCESSAT
static
int
faccessat
(
int
__fd
,
const
char
*
__file
,
int
__type
,
int
__flag
)
static
int
faccessat
(
int
__fd
,
const
char
*
__file
,
int
__type
,
int
__flag
)
{
{
#ifdef __NR_faccessat
#ifdef __NR_faccessat
return
syscall
(
__NR_faccessat
,
__fd
,
__file
,
__type
,
__flag
);
return
syscall
(
__NR_faccessat
,
__fd
,
__file
,
__type
,
__flag
);
#else
#else
errno
=
ENOSYS
;
errno
=
ENOSYS
;
return
-
1
;
return
-
1
;
#endif
#endif
}
}
#endif
#endif
...
@@ -115,85 +113,91 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
...
@@ -115,85 +113,91 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
static
bool
config_file_exists
(
const
char
*
lxcpath
,
const
char
*
cname
)
static
bool
config_file_exists
(
const
char
*
lxcpath
,
const
char
*
cname
)
{
{
/* $lxcpath + '/' + $cname + '/config' + \0 */
int
ret
;
int
ret
,
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
9
;
size_t
len
;
char
*
fname
=
alloca
(
len
)
;
char
*
fname
;
ret
=
snprintf
(
fname
,
len
,
"%s/%s/config"
,
lxcpath
,
cname
);
/* $lxcpath + '/' + $cname + '/config' + \0 */
if
(
ret
<
0
||
ret
>=
len
)
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
9
;
fname
=
alloca
(
len
);
ret
=
snprintf
(
fname
,
len
,
"%s/%s/config"
,
lxcpath
,
cname
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
return
false
;
return
false
;
return
file_exists
(
fname
);
return
file_exists
(
fname
);
}
}
/*
/* A few functions to help detect when a container creation failed. If a
* A few functions to help detect when a container creation failed.
* container creation was killed partway through, then trying to actually start
* If a container creation was killed partway through, then trying
* that container could harm the host. We detect this by creating a 'partial'
* to actually start that container could harm the host. We detect
* file under the container directory, and keeping an advisory lock. When
* this by creating a 'partial' file under the container directory,
* container creation completes, we remove that file. When we load or try to
* and keeping an advisory lock. When container creation completes,
* start a container, if we find that file, without a flock, we remove the
* we remove that file. When we load or try to start a container, if
* container.
* we find that file, without a flock, we remove the container.
*/
*/
static
int
ongoing_create
(
struct
lxc_container
*
c
)
static
int
ongoing_create
(
struct
lxc_container
*
c
)
{
{
int
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
10
;
char
*
path
=
alloca
(
len
);
int
fd
,
ret
;
int
fd
,
ret
;
size_t
len
;
char
*
path
;
struct
flock
lk
;
struct
flock
lk
;
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
10
;
path
=
alloca
(
len
);
ret
=
snprintf
(
path
,
len
,
"%s/%s/partial"
,
c
->
config_path
,
c
->
name
);
ret
=
snprintf
(
path
,
len
,
"%s/%s/partial"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
len
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
ERROR
(
"Error writing partial pathname"
);
return
-
1
;
return
-
1
;
}
if
(
!
file_exists
(
path
))
if
(
!
file_exists
(
path
))
return
0
;
return
0
;
fd
=
open
(
path
,
O_RDWR
);
fd
=
open
(
path
,
O_RDWR
);
if
(
fd
<
0
)
{
if
(
fd
<
0
)
/* give benefit of the doubt */
SYSERROR
(
"Error opening partial file"
);
return
0
;
return
0
;
}
lk
.
l_type
=
F_WRLCK
;
lk
.
l_type
=
F_WRLCK
;
lk
.
l_whence
=
SEEK_SET
;
lk
.
l_whence
=
SEEK_SET
;
lk
.
l_start
=
0
;
lk
.
l_start
=
0
;
lk
.
l_len
=
0
;
lk
.
l_len
=
0
;
lk
.
l_pid
=
-
1
;
lk
.
l_pid
=
-
1
;
if
(
fcntl
(
fd
,
F_GETLK
,
&
lk
)
==
0
&&
lk
.
l_pid
!=
-
1
)
{
ret
=
fcntl
(
fd
,
F_GETLK
,
&
lk
);
close
(
fd
);
if
(
ret
==
0
&&
lk
.
l_pid
!=
-
1
)
{
/* create is still ongoing */
/* create is still ongoing */
close
(
fd
);
return
1
;
return
1
;
}
}
/* create completed but partial is still there. */
close
(
fd
);
/* Create completed but partial is still there. */
return
2
;
return
2
;
}
}
static
int
create_partial
(
struct
lxc_container
*
c
)
static
int
create_partial
(
struct
lxc_container
*
c
)
{
{
/* $lxcpath + '/' + $name + '/partial' + \0 */
int
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
10
;
char
*
path
=
alloca
(
len
);
int
fd
,
ret
;
int
fd
,
ret
;
size_t
len
;
char
*
path
;
struct
flock
lk
;
struct
flock
lk
;
/* $lxcpath + '/' + $name + '/partial' + \0 */
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
10
;
path
=
alloca
(
len
);
ret
=
snprintf
(
path
,
len
,
"%s/%s/partial"
,
c
->
config_path
,
c
->
name
);
ret
=
snprintf
(
path
,
len
,
"%s/%s/partial"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
len
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
ERROR
(
"Error writing partial pathname"
);
return
-
1
;
return
-
1
;
}
if
((
fd
=
open
(
path
,
O_RDWR
|
O_CREAT
|
O_EXCL
,
0755
))
<
0
)
{
fd
=
open
(
path
,
O_RDWR
|
O_CREAT
|
O_EXCL
,
0755
);
SYSERROR
(
"Error creating partial file"
);
if
(
fd
<
0
)
return
-
1
;
return
-
1
;
}
lk
.
l_type
=
F_WRLCK
;
lk
.
l_type
=
F_WRLCK
;
lk
.
l_whence
=
SEEK_SET
;
lk
.
l_whence
=
SEEK_SET
;
lk
.
l_start
=
0
;
lk
.
l_start
=
0
;
lk
.
l_len
=
0
;
lk
.
l_len
=
0
;
if
(
fcntl
(
fd
,
F_SETLKW
,
&
lk
)
<
0
)
{
SYSERROR
(
"Error locking partial file %s"
,
path
);
ret
=
fcntl
(
fd
,
F_SETLKW
,
&
lk
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to lock partial file %s"
,
path
);
close
(
fd
);
close
(
fd
);
return
-
1
;
return
-
1
;
}
}
...
@@ -203,19 +207,21 @@ static int create_partial(struct lxc_container *c)
...
@@ -203,19 +207,21 @@ static int create_partial(struct lxc_container *c)
static
void
remove_partial
(
struct
lxc_container
*
c
,
int
fd
)
static
void
remove_partial
(
struct
lxc_container
*
c
,
int
fd
)
{
{
/* $lxcpath + '/' + $name + '/partial' + \0 */
int
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
10
;
char
*
path
=
alloca
(
len
);
int
ret
;
int
ret
;
size_t
len
;
char
*
path
;
close
(
fd
);
close
(
fd
);
/* $lxcpath + '/' + $name + '/partial' + \0 */
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
10
;
path
=
alloca
(
len
);
ret
=
snprintf
(
path
,
len
,
"%s/%s/partial"
,
c
->
config_path
,
c
->
name
);
ret
=
snprintf
(
path
,
len
,
"%s/%s/partial"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
len
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
ERROR
(
"Error writing partial pathname"
);
return
;
return
;
}
if
(
unlink
(
path
)
<
0
)
ret
=
unlink
(
path
);
SYSERROR
(
"Error unlink partial file %s"
,
path
);
if
(
ret
<
0
)
SYSERROR
(
"Failed to remove partial file %s"
,
path
);
}
}
/* LOCKING
/* LOCKING
...
@@ -247,41 +253,49 @@ static void lxc_container_free(struct lxc_container *c)
...
@@ -247,41 +253,49 @@ static void lxc_container_free(struct lxc_container *c)
free
(
c
->
configfile
);
free
(
c
->
configfile
);
c
->
configfile
=
NULL
;
c
->
configfile
=
NULL
;
free
(
c
->
error_string
);
free
(
c
->
error_string
);
c
->
error_string
=
NULL
;
c
->
error_string
=
NULL
;
if
(
c
->
slock
)
{
if
(
c
->
slock
)
{
lxc_putlock
(
c
->
slock
);
lxc_putlock
(
c
->
slock
);
c
->
slock
=
NULL
;
c
->
slock
=
NULL
;
}
}
if
(
c
->
privlock
)
{
if
(
c
->
privlock
)
{
lxc_putlock
(
c
->
privlock
);
lxc_putlock
(
c
->
privlock
);
c
->
privlock
=
NULL
;
c
->
privlock
=
NULL
;
}
}
free
(
c
->
name
);
free
(
c
->
name
);
c
->
name
=
NULL
;
c
->
name
=
NULL
;
if
(
c
->
lxc_conf
)
{
if
(
c
->
lxc_conf
)
{
lxc_conf_free
(
c
->
lxc_conf
);
lxc_conf_free
(
c
->
lxc_conf
);
c
->
lxc_conf
=
NULL
;
c
->
lxc_conf
=
NULL
;
}
}
free
(
c
->
config_path
);
free
(
c
->
config_path
);
c
->
config_path
=
NULL
;
c
->
config_path
=
NULL
;
free
(
c
);
free
(
c
);
}
}
/*
/* Consider the following case:
* Consider the following case:
*
freer | racing get()er
* |====================================================================|
==================================================================
* | freer | racing get()er |
lxc_container_put() | lxc_container_get()
* |====================================================================|
\ lxclock(c->privlock) | c->numthreads < 1? (no)
* | lxc_container_put() | lxc_container_get() |
\ c->numthreads = 0 | \ lxclock(c->privlock) -> waits
* | \ lxclock(c->privlock) | c->numthreads < 1? (no) |
\ lxcunlock() | \
* | \ c->numthreads = 0 | \ lxclock(c->privlock) -> waits |
\ lxc_container_free() | \ lxclock() returns
* | \ lxcunlock() | \ |
| \ c->numthreads < 1 -> return 0
* | \ lxc_container_free() | \ lxclock() returns |
\ \ (free stuff) |
* | | \ c->numthreads < 1 -> return 0 |
\ \ sem_destroy(privlock) |
* | \ \ (free stuff) | |
* | \ \ sem_destroy(privlock) | |
* |_______________________________|____________________________________|
*
* When the get()er checks numthreads the first time, one of the following
* When the get()er checks numthreads the first time, one of the following
* is true:
* is true:
* 1. freer has set numthreads = 0. get() returns 0
* 1. freer has set numthreads = 0. get() returns 0
...
@@ -314,6 +328,7 @@ int lxc_container_get(struct lxc_container *c)
...
@@ -314,6 +328,7 @@ int lxc_container_get(struct lxc_container *c)
c
->
numthreads
++
;
c
->
numthreads
++
;
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
return
1
;
return
1
;
}
}
...
@@ -321,37 +336,45 @@ int lxc_container_put(struct lxc_container *c)
...
@@ -321,37 +336,45 @@ int lxc_container_put(struct lxc_container *c)
{
{
if
(
!
c
)
if
(
!
c
)
return
-
1
;
return
-
1
;
if
(
container_mem_lock
(
c
))
if
(
container_mem_lock
(
c
))
return
-
1
;
return
-
1
;
if
(
--
c
->
numthreads
<
1
)
{
if
(
--
c
->
numthreads
<
1
)
{
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
lxc_container_free
(
c
);
lxc_container_free
(
c
);
return
1
;
return
1
;
}
}
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
return
0
;
return
0
;
}
}
static
bool
do_lxcapi_is_defined
(
struct
lxc_container
*
c
)
static
bool
do_lxcapi_is_defined
(
struct
lxc_container
*
c
)
{
{
int
statret
;
struct
stat
statbuf
;
struct
stat
statbuf
;
bool
ret
=
false
;
bool
ret
=
false
;
int
statret
;
if
(
!
c
)
if
(
!
c
)
return
false
;
return
false
;
if
(
container_mem_lock
(
c
))
if
(
container_mem_lock
(
c
))
return
false
;
return
false
;
if
(
!
c
->
configfile
)
if
(
!
c
->
configfile
)
goto
out
;
goto
on_error
;
statret
=
stat
(
c
->
configfile
,
&
statbuf
);
statret
=
stat
(
c
->
configfile
,
&
statbuf
);
if
(
statret
!=
0
)
if
(
statret
!=
0
)
goto
out
;
goto
on_error
;
ret
=
true
;
ret
=
true
;
o
ut
:
o
n_error
:
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
return
ret
;
return
ret
;
}
}
...
@@ -435,6 +458,7 @@ static const char *do_lxcapi_state(struct lxc_container *c)
...
@@ -435,6 +458,7 @@ static const char *do_lxcapi_state(struct lxc_container *c)
if
(
!
c
)
if
(
!
c
)
return
NULL
;
return
NULL
;
s
=
lxc_getstate
(
c
->
name
,
c
->
config_path
);
s
=
lxc_getstate
(
c
->
name
,
c
->
config_path
);
return
lxc_state2str
(
s
);
return
lxc_state2str
(
s
);
}
}
...
@@ -444,6 +468,7 @@ WRAP_API(const char *, lxcapi_state)
...
@@ -444,6 +468,7 @@ WRAP_API(const char *, lxcapi_state)
static
bool
is_stopped
(
struct
lxc_container
*
c
)
static
bool
is_stopped
(
struct
lxc_container
*
c
)
{
{
lxc_state_t
s
;
lxc_state_t
s
;
s
=
lxc_getstate
(
c
->
name
,
c
->
config_path
);
s
=
lxc_getstate
(
c
->
name
,
c
->
config_path
);
return
(
s
==
STOPPED
);
return
(
s
==
STOPPED
);
}
}
...
@@ -454,9 +479,11 @@ static bool do_lxcapi_is_running(struct lxc_container *c)
...
@@ -454,9 +479,11 @@ static bool do_lxcapi_is_running(struct lxc_container *c)
if
(
!
c
)
if
(
!
c
)
return
false
;
return
false
;
s
=
do_lxcapi_state
(
c
);
s
=
do_lxcapi_state
(
c
);
if
(
!
s
||
strcmp
(
s
,
"STOPPED"
)
==
0
)
if
(
!
s
||
strcmp
(
s
,
"STOPPED"
)
==
0
)
return
false
;
return
false
;
return
true
;
return
true
;
}
}
...
@@ -465,12 +492,14 @@ WRAP_API(bool, lxcapi_is_running)
...
@@ -465,12 +492,14 @@ WRAP_API(bool, lxcapi_is_running)
static
bool
do_lxcapi_freeze
(
struct
lxc_container
*
c
)
static
bool
do_lxcapi_freeze
(
struct
lxc_container
*
c
)
{
{
int
ret
;
int
ret
;
if
(
!
c
)
if
(
!
c
)
return
false
;
return
false
;
ret
=
lxc_freeze
(
c
->
name
,
c
->
config_path
);
ret
=
lxc_freeze
(
c
->
name
,
c
->
config_path
);
if
(
ret
)
if
(
ret
)
return
false
;
return
false
;
return
true
;
return
true
;
}
}
...
@@ -479,12 +508,14 @@ WRAP_API(bool, lxcapi_freeze)
...
@@ -479,12 +508,14 @@ WRAP_API(bool, lxcapi_freeze)
static
bool
do_lxcapi_unfreeze
(
struct
lxc_container
*
c
)
static
bool
do_lxcapi_unfreeze
(
struct
lxc_container
*
c
)
{
{
int
ret
;
int
ret
;
if
(
!
c
)
if
(
!
c
)
return
false
;
return
false
;
ret
=
lxc_unfreeze
(
c
->
name
,
c
->
config_path
);
ret
=
lxc_unfreeze
(
c
->
name
,
c
->
config_path
);
if
(
ret
)
if
(
ret
)
return
false
;
return
false
;
return
true
;
return
true
;
}
}
...
@@ -492,12 +523,10 @@ WRAP_API(bool, lxcapi_unfreeze)
...
@@ -492,12 +523,10 @@ WRAP_API(bool, lxcapi_unfreeze)
static
int
do_lxcapi_console_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
int
*
masterfd
)
static
int
do_lxcapi_console_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
int
*
masterfd
)
{
{
int
ttyfd
;
if
(
!
c
)
if
(
!
c
)
return
-
1
;
return
-
1
;
ttyfd
=
lxc_console_getfd
(
c
,
ttynum
,
masterfd
);
return
lxc_console_getfd
(
c
,
ttynum
,
masterfd
);
return
ttyfd
;
}
}
WRAP_API_2
(
int
,
lxcapi_console_getfd
,
int
*
,
int
*
)
WRAP_API_2
(
int
,
lxcapi_console_getfd
,
int
*
,
int
*
)
...
@@ -513,6 +542,7 @@ static int lxcapi_console(struct lxc_container *c, int ttynum, int stdinfd,
...
@@ -513,6 +542,7 @@ static int lxcapi_console(struct lxc_container *c, int ttynum, int stdinfd,
current_config
=
c
->
lxc_conf
;
current_config
=
c
->
lxc_conf
;
ret
=
lxc_console
(
c
,
ttynum
,
stdinfd
,
stdoutfd
,
stderrfd
,
escape
);
ret
=
lxc_console
(
c
,
ttynum
,
stdinfd
,
stdoutfd
,
stderrfd
,
escape
);
current_config
=
NULL
;
current_config
=
NULL
;
return
ret
;
return
ret
;
}
}
...
@@ -553,18 +583,22 @@ static bool load_config_locked(struct lxc_container *c, const char *fname)
...
@@ -553,18 +583,22 @@ static bool load_config_locked(struct lxc_container *c, const char *fname)
{
{
if
(
!
c
->
lxc_conf
)
if
(
!
c
->
lxc_conf
)
c
->
lxc_conf
=
lxc_conf_init
();
c
->
lxc_conf
=
lxc_conf_init
();
if
(
!
c
->
lxc_conf
)
if
(
!
c
->
lxc_conf
)
return
false
;
return
false
;
if
(
lxc_config_read
(
fname
,
c
->
lxc_conf
,
false
)
!=
0
)
if
(
lxc_config_read
(
fname
,
c
->
lxc_conf
,
false
)
!=
0
)
return
false
;
return
false
;
return
true
;
return
true
;
}
}
static
bool
do_lxcapi_load_config
(
struct
lxc_container
*
c
,
const
char
*
alt_file
)
static
bool
do_lxcapi_load_config
(
struct
lxc_container
*
c
,
const
char
*
alt_file
)
{
{
bool
ret
=
false
,
need_disklock
=
false
;
int
lret
;
int
lret
;
const
char
*
fname
;
const
char
*
fname
;
bool
need_disklock
=
false
,
ret
=
false
;
if
(
!
c
)
if
(
!
c
)
return
false
;
return
false
;
...
@@ -573,10 +607,10 @@ static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
...
@@ -573,10 +607,10 @@ static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
fname
=
alt_file
;
fname
=
alt_file
;
if
(
!
fname
)
if
(
!
fname
)
return
false
;
return
false
;
/*
* If we're reading something other than the container's config,
/* If we're reading something other than the container's config, we only
*
we only need to lock the in-memory container. If loading the
*
need to lock the in-memory container. If loading the container's
* con
tainer's con
fig file, take the disk lock.
* config file, take the disk lock.
*/
*/
if
(
strcmp
(
fname
,
c
->
configfile
)
==
0
)
if
(
strcmp
(
fname
,
c
->
configfile
)
==
0
)
need_disklock
=
true
;
need_disklock
=
true
;
...
@@ -594,6 +628,7 @@ static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
...
@@ -594,6 +628,7 @@ static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
container_disk_unlock
(
c
);
container_disk_unlock
(
c
);
else
else
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
return
ret
;
return
ret
;
}
}
...
@@ -603,12 +638,13 @@ static bool do_lxcapi_want_daemonize(struct lxc_container *c, bool state)
...
@@ -603,12 +638,13 @@ static bool do_lxcapi_want_daemonize(struct lxc_container *c, bool state)
{
{
if
(
!
c
||
!
c
->
lxc_conf
)
if
(
!
c
||
!
c
->
lxc_conf
)
return
false
;
return
false
;
if
(
container_mem_lock
(
c
))
{
ERROR
(
"Error getting mem lock"
);
if
(
container_mem_lock
(
c
))
return
false
;
return
false
;
}
c
->
daemonize
=
state
;
c
->
daemonize
=
state
;
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
return
true
;
return
true
;
}
}
...
@@ -618,18 +654,20 @@ static bool do_lxcapi_want_close_all_fds(struct lxc_container *c, bool state)
...
@@ -618,18 +654,20 @@ static bool do_lxcapi_want_close_all_fds(struct lxc_container *c, bool state)
{
{
if
(
!
c
||
!
c
->
lxc_conf
)
if
(
!
c
||
!
c
->
lxc_conf
)
return
false
;
return
false
;
if
(
container_mem_lock
(
c
))
{
ERROR
(
"Error getting mem lock"
);
if
(
container_mem_lock
(
c
))
return
false
;
return
false
;
}
c
->
lxc_conf
->
close_all_fds
=
state
;
c
->
lxc_conf
->
close_all_fds
=
state
;
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
return
true
;
return
true
;
}
}
WRAP_API_1
(
bool
,
lxcapi_want_close_all_fds
,
bool
)
WRAP_API_1
(
bool
,
lxcapi_want_close_all_fds
,
bool
)
static
bool
do_lxcapi_wait
(
struct
lxc_container
*
c
,
const
char
*
state
,
int
timeout
)
static
bool
do_lxcapi_wait
(
struct
lxc_container
*
c
,
const
char
*
state
,
int
timeout
)
{
{
int
ret
;
int
ret
;
...
@@ -646,13 +684,11 @@ static bool am_single_threaded(void)
...
@@ -646,13 +684,11 @@ static bool am_single_threaded(void)
{
{
struct
dirent
*
direntp
;
struct
dirent
*
direntp
;
DIR
*
dir
;
DIR
*
dir
;
int
count
=
0
;
int
count
=
0
;
dir
=
opendir
(
"/proc/self/task"
);
dir
=
opendir
(
"/proc/self/task"
);
if
(
!
dir
)
{
if
(
!
dir
)
INFO
(
"failed to open /proc/self/task"
);
return
false
;
return
false
;
}
while
((
direntp
=
readdir
(
dir
)))
{
while
((
direntp
=
readdir
(
dir
)))
{
if
(
!
strcmp
(
direntp
->
d_name
,
"."
))
if
(
!
strcmp
(
direntp
->
d_name
,
"."
))
...
@@ -660,24 +696,28 @@ static bool am_single_threaded(void)
...
@@ -660,24 +696,28 @@ static bool am_single_threaded(void)
if
(
!
strcmp
(
direntp
->
d_name
,
".."
))
if
(
!
strcmp
(
direntp
->
d_name
,
".."
))
continue
;
continue
;
if
(
++
count
>
1
)
if
(
++
count
>
1
)
break
;
break
;
}
}
closedir
(
dir
);
closedir
(
dir
);
return
count
==
1
;
return
count
==
1
;
}
}
static
void
push_arg
(
char
***
argp
,
char
*
arg
,
int
*
nargs
)
static
void
push_arg
(
char
***
argp
,
char
*
arg
,
int
*
nargs
)
{
{
char
**
argv
;
char
*
copy
;
char
*
copy
;
char
**
argv
;
do
{
do
{
copy
=
strdup
(
arg
);
copy
=
strdup
(
arg
);
}
while
(
!
copy
);
}
while
(
!
copy
);
do
{
do
{
argv
=
realloc
(
*
argp
,
(
*
nargs
+
2
)
*
sizeof
(
char
*
));
argv
=
realloc
(
*
argp
,
(
*
nargs
+
2
)
*
sizeof
(
char
*
));
}
while
(
!
argv
);
}
while
(
!
argv
);
*
argp
=
argv
;
*
argp
=
argv
;
argv
[
*
nargs
]
=
copy
;
argv
[
*
nargs
]
=
copy
;
(
*
nargs
)
++
;
(
*
nargs
)
++
;
...
@@ -687,9 +727,10 @@ static void push_arg(char ***argp, char *arg, int *nargs)
...
@@ -687,9 +727,10 @@ static void push_arg(char ***argp, char *arg, int *nargs)
static
char
**
split_init_cmd
(
const
char
*
incmd
)
static
char
**
split_init_cmd
(
const
char
*
incmd
)
{
{
size_t
len
;
size_t
len
;
int
nargs
=
0
;
char
*
copy
,
*
p
;
char
*
copy
,
*
p
,
*
saveptr
=
NULL
;
char
**
argv
;
char
**
argv
;
int
nargs
=
0
;
char
*
saveptr
=
NULL
;
if
(
!
incmd
)
if
(
!
incmd
)
return
NULL
;
return
NULL
;
...
@@ -697,20 +738,21 @@ static char **split_init_cmd(const char *incmd)
...
@@ -697,20 +738,21 @@ static char **split_init_cmd(const char *incmd)
len
=
strlen
(
incmd
)
+
1
;
len
=
strlen
(
incmd
)
+
1
;
copy
=
alloca
(
len
);
copy
=
alloca
(
len
);
strncpy
(
copy
,
incmd
,
len
);
strncpy
(
copy
,
incmd
,
len
);
copy
[
len
-
1
]
=
'\0'
;
copy
[
len
-
1
]
=
'\0'
;
do
{
do
{
argv
=
malloc
(
sizeof
(
char
*
));
argv
=
malloc
(
sizeof
(
char
*
));
}
while
(
!
argv
);
}
while
(
!
argv
);
argv
[
0
]
=
NULL
;
argv
[
0
]
=
NULL
;
for
(
p
=
strtok_r
(
copy
,
" "
,
&
saveptr
);
p
!=
NULL
;
for
(;
(
p
=
strtok_r
(
copy
,
" "
,
&
saveptr
));
copy
=
NULL
)
p
=
strtok_r
(
NULL
,
" "
,
&
saveptr
))
push_arg
(
&
argv
,
p
,
&
nargs
);
push_arg
(
&
argv
,
p
,
&
nargs
);
if
(
nargs
==
0
)
{
if
(
nargs
==
0
)
{
free
(
argv
);
free
(
argv
);
return
NULL
;
return
NULL
;
}
}
return
argv
;
return
argv
;
}
}
...
@@ -720,8 +762,10 @@ static void free_init_cmd(char **argv)
...
@@ -720,8 +762,10 @@ static void free_init_cmd(char **argv)
if
(
!
argv
)
if
(
!
argv
)
return
;
return
;
while
(
argv
[
i
])
while
(
argv
[
i
])
free
(
argv
[
i
++
]);
free
(
argv
[
i
++
]);
free
(
argv
);
free
(
argv
);
}
}
...
@@ -902,14 +946,14 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
...
@@ -902,14 +946,14 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
pid
=
fork
();
pid
=
fork
();
if
(
pid
<
0
)
{
if
(
pid
<
0
)
{
SYSERROR
(
"Failed to fork first child process"
);
SYSERROR
(
"Failed to fork first child process"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* second parent */
/* second parent */
if
(
pid
!=
0
)
{
if
(
pid
!=
0
)
{
free_init_cmd
(
init_cmd
);
free_init_cmd
(
init_cmd
);
lxc_free_handler
(
handler
);
lxc_free_handler
(
handler
);
exit
(
EXIT_SUCCESS
);
_
exit
(
EXIT_SUCCESS
);
}
}
/* second child */
/* second child */
...
@@ -918,7 +962,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
...
@@ -918,7 +962,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
ret
=
chdir
(
"/"
);
ret
=
chdir
(
"/"
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to change to
\"
/
\"
directory"
);
SYSERROR
(
"Failed to change to
\"
/
\"
directory"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
keepfds
[
0
]
=
handler
->
conf
->
maincmd_fd
;
keepfds
[
0
]
=
handler
->
conf
->
maincmd_fd
;
...
@@ -927,13 +971,13 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
...
@@ -927,13 +971,13 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
ret
=
lxc_check_inherited
(
conf
,
true
,
keepfds
,
ret
=
lxc_check_inherited
(
conf
,
true
,
keepfds
,
sizeof
(
keepfds
)
/
sizeof
(
keepfds
[
0
]));
sizeof
(
keepfds
)
/
sizeof
(
keepfds
[
0
]));
if
(
ret
<
0
)
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
/* redirect std{in,out,err} to /dev/null */
/* redirect std{in,out,err} to /dev/null */
ret
=
null_stdfds
();
ret
=
null_stdfds
();
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"Failed to redirect std{in,out,err} to /dev/null"
);
ERROR
(
"Failed to redirect std{in,out,err} to /dev/null"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* become session leader */
/* become session leader */
...
@@ -960,7 +1004,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
...
@@ -960,7 +1004,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
free_init_cmd
(
init_cmd
);
free_init_cmd
(
init_cmd
);
lxc_free_handler
(
handler
);
lxc_free_handler
(
handler
);
if
(
daemonize
)
if
(
daemonize
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
return
false
;
return
false
;
}
}
...
@@ -971,7 +1015,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
...
@@ -971,7 +1015,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
free_init_cmd
(
init_cmd
);
free_init_cmd
(
init_cmd
);
lxc_free_handler
(
handler
);
lxc_free_handler
(
handler
);
if
(
daemonize
)
if
(
daemonize
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
return
false
;
return
false
;
}
}
...
@@ -1042,9 +1086,9 @@ on_error:
...
@@ -1042,9 +1086,9 @@ on_error:
free_init_cmd
(
init_cmd
);
free_init_cmd
(
init_cmd
);
if
(
daemonize
&&
ret
!=
0
)
if
(
daemonize
&&
ret
!=
0
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
else
if
(
daemonize
)
else
if
(
daemonize
)
exit
(
EXIT_SUCCESS
);
_
exit
(
EXIT_SUCCESS
);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
return
false
;
return
false
;
...
@@ -1052,18 +1096,19 @@ on_error:
...
@@ -1052,18 +1096,19 @@ on_error:
return
true
;
return
true
;
}
}
static
bool
lxcapi_start
(
struct
lxc_container
*
c
,
int
useinit
,
char
*
const
argv
[])
static
bool
lxcapi_start
(
struct
lxc_container
*
c
,
int
useinit
,
char
*
const
argv
[])
{
{
bool
ret
;
bool
ret
;
current_config
=
c
?
c
->
lxc_conf
:
NULL
;
current_config
=
c
?
c
->
lxc_conf
:
NULL
;
ret
=
do_lxcapi_start
(
c
,
useinit
,
argv
);
ret
=
do_lxcapi_start
(
c
,
useinit
,
argv
);
current_config
=
NULL
;
current_config
=
NULL
;
return
ret
;
return
ret
;
}
}
/*
/* Note, there MUST be an ending NULL. */
* note there MUST be an ending NULL
*/
static
bool
lxcapi_startl
(
struct
lxc_container
*
c
,
int
useinit
,
...)
static
bool
lxcapi_startl
(
struct
lxc_container
*
c
,
int
useinit
,
...)
{
{
va_list
ap
;
va_list
ap
;
...
@@ -1079,16 +1124,13 @@ static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
...
@@ -1079,16 +1124,13 @@ static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
va_start
(
ap
,
useinit
);
va_start
(
ap
,
useinit
);
inargs
=
lxc_va_arg_list_to_argv
(
ap
,
0
,
1
);
inargs
=
lxc_va_arg_list_to_argv
(
ap
,
0
,
1
);
va_end
(
ap
);
va_end
(
ap
);
if
(
!
inargs
)
if
(
!
inargs
)
{
goto
on_error
;
ERROR
(
"Memory allocation error."
);
goto
out
;
}
/* pass NULL if no arguments were supplied */
/* pass NULL if no arguments were supplied */
bret
=
do_lxcapi_start
(
c
,
useinit
,
*
inargs
?
inargs
:
NULL
);
bret
=
do_lxcapi_start
(
c
,
useinit
,
*
inargs
?
inargs
:
NULL
);
o
ut
:
o
n_error
:
if
(
inargs
)
{
if
(
inargs
)
{
char
**
arg
;
char
**
arg
;
for
(
arg
=
inargs
;
*
arg
;
arg
++
)
for
(
arg
=
inargs
;
*
arg
;
arg
++
)
...
@@ -1097,6 +1139,7 @@ out:
...
@@ -1097,6 +1139,7 @@ out:
}
}
current_config
=
NULL
;
current_config
=
NULL
;
return
bret
;
return
bret
;
}
}
...
@@ -1116,48 +1159,56 @@ WRAP_API(bool, lxcapi_stop)
...
@@ -1116,48 +1159,56 @@ WRAP_API(bool, lxcapi_stop)
static
int
do_create_container_dir
(
const
char
*
path
,
struct
lxc_conf
*
conf
)
static
int
do_create_container_dir
(
const
char
*
path
,
struct
lxc_conf
*
conf
)
{
{
int
ret
=
-
1
,
lasterr
;
int
lasterr
;
char
*
p
=
alloca
(
strlen
(
path
)
+
1
);
size_t
len
;
char
*
p
;
int
ret
=
-
1
;
mode_t
mask
=
umask
(
0002
);
mode_t
mask
=
umask
(
0002
);
ret
=
mkdir
(
path
,
0770
);
ret
=
mkdir
(
path
,
0770
);
lasterr
=
errno
;
lasterr
=
errno
;
umask
(
mask
);
umask
(
mask
);
errno
=
lasterr
;
errno
=
lasterr
;
if
(
ret
)
{
if
(
ret
)
{
if
(
errno
==
EEXIST
)
if
(
errno
!=
EEXIST
)
ret
=
0
;
else
{
SYSERROR
(
"failed to create container path %s"
,
path
);
return
-
1
;
return
-
1
;
}
ret
=
0
;
}
}
len
=
strlen
(
path
);
p
=
alloca
(
len
+
1
);
strcpy
(
p
,
path
);
strcpy
(
p
,
path
);
if
(
!
lxc_list_empty
(
&
conf
->
id_map
)
&&
chown_mapped_root
(
p
,
conf
)
!=
0
)
{
if
(
!
lxc_list_empty
(
&
conf
->
id_map
))
{
ERROR
(
"Failed to chown container dir"
);
ret
=
chown_mapped_root
(
p
,
conf
);
ret
=
-
1
;
if
(
ret
<
0
)
ret
=
-
1
;
}
}
return
ret
;
return
ret
;
}
}
/*
/* Create the standard expected container dir. */
* create the standard expected container dir
*/
static
bool
create_container_dir
(
struct
lxc_container
*
c
)
static
bool
create_container_dir
(
struct
lxc_container
*
c
)
{
{
int
ret
;
size_t
len
;
char
*
s
;
char
*
s
;
int
len
,
ret
;
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
2
;
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
2
;
s
=
malloc
(
len
);
s
=
malloc
(
len
);
if
(
!
s
)
if
(
!
s
)
return
false
;
return
false
;
ret
=
snprintf
(
s
,
len
,
"%s/%s"
,
c
->
config_path
,
c
->
name
);
ret
=
snprintf
(
s
,
len
,
"%s/%s"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
len
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
{
free
(
s
);
free
(
s
);
return
false
;
return
false
;
}
}
ret
=
do_create_container_dir
(
s
,
c
->
lxc_conf
);
ret
=
do_create_container_dir
(
s
,
c
->
lxc_conf
);
free
(
s
);
free
(
s
);
return
ret
==
0
;
return
ret
==
0
;
}
}
...
@@ -1219,15 +1270,19 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c,
...
@@ -1219,15 +1270,19 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c,
static
char
*
lxcbasename
(
char
*
path
)
static
char
*
lxcbasename
(
char
*
path
)
{
{
char
*
p
=
path
+
strlen
(
path
)
-
1
;
char
*
p
;
p
=
path
+
strlen
(
path
)
-
1
;
while
(
*
p
!=
'/'
&&
p
>
path
)
while
(
*
p
!=
'/'
&&
p
>
path
)
p
--
;
p
--
;
return
p
;
return
p
;
}
}
static
bool
create_run_template
(
struct
lxc_container
*
c
,
char
*
tpath
,
bool
need_null_stdfds
,
static
bool
create_run_template
(
struct
lxc_container
*
c
,
char
*
tpath
,
char
*
const
argv
[])
bool
need_null_stdfds
,
char
*
const
argv
[])
{
{
int
ret
;
pid_t
pid
;
pid_t
pid
;
if
(
!
tpath
)
if
(
!
tpath
)
...
@@ -1235,47 +1290,58 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
...
@@ -1235,47 +1290,58 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
pid
=
fork
();
pid
=
fork
();
if
(
pid
<
0
)
{
if
(
pid
<
0
)
{
SYSERROR
(
"
f
ailed to fork task for container creation template"
);
SYSERROR
(
"
F
ailed to fork task for container creation template"
);
return
false
;
return
false
;
}
}
if
(
pid
==
0
)
{
/* child */
if
(
pid
==
0
)
{
/* child */
char
*
patharg
,
*
namearg
,
*
rootfsarg
;
int
i
,
len
;
struct
lxc_storage
*
bdev
=
NULL
;
char
*
namearg
,
*
patharg
,
*
rootfsarg
;
int
i
;
int
ret
,
len
,
nargs
=
0
;
char
**
newargv
;
char
**
newargv
;
int
nargs
=
0
;
struct
lxc_storage
*
bdev
=
NULL
;
struct
lxc_conf
*
conf
=
c
->
lxc_conf
;
struct
lxc_conf
*
conf
=
c
->
lxc_conf
;
uid_t
euid
;
if
(
need_null_stdfds
&&
null_stdfds
()
<
0
)
{
if
(
need_null_stdfds
)
{
exit
(
1
);
ret
=
null_stdfds
();
if
(
ret
<
0
)
_exit
(
EXIT_FAILURE
);
}
}
bdev
=
storage_init
(
c
->
lxc_conf
);
bdev
=
storage_init
(
c
->
lxc_conf
);
if
(
!
bdev
)
{
if
(
!
bdev
)
{
ERROR
(
"
Error opening rootfs
"
);
ERROR
(
"
Failed to initialize storage
"
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
}
if
(
geteuid
()
==
0
)
{
euid
=
geteuid
();
if
(
unshare
(
CLONE_NEWNS
)
<
0
)
{
if
(
euid
==
0
)
{
ERROR
(
"error unsharing mounts"
);
ret
=
unshare
(
CLONE_NEWNS
);
exit
(
1
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to unshare CLONE_NEWNS"
);
_exit
(
EXIT_FAILURE
);
}
}
if
(
detect_shared_rootfs
())
{
if
(
mount
(
NULL
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
NULL
))
{
ret
=
detect_shared_rootfs
();
SYSERROR
(
"Failed to make / rslave to run template"
);
if
(
ret
==
1
)
{
ret
=
mount
(
NULL
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
NULL
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to make
\"
/
\"
rslave"
);
ERROR
(
"Continuing..."
);
ERROR
(
"Continuing..."
);
}
}
}
}
}
}
if
(
strcmp
(
bdev
->
type
,
"dir"
)
&&
strcmp
(
bdev
->
type
,
"btrfs"
))
{
if
(
geteuid
()
!=
0
)
{
if
(
strcmp
(
bdev
->
type
,
"dir"
)
!=
0
&&
strcmp
(
bdev
->
type
,
"btrfs"
)
!=
0
)
{
ERROR
(
"non-root users can only create btrfs and directory-backed containers"
);
if
(
euid
!=
0
)
{
exit
(
EXIT_FAILURE
);
ERROR
(
"Unprivileged users can only create "
"btrfs and directory-backed containers"
);
_exit
(
EXIT_FAILURE
);
}
}
if
(
!
strcmp
(
bdev
->
type
,
"overlay"
)
||
!
strcmp
(
bdev
->
type
,
"overlayfs"
))
{
if
(
strcmp
(
bdev
->
type
,
"overlay"
)
==
0
||
strcmp
(
bdev
->
type
,
"overlayfs"
)
==
0
)
{
/* If we create an overlay container we need to
/* If we create an overlay container we need to
* rsync the contents into
* rsync the contents into
* <container-path>/<container-name>/rootfs.
* <container-path>/<container-name>/rootfs.
...
@@ -1298,7 +1364,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
...
@@ -1298,7 +1364,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
src
=
ovl_get_rootfs
(
bdev
->
src
,
&
(
size_t
){
0
});
src
=
ovl_get_rootfs
(
bdev
->
src
,
&
(
size_t
){
0
});
if
(
!
src
)
{
if
(
!
src
)
{
ERROR
(
"Failed to get rootfs"
);
ERROR
(
"Failed to get rootfs"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
ret
=
mount
(
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
,
NULL
);
ret
=
mount
(
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
,
NULL
);
...
@@ -1307,9 +1373,10 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
...
@@ -1307,9 +1373,10 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
return
-
1
;
return
-
1
;
}
}
}
else
{
}
else
{
if
(
bdev
->
ops
->
mount
(
bdev
)
<
0
)
{
ret
=
bdev
->
ops
->
mount
(
bdev
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to mount rootfs"
);
ERROR
(
"Failed to mount rootfs"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
}
}
}
else
{
/* TODO come up with a better way here! */
}
else
{
/* TODO come up with a better way here! */
...
@@ -1319,76 +1386,80 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
...
@@ -1319,76 +1386,80 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
bdev
->
dest
=
strdup
(
src
);
bdev
->
dest
=
strdup
(
src
);
}
}
/*
/* Create our new array, pre-pend the template name and base
* create our new array, pre-pend the template name and
* args.
* base args
*/
*/
if
(
argv
)
if
(
argv
)
for
(
nargs
=
0
;
argv
[
nargs
];
nargs
++
)
;
for
(
nargs
=
0
;
argv
[
nargs
];
nargs
++
)
{
nargs
+=
4
;
/* template, path, rootfs and name args */
;
}
/* template, path, rootfs and name args */
nargs
+=
4
;
newargv
=
malloc
(
nargs
*
sizeof
(
*
newargv
));
newargv
=
malloc
(
nargs
*
sizeof
(
*
newargv
));
if
(
!
newargv
)
if
(
!
newargv
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
newargv
[
0
]
=
lxcbasename
(
tpath
);
newargv
[
0
]
=
lxcbasename
(
tpath
);
/* --path */
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
strlen
(
"--path="
)
+
2
;
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
strlen
(
"--path="
)
+
2
;
patharg
=
malloc
(
len
);
patharg
=
malloc
(
len
);
if
(
!
patharg
)
if
(
!
patharg
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
ret
=
snprintf
(
patharg
,
len
,
"--path=%s/%s"
,
c
->
config_path
,
c
->
name
);
ret
=
snprintf
(
patharg
,
len
,
"--path=%s/%s"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
len
)
if
(
ret
<
0
||
ret
>=
len
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
newargv
[
1
]
=
patharg
;
newargv
[
1
]
=
patharg
;
/* --name */
len
=
strlen
(
"--name="
)
+
strlen
(
c
->
name
)
+
1
;
len
=
strlen
(
"--name="
)
+
strlen
(
c
->
name
)
+
1
;
namearg
=
malloc
(
len
);
namearg
=
malloc
(
len
);
if
(
!
namearg
)
if
(
!
namearg
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
ret
=
snprintf
(
namearg
,
len
,
"--name=%s"
,
c
->
name
);
ret
=
snprintf
(
namearg
,
len
,
"--name=%s"
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
len
)
if
(
ret
<
0
||
ret
>=
len
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
newargv
[
2
]
=
namearg
;
newargv
[
2
]
=
namearg
;
/* --rootfs */
len
=
strlen
(
"--rootfs="
)
+
1
+
strlen
(
bdev
->
dest
);
len
=
strlen
(
"--rootfs="
)
+
1
+
strlen
(
bdev
->
dest
);
rootfsarg
=
malloc
(
len
);
rootfsarg
=
malloc
(
len
);
if
(
!
rootfsarg
)
if
(
!
rootfsarg
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
ret
=
snprintf
(
rootfsarg
,
len
,
"--rootfs=%s"
,
bdev
->
dest
);
ret
=
snprintf
(
rootfsarg
,
len
,
"--rootfs=%s"
,
bdev
->
dest
);
if
(
ret
<
0
||
ret
>=
len
)
if
(
ret
<
0
||
ret
>=
len
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
newargv
[
3
]
=
rootfsarg
;
newargv
[
3
]
=
rootfsarg
;
/* add passed-in args */
/* add passed-in args */
if
(
argv
)
if
(
argv
)
for
(
i
=
4
;
i
<
nargs
;
i
++
)
for
(
i
=
4
;
i
<
nargs
;
i
++
)
newargv
[
i
]
=
argv
[
i
-
4
];
newargv
[
i
]
=
argv
[
i
-
4
];
/* add trailing NULL */
/* add trailing NULL */
nargs
++
;
nargs
++
;
newargv
=
realloc
(
newargv
,
nargs
*
sizeof
(
*
newargv
));
newargv
=
realloc
(
newargv
,
nargs
*
sizeof
(
*
newargv
));
if
(
!
newargv
)
if
(
!
newargv
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
newargv
[
nargs
-
1
]
=
NULL
;
newargv
[
nargs
-
1
]
=
NULL
;
/*
/* If we're running the template in a mapped userns, then we
* If we're running the template in a mapped userns, then
* prepend the template command with: lxc-usernsexec <-m map1>
* we prepend the template command with:
* ... <-m mapn> -- and we append "--mapped-uid x", where x is
* lxc-usernsexec <-m map1> ... <-m mapn> --
* the mapped uid for our geteuid()
* and we append "--mapped-uid x", where x is the mapped uid
* for our geteuid()
*/
*/
if
(
!
lxc_list_empty
(
&
conf
->
id_map
))
{
if
(
!
lxc_list_empty
(
&
conf
->
id_map
))
{
int
n2args
=
1
;
int
extraargs
,
hostuid_mapped
,
hostgid_mapped
;
char
txtuid
[
20
];
char
**
n2
;
char
txtgid
[
20
];
char
txtuid
[
20
],
txtgid
[
20
];
char
**
n2
=
malloc
(
n2args
*
sizeof
(
*
n2
));
struct
lxc_list
*
it
;
struct
lxc_list
*
it
;
struct
id_map
*
map
;
struct
id_map
*
map
;
int
n2args
=
1
;
n2
=
malloc
(
n2args
*
sizeof
(
*
n2
));
if
(
!
n2
)
_exit
(
EXIT_FAILURE
);
if
(
!
n2
)
{
SYSERROR
(
"out of memory"
);
exit
(
1
);
}
newargv
[
0
]
=
tpath
;
newargv
[
0
]
=
tpath
;
tpath
=
"lxc-usernsexec"
;
tpath
=
"lxc-usernsexec"
;
n2
[
0
]
=
"lxc-usernsexec"
;
n2
[
0
]
=
"lxc-usernsexec"
;
...
@@ -1397,97 +1468,103 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
...
@@ -1397,97 +1468,103 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
n2args
+=
2
;
n2args
+=
2
;
n2
=
realloc
(
n2
,
n2args
*
sizeof
(
char
*
));
n2
=
realloc
(
n2
,
n2args
*
sizeof
(
char
*
));
if
(
!
n2
)
if
(
!
n2
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
n2
[
n2args
-
2
]
=
"-m"
;
n2
[
n2args
-
1
]
=
malloc
(
200
);
n2
[
n2args
-
2
]
=
"-m"
;
if
(
!
n2
[
n2args
-
1
])
n2
[
n2args
-
1
]
=
malloc
(
200
);
exit
(
1
);
if
(
!
n2
[
n2args
-
1
])
ret
=
snprintf
(
n2
[
n2args
-
1
],
200
,
"%c:%lu:%lu:%lu"
,
_exit
(
EXIT_FAILURE
);
map
->
idtype
==
ID_TYPE_UID
?
'u'
:
'g'
,
map
->
nsid
,
map
->
hostid
,
map
->
range
);
ret
=
snprintf
(
n2
[
n2args
-
1
],
200
,
"%c:%lu:%lu:%lu"
,
map
->
idtype
==
ID_TYPE_UID
?
'u'
:
'g'
,
map
->
nsid
,
map
->
hostid
,
map
->
range
);
if
(
ret
<
0
||
ret
>=
200
)
if
(
ret
<
0
||
ret
>=
200
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
}
int
hostid_mapped
=
mapped_hostid
(
geteuid
(),
conf
,
ID_TYPE_UID
);
int
extraargs
=
hostid_mapped
>=
0
?
1
:
3
;
hostuid_mapped
=
mapped_hostid
(
geteuid
(),
conf
,
ID_TYPE_UID
);
extraargs
=
hostuid_mapped
>=
0
?
1
:
3
;
n2
=
realloc
(
n2
,
(
nargs
+
n2args
+
extraargs
)
*
sizeof
(
char
*
));
n2
=
realloc
(
n2
,
(
nargs
+
n2args
+
extraargs
)
*
sizeof
(
char
*
));
if
(
!
n2
)
if
(
!
n2
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
if
(
hostid_mapped
<
0
)
{
hostid_mapped
=
find_unmapped_nsid
(
conf
,
ID_TYPE_UID
);
if
(
hostuid_mapped
<
0
)
{
hostuid_mapped
=
find_unmapped_nsid
(
conf
,
ID_TYPE_UID
);
n2
[
n2args
++
]
=
"-m"
;
n2
[
n2args
++
]
=
"-m"
;
if
(
hostid_mapped
<
0
)
{
if
(
host
u
id_mapped
<
0
)
{
ERROR
(
"
Could not
find free uid to map"
);
ERROR
(
"
Failed to
find free uid to map"
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
}
n2
[
n2args
++
]
=
malloc
(
200
);
n2
[
n2args
++
]
=
malloc
(
200
);
if
(
!
n2
[
n2args
-
1
])
{
if
(
!
n2
[
n2args
-
1
])
{
SYSERROR
(
"out of memory"
);
SYSERROR
(
"out of memory"
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
ret
=
snprintf
(
n2
[
n2args
-
1
],
200
,
"u:%d:%d:1"
,
hostid_mapped
,
geteuid
());
if
(
ret
<
0
||
ret
>=
200
)
{
ERROR
(
"string too long"
);
exit
(
1
);
}
}
ret
=
snprintf
(
n2
[
n2args
-
1
],
200
,
"u:%d:%d:1"
,
hostuid_mapped
,
geteuid
());
if
(
ret
<
0
||
ret
>=
200
)
_exit
(
EXIT_FAILURE
);
}
}
int
hostgid_mapped
=
mapped_hostid
(
getegid
(),
conf
,
ID_TYPE_GID
);
hostgid_mapped
=
mapped_hostid
(
getegid
(),
conf
,
ID_TYPE_GID
);
extraargs
=
hostgid_mapped
>=
0
?
1
:
3
;
extraargs
=
hostgid_mapped
>=
0
?
1
:
3
;
n2
=
realloc
(
n2
,
(
nargs
+
n2args
+
extraargs
)
*
sizeof
(
char
*
));
n2
=
realloc
(
n2
,
(
nargs
+
n2args
+
extraargs
)
*
sizeof
(
char
*
));
if
(
!
n2
)
if
(
!
n2
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
if
(
hostgid_mapped
<
0
)
{
if
(
hostgid_mapped
<
0
)
{
hostgid_mapped
=
find_unmapped_nsid
(
conf
,
ID_TYPE_GID
);
hostgid_mapped
=
find_unmapped_nsid
(
conf
,
ID_TYPE_GID
);
n2
[
n2args
++
]
=
"-m"
;
n2
[
n2args
++
]
=
"-m"
;
if
(
hostgid_mapped
<
0
)
{
if
(
hostgid_mapped
<
0
)
{
ERROR
(
"
Could not find free u
id to map"
);
ERROR
(
"
Failed to find free g
id to map"
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
}
n2
[
n2args
++
]
=
malloc
(
200
);
n2
[
n2args
++
]
=
malloc
(
200
);
if
(
!
n2
[
n2args
-
1
])
{
if
(
!
n2
[
n2args
-
1
])
{
SYSERROR
(
"out of memory"
);
SYSERROR
(
"out of memory"
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
ret
=
snprintf
(
n2
[
n2args
-
1
],
200
,
"g:%d:%d:1"
,
hostgid_mapped
,
getegid
());
if
(
ret
<
0
||
ret
>=
200
)
{
ERROR
(
"string too long"
);
exit
(
1
);
}
}
ret
=
snprintf
(
n2
[
n2args
-
1
],
200
,
"g:%d:%d:1"
,
hostgid_mapped
,
getegid
());
if
(
ret
<
0
||
ret
>=
200
)
_exit
(
EXIT_FAILURE
);
}
}
n2
[
n2args
++
]
=
"--"
;
n2
[
n2args
++
]
=
"--"
;
for
(
i
=
0
;
i
<
nargs
;
i
++
)
for
(
i
=
0
;
i
<
nargs
;
i
++
)
n2
[
i
+
n2args
]
=
newargv
[
i
];
n2
[
i
+
n2args
]
=
newargv
[
i
];
n2args
+=
nargs
;
n2args
+=
nargs
;
/* Finally add "--mapped-uid $uid" to tell template
* what to chown cached images to.
/* Finally add "--mapped-uid $uid" to tell template what
* to chown cached images to.
*/
*/
n2args
+=
4
;
n2args
+=
4
;
n2
=
realloc
(
n2
,
n2args
*
sizeof
(
char
*
));
n2
=
realloc
(
n2
,
n2args
*
sizeof
(
char
*
));
if
(
!
n2
)
{
if
(
!
n2
)
SYSERROR
(
"out of memory"
);
_exit
(
EXIT_FAILURE
);
exit
(
1
);
}
/* note n2[n2args-1] is NULL */
/* note n2[n2args-1] is NULL */
n2
[
n2args
-
5
]
=
"--mapped-uid"
;
n2
[
n2args
-
5
]
=
"--mapped-uid"
;
snprintf
(
txtuid
,
20
,
"%d"
,
hostid_mapped
);
snprintf
(
txtuid
,
20
,
"%d"
,
host
u
id_mapped
);
n2
[
n2args
-
4
]
=
txtuid
;
n2
[
n2args
-
4
]
=
txtuid
;
n2
[
n2args
-
3
]
=
"--mapped-gid"
;
n2
[
n2args
-
3
]
=
"--mapped-gid"
;
snprintf
(
txtgid
,
20
,
"%d"
,
hostgid_mapped
);
snprintf
(
txtgid
,
20
,
"%d"
,
hostgid_mapped
);
n2
[
n2args
-
2
]
=
txtgid
;
n2
[
n2args
-
2
]
=
txtgid
;
n2
[
n2args
-
1
]
=
NULL
;
n2
[
n2args
-
1
]
=
NULL
;
free
(
newargv
);
free
(
newargv
);
newargv
=
n2
;
newargv
=
n2
;
}
}
/* execute */
execvp
(
tpath
,
newargv
);
execvp
(
tpath
,
newargv
);
SYSERROR
(
"Failed to execute template %s"
,
tpath
);
SYSERROR
(
"Failed to execute template %s"
,
tpath
);
exit
(
1
);
_exit
(
EXIT_FAILURE
);
}
}
if
(
wait_for_pid
(
pid
)
!=
0
)
{
ret
=
wait_for_pid
(
pid
);
ERROR
(
"container creation template for %s failed"
,
c
->
name
);
if
(
ret
!=
0
)
{
ERROR
(
"Failed to create container from template"
);
return
false
;
return
false
;
}
}
...
@@ -1618,8 +1695,8 @@ static void lxcapi_clear_config(struct lxc_container *c)
...
@@ -1618,8 +1695,8 @@ static void lxcapi_clear_config(struct lxc_container *c)
* arguments, you can just pass NULL.
* arguments, you can just pass NULL.
*/
*/
static
bool
do_lxcapi_create
(
struct
lxc_container
*
c
,
const
char
*
t
,
static
bool
do_lxcapi_create
(
struct
lxc_container
*
c
,
const
char
*
t
,
const
char
*
bdevtype
,
struct
bdev_specs
*
specs
,
int
flag
s
,
const
char
*
bdevtype
,
struct
bdev_specs
*
spec
s
,
char
*
const
argv
[])
int
flags
,
char
*
const
argv
[])
{
{
int
partial_fd
;
int
partial_fd
;
pid_t
pid
;
pid_t
pid
;
...
@@ -1713,7 +1790,7 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
...
@@ -1713,7 +1790,7 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
if
(
!
bdev
)
{
if
(
!
bdev
)
{
ERROR
(
"Failed to create %s storage for %s"
,
ERROR
(
"Failed to create %s storage for %s"
,
bdevtype
?
bdevtype
:
"(none)"
,
c
->
name
);
bdevtype
?
bdevtype
:
"(none)"
,
c
->
name
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* Save config file again to store the new rootfs location. */
/* Save config file again to store the new rootfs location. */
...
@@ -1724,9 +1801,9 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
...
@@ -1724,9 +1801,9 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
*/
*/
bdev
->
ops
->
umount
(
bdev
);
bdev
->
ops
->
umount
(
bdev
);
bdev
->
ops
->
destroy
(
bdev
);
bdev
->
ops
->
destroy
(
bdev
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
exit
(
EXIT_SUCCESS
);
_
exit
(
EXIT_SUCCESS
);
}
}
if
(
wait_for_pid
(
pid
)
!=
0
)
if
(
wait_for_pid
(
pid
)
!=
0
)
goto
out_unlock
;
goto
out_unlock
;
...
@@ -2165,7 +2242,7 @@ static char ** do_lxcapi_get_interfaces(struct lxc_container *c)
...
@@ -2165,7 +2242,7 @@ static char ** do_lxcapi_get_interfaces(struct lxc_container *c)
/* close the write-end of the pipe, thus sending EOF to the reader */
/* close the write-end of the pipe, thus sending EOF to the reader */
close
(
pipefd
[
1
]);
close
(
pipefd
[
1
]);
exit
(
ret
);
_
exit
(
ret
);
}
}
/* close the write-end of the pipe */
/* close the write-end of the pipe */
...
@@ -2290,7 +2367,7 @@ static char** do_lxcapi_get_ips(struct lxc_container *c, const char* interface,
...
@@ -2290,7 +2367,7 @@ static char** do_lxcapi_get_ips(struct lxc_container *c, const char* interface,
/* close the write-end of the pipe, thus sending EOF to the reader */
/* close the write-end of the pipe, thus sending EOF to the reader */
close
(
pipefd
[
1
]);
close
(
pipefd
[
1
]);
exit
(
ret
);
_
exit
(
ret
);
}
}
/* close the write-end of the pipe */
/* close the write-end of the pipe */
...
@@ -2391,9 +2468,8 @@ WRAP_API_3(int, lxcapi_get_keys, const char *, char *, int)
...
@@ -2391,9 +2468,8 @@ WRAP_API_3(int, lxcapi_get_keys, const char *, char *, int)
static
bool
do_lxcapi_save_config
(
struct
lxc_container
*
c
,
const
char
*
alt_file
)
static
bool
do_lxcapi_save_config
(
struct
lxc_container
*
c
,
const
char
*
alt_file
)
{
{
FILE
*
fou
t
;
int
fd
,
lre
t
;
bool
ret
=
false
,
need_disklock
=
false
;
bool
ret
=
false
,
need_disklock
=
false
;
int
lret
;
if
(
!
alt_file
)
if
(
!
alt_file
)
alt_file
=
c
->
configfile
;
alt_file
=
c
->
configfile
;
...
@@ -2403,7 +2479,10 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
...
@@ -2403,7 +2479,10 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
/* If we haven't yet loaded a config, load the stock config. */
/* If we haven't yet loaded a config, load the stock config. */
if
(
!
c
->
lxc_conf
)
{
if
(
!
c
->
lxc_conf
)
{
if
(
!
do_lxcapi_load_config
(
c
,
lxc_global_config_value
(
"lxc.default_config"
)))
{
if
(
!
do_lxcapi_load_config
(
c
,
lxc_global_config_value
(
"lxc.default_config"
)))
{
ERROR
(
"Error loading default configuration file %s while saving %s"
,
lxc_global_config_value
(
"lxc.default_config"
),
c
->
name
);
ERROR
(
"Error loading default configuration file %s "
"while saving %s"
,
lxc_global_config_value
(
"lxc.default_config"
),
c
->
name
);
return
false
;
return
false
;
}
}
}
}
...
@@ -2426,18 +2505,24 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
...
@@ -2426,18 +2505,24 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
if
(
lret
)
if
(
lret
)
return
false
;
return
false
;
fout
=
fopen
(
alt_file
,
"w"
);
fd
=
open
(
alt_file
,
O_WRONLY
|
O_CREAT
|
O_CLOEXEC
,
if
(
!
fout
)
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
|
S_IROTH
|
S_IWOTH
);
goto
out
;
if
(
fd
<
0
)
write_config
(
fout
,
c
->
lxc_conf
);
goto
on_error
;
fclose
(
fout
);
lret
=
write_config
(
fd
,
c
->
lxc_conf
);
close
(
fd
);
if
(
lret
<
0
)
goto
on_error
;
ret
=
true
;
ret
=
true
;
o
ut
:
o
n_error
:
if
(
need_disklock
)
if
(
need_disklock
)
container_disk_unlock
(
c
);
container_disk_unlock
(
c
);
else
else
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
return
ret
;
return
ret
;
}
}
...
@@ -3488,10 +3573,9 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
...
@@ -3488,10 +3573,9 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
char
**
hookargs
)
char
**
hookargs
)
{
{
char
newpath
[
MAXPATHLEN
];
char
newpath
[
MAXPATHLEN
];
int
ret
;
int
fd
,
ret
;
struct
clone_update_data
data
;
struct
clone_update_data
data
;
size_t
saved_unexp_len
;
size_t
saved_unexp_len
;
FILE
*
fout
;
pid_t
pid
;
pid_t
pid
;
int
storage_copied
=
0
;
int
storage_copied
=
0
;
char
*
origroot
=
NULL
,
*
saved_unexp_conf
=
NULL
;
char
*
origroot
=
NULL
,
*
saved_unexp_conf
=
NULL
;
...
@@ -3535,9 +3619,11 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
...
@@ -3535,9 +3619,11 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
origroot
=
c
->
lxc_conf
->
rootfs
.
path
;
origroot
=
c
->
lxc_conf
->
rootfs
.
path
;
c
->
lxc_conf
->
rootfs
.
path
=
NULL
;
c
->
lxc_conf
->
rootfs
.
path
=
NULL
;
}
}
fout
=
fopen
(
newpath
,
"w"
);
if
(
!
fout
)
{
fd
=
open
(
newpath
,
O_WRONLY
|
O_CREAT
|
O_CLOEXEC
,
SYSERROR
(
"open %s"
,
newpath
);
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
|
S_IROTH
|
S_IWOTH
);
if
(
fd
<
0
)
{
SYSERROR
(
"Failed to open
\"
%s
\"
"
,
newpath
);
goto
out
;
goto
out
;
}
}
...
@@ -3545,14 +3631,13 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
...
@@ -3545,14 +3631,13 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
saved_unexp_len
=
c
->
lxc_conf
->
unexpanded_len
;
saved_unexp_len
=
c
->
lxc_conf
->
unexpanded_len
;
c
->
lxc_conf
->
unexpanded_config
=
strdup
(
saved_unexp_conf
);
c
->
lxc_conf
->
unexpanded_config
=
strdup
(
saved_unexp_conf
);
if
(
!
c
->
lxc_conf
->
unexpanded_config
)
{
if
(
!
c
->
lxc_conf
->
unexpanded_config
)
{
ERROR
(
"Out of memory"
);
close
(
fd
);
fclose
(
fout
);
goto
out
;
goto
out
;
}
}
clear_unexp_config_line
(
c
->
lxc_conf
,
"lxc.rootfs.path"
,
false
);
clear_unexp_config_line
(
c
->
lxc_conf
,
"lxc.rootfs.path"
,
false
);
write_config
(
f
out
,
c
->
lxc_conf
);
write_config
(
f
d
,
c
->
lxc_conf
);
fclose
(
fout
);
close
(
fd
);
c
->
lxc_conf
->
rootfs
.
path
=
origroot
;
c
->
lxc_conf
->
rootfs
.
path
=
origroot
;
free
(
c
->
lxc_conf
->
unexpanded_config
);
free
(
c
->
lxc_conf
->
unexpanded_config
);
c
->
lxc_conf
->
unexpanded_config
=
saved_unexp_conf
;
c
->
lxc_conf
->
unexpanded_config
=
saved_unexp_conf
;
...
@@ -3662,10 +3747,10 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
...
@@ -3662,10 +3747,10 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
else
else
ret
=
clone_update_rootfs
(
&
data
);
ret
=
clone_update_rootfs
(
&
data
);
if
(
ret
<
0
)
if
(
ret
<
0
)
exit
(
1
);
_exit
(
EXIT_FAILURE
);
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
exit
(
0
);
_exit
(
EXIT_SUCCESS
);
out:
out:
container_mem_unlock
(
c
);
container_mem_unlock
(
c
);
...
@@ -4235,11 +4320,11 @@ static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
...
@@ -4235,11 +4320,11 @@ static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
ret
=
chroot
(
chrootpath
);
ret
=
chroot
(
chrootpath
);
if
(
ret
<
0
)
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
ret
=
chdir
(
"/"
);
ret
=
chdir
(
"/"
);
if
(
ret
<
0
)
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
/* remove path if it exists */
/* remove path if it exists */
ret
=
faccessat
(
AT_FDCWD
,
path
,
F_OK
,
AT_SYMLINK_NOFOLLOW
);
ret
=
faccessat
(
AT_FDCWD
,
path
,
F_OK
,
AT_SYMLINK_NOFOLLOW
);
...
@@ -4247,24 +4332,24 @@ static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
...
@@ -4247,24 +4332,24 @@ static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
ret
=
unlink
(
path
);
ret
=
unlink
(
path
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"%s - Failed to remove
\"
%s
\"
"
,
strerror
(
errno
),
path
);
ERROR
(
"%s - Failed to remove
\"
%s
\"
"
,
strerror
(
errno
),
path
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
}
}
if
(
!
add
)
if
(
!
add
)
exit
(
EXIT_SUCCESS
);
_
exit
(
EXIT_SUCCESS
);
/* create any missing directories */
/* create any missing directories */
tmp
=
strdup
(
path
);
tmp
=
strdup
(
path
);
if
(
!
tmp
)
if
(
!
tmp
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
directory_path
=
dirname
(
tmp
);
directory_path
=
dirname
(
tmp
);
ret
=
mkdir_p
(
directory_path
,
0755
);
ret
=
mkdir_p
(
directory_path
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
ERROR
(
"%s - Failed to create path
\"
%s
\"
"
,
strerror
(
errno
),
directory_path
);
ERROR
(
"%s - Failed to create path
\"
%s
\"
"
,
strerror
(
errno
),
directory_path
);
free
(
tmp
);
free
(
tmp
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* create the device node */
/* create the device node */
...
@@ -4272,17 +4357,17 @@ static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
...
@@ -4272,17 +4357,17 @@ static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
free
(
tmp
);
free
(
tmp
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"%s - Failed to create device node at
\"
%s
\"
"
,
strerror
(
errno
),
path
);
ERROR
(
"%s - Failed to create device node at
\"
%s
\"
"
,
strerror
(
errno
),
path
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
exit
(
EXIT_SUCCESS
);
_
exit
(
EXIT_SUCCESS
);
}
}
static
bool
add_remove_device_node
(
struct
lxc_container
*
c
,
const
char
*
src_path
,
const
char
*
dest_path
,
bool
add
)
static
bool
add_remove_device_node
(
struct
lxc_container
*
c
,
const
char
*
src_path
,
const
char
*
dest_path
,
bool
add
)
{
{
int
ret
;
int
ret
;
struct
stat
st
;
struct
stat
st
;
char
value
[
MAX_BUFFER
];
char
value
[
LXC_
MAX_BUFFER
];
const
char
*
p
;
const
char
*
p
;
/* make sure container is running */
/* make sure container is running */
...
@@ -4300,14 +4385,14 @@ static bool add_remove_device_node(struct lxc_container *c, const char *src_path
...
@@ -4300,14 +4385,14 @@ static bool add_remove_device_node(struct lxc_container *c, const char *src_path
/* continue if path is character device or block device */
/* continue if path is character device or block device */
if
(
S_ISCHR
(
st
.
st_mode
))
if
(
S_ISCHR
(
st
.
st_mode
))
ret
=
snprintf
(
value
,
MAX_BUFFER
,
"c %d:%d rwm"
,
major
(
st
.
st_rdev
),
minor
(
st
.
st_rdev
));
ret
=
snprintf
(
value
,
LXC_
MAX_BUFFER
,
"c %d:%d rwm"
,
major
(
st
.
st_rdev
),
minor
(
st
.
st_rdev
));
else
if
(
S_ISBLK
(
st
.
st_mode
))
else
if
(
S_ISBLK
(
st
.
st_mode
))
ret
=
snprintf
(
value
,
MAX_BUFFER
,
"b %d:%d rwm"
,
major
(
st
.
st_rdev
),
minor
(
st
.
st_rdev
));
ret
=
snprintf
(
value
,
LXC_
MAX_BUFFER
,
"b %d:%d rwm"
,
major
(
st
.
st_rdev
),
minor
(
st
.
st_rdev
));
else
else
return
false
;
return
false
;
/* check snprintf return code */
/* check snprintf return code */
if
(
ret
<
0
||
ret
>=
MAX_BUFFER
)
if
(
ret
<
0
||
ret
>=
LXC_
MAX_BUFFER
)
return
false
;
return
false
;
if
(
!
do_add_remove_node
(
do_lxcapi_init_pid
(
c
),
p
,
add
,
&
st
))
if
(
!
do_add_remove_node
(
do_lxcapi_init_pid
(
c
),
p
,
add
,
&
st
))
...
@@ -4333,7 +4418,7 @@ static bool do_lxcapi_add_device_node(struct lxc_container *c, const char *src_p
...
@@ -4333,7 +4418,7 @@ static bool do_lxcapi_add_device_node(struct lxc_container *c, const char *src_p
{
{
// cannot mknod if we're not privileged wrt init_user_ns
// cannot mknod if we're not privileged wrt init_user_ns
if
(
am_host_unpriv
())
{
if
(
am_host_unpriv
())
{
ERROR
(
NOT_SUPPORTED_ERROR
,
__FUNCTION__
);
ERROR
(
LXC_UNPRIV_EOPNOTSUPP
,
__FUNCTION__
);
return
false
;
return
false
;
}
}
return
add_remove_device_node
(
c
,
src_path
,
dest_path
,
true
);
return
add_remove_device_node
(
c
,
src_path
,
dest_path
,
true
);
...
@@ -4344,7 +4429,7 @@ WRAP_API_2(bool, lxcapi_add_device_node, const char *, const char *)
...
@@ -4344,7 +4429,7 @@ WRAP_API_2(bool, lxcapi_add_device_node, const char *, const char *)
static
bool
do_lxcapi_remove_device_node
(
struct
lxc_container
*
c
,
const
char
*
src_path
,
const
char
*
dest_path
)
static
bool
do_lxcapi_remove_device_node
(
struct
lxc_container
*
c
,
const
char
*
src_path
,
const
char
*
dest_path
)
{
{
if
(
am_guest_unpriv
())
{
if
(
am_guest_unpriv
())
{
ERROR
(
NOT_SUPPORTED_ERROR
,
__FUNCTION__
);
ERROR
(
LXC_UNPRIV_EOPNOTSUPP
,
__FUNCTION__
);
return
false
;
return
false
;
}
}
return
add_remove_device_node
(
c
,
src_path
,
dest_path
,
false
);
return
add_remove_device_node
(
c
,
src_path
,
dest_path
,
false
);
...
@@ -4360,7 +4445,7 @@ static bool do_lxcapi_attach_interface(struct lxc_container *c,
...
@@ -4360,7 +4445,7 @@ static bool do_lxcapi_attach_interface(struct lxc_container *c,
int
ret
=
0
;
int
ret
=
0
;
if
(
am_guest_unpriv
())
{
if
(
am_guest_unpriv
())
{
ERROR
(
NOT_SUPPORTED_ERROR
,
__FUNCTION__
);
ERROR
(
LXC_UNPRIV_EOPNOTSUPP
,
__FUNCTION__
);
return
false
;
return
false
;
}
}
...
@@ -4403,7 +4488,7 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
...
@@ -4403,7 +4488,7 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
* But for other types guest privilege suffices.
* But for other types guest privilege suffices.
*/
*/
if
(
am_guest_unpriv
())
{
if
(
am_guest_unpriv
())
{
ERROR
(
NOT_SUPPORTED_ERROR
,
__FUNCTION__
);
ERROR
(
LXC_UNPRIV_EOPNOTSUPP
,
__FUNCTION__
);
return
false
;
return
false
;
}
}
...
@@ -4425,13 +4510,13 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
...
@@ -4425,13 +4510,13 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
init_pid
=
do_lxcapi_init_pid
(
c
);
init_pid
=
do_lxcapi_init_pid
(
c
);
if
(
!
switch_to_ns
(
init_pid
,
"net"
))
{
if
(
!
switch_to_ns
(
init_pid
,
"net"
))
{
ERROR
(
"Failed to enter network namespace"
);
ERROR
(
"Failed to enter network namespace"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
ret
=
lxc_netdev_isup
(
ifname
);
ret
=
lxc_netdev_isup
(
ifname
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"Failed to determine whether network device
\"
%s
\"
is up"
,
ifname
);
ERROR
(
"Failed to determine whether network device
\"
%s
\"
is up"
,
ifname
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* netdev of ifname is up. */
/* netdev of ifname is up. */
...
@@ -4439,7 +4524,7 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
...
@@ -4439,7 +4524,7 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
ret
=
lxc_netdev_down
(
ifname
);
ret
=
lxc_netdev_down
(
ifname
);
if
(
ret
)
{
if
(
ret
)
{
ERROR
(
"Failed to set network device
\"
%s
\"
down"
,
ifname
);
ERROR
(
"Failed to set network device
\"
%s
\"
down"
,
ifname
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
}
}
...
@@ -4450,10 +4535,10 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
...
@@ -4450,10 +4535,10 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
ERROR
(
"Network device
\"
%s
\"
not found"
,
ifname
);
ERROR
(
"Network device
\"
%s
\"
not found"
,
ifname
);
else
else
ERROR
(
"Failed to remove network device
\"
%s
\"
"
,
ifname
);
ERROR
(
"Failed to remove network device
\"
%s
\"
"
,
ifname
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
exit
(
EXIT_SUCCESS
);
_
exit
(
EXIT_SUCCESS
);
}
}
ret
=
wait_for_pid
(
pid
);
ret
=
wait_for_pid
(
pid
);
...
...
src/lxc/lxclock.c
View file @
c8a5adcd
...
@@ -72,10 +72,11 @@ static void lock_mutex(pthread_mutex_t *l)
...
@@ -72,10 +72,11 @@ static void lock_mutex(pthread_mutex_t *l)
{
{
int
ret
;
int
ret
;
if
((
ret
=
pthread_mutex_lock
(
l
))
!=
0
)
{
ret
=
pthread_mutex_lock
(
l
);
fprintf
(
stderr
,
"pthread_mutex_lock returned:%d %s
\n
"
,
ret
,
strerror
(
ret
));
if
(
ret
!=
0
)
{
fprintf
(
stderr
,
"%s - Failed acquire mutex"
,
strerror
(
ret
));
dump_stacktrace
();
dump_stacktrace
();
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
}
}
...
@@ -83,11 +84,11 @@ static void unlock_mutex(pthread_mutex_t *l)
...
@@ -83,11 +84,11 @@ static void unlock_mutex(pthread_mutex_t *l)
{
{
int
ret
;
int
ret
;
if
((
ret
=
pthread_mutex_unlock
(
l
))
!=
0
)
{
ret
=
pthread_mutex_unlock
(
l
);
fprintf
(
stderr
,
"%s: pthread_mutex_unlock returned:%d %s
\n
"
,
if
(
ret
!=
0
)
{
__FILE__
,
ret
,
strerror
(
ret
));
fprintf
(
stderr
,
"%s - Failed to release mutex"
,
strerror
(
ret
));
dump_stacktrace
();
dump_stacktrace
();
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
}
}
...
...
src/lxc/network.c
View file @
c8a5adcd
...
@@ -635,7 +635,7 @@ static int lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old,
...
@@ -635,7 +635,7 @@ static int lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old,
if
(
!
switch_to_ns
(
pid
,
"net"
))
if
(
!
switch_to_ns
(
pid
,
"net"
))
return
-
1
;
return
-
1
;
exit
(
lxc_netdev_rename_by_name
(
old
,
new
));
_
exit
(
lxc_netdev_rename_by_name
(
old
,
new
));
}
}
static
int
lxc_netdev_move_wlan
(
char
*
physname
,
const
char
*
ifname
,
pid_t
pid
,
static
int
lxc_netdev_move_wlan
(
char
*
physname
,
const
char
*
ifname
,
pid_t
pid
,
...
@@ -663,7 +663,7 @@ static int lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid,
...
@@ -663,7 +663,7 @@ static int lxc_netdev_move_wlan(char *physname, const char *ifname, pid_t pid,
sprintf
(
pidstr
,
"%d"
,
pid
);
sprintf
(
pidstr
,
"%d"
,
pid
);
execlp
(
"iw"
,
"iw"
,
"phy"
,
physname
,
"set"
,
"netns"
,
pidstr
,
execlp
(
"iw"
,
"iw"
,
"phy"
,
physname
,
"set"
,
"netns"
,
pidstr
,
(
char
*
)
NULL
);
(
char
*
)
NULL
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
if
(
wait_for_pid
(
fpid
))
if
(
wait_for_pid
(
fpid
))
...
@@ -2126,7 +2126,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna
...
@@ -2126,7 +2126,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna
close
(
pipefd
[
1
]);
close
(
pipefd
[
1
]);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to duplicate std{err,out} file descriptor"
);
SYSERROR
(
"Failed to duplicate std{err,out} file descriptor"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
if
(
netdev
->
link
[
0
]
!=
'\0'
)
if
(
netdev
->
link
[
0
]
!=
'\0'
)
...
@@ -2136,7 +2136,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna
...
@@ -2136,7 +2136,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna
ret
=
snprintf
(
pidstr
,
LXC_NUMSTRLEN64
,
"%d"
,
pid
);
ret
=
snprintf
(
pidstr
,
LXC_NUMSTRLEN64
,
"%d"
,
pid
);
if
(
ret
<
0
||
ret
>=
LXC_NUMSTRLEN64
)
if
(
ret
<
0
||
ret
>=
LXC_NUMSTRLEN64
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
pidstr
[
LXC_NUMSTRLEN64
-
1
]
=
'\0'
;
pidstr
[
LXC_NUMSTRLEN64
-
1
]
=
'\0'
;
INFO
(
"Execing lxc-user-nic create %s %s %s veth %s %s"
,
lxcpath
,
INFO
(
"Execing lxc-user-nic create %s %s %s veth %s %s"
,
lxcpath
,
...
@@ -2151,7 +2151,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna
...
@@ -2151,7 +2151,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna
lxcpath
,
lxcname
,
pidstr
,
"veth"
,
netdev_link
,
lxcpath
,
lxcname
,
pidstr
,
"veth"
,
netdev_link
,
(
char
*
)
NULL
);
(
char
*
)
NULL
);
SYSERROR
(
"Failed to execute lxc-user-nic"
);
SYSERROR
(
"Failed to execute lxc-user-nic"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* close the write-end of the pipe */
/* close the write-end of the pipe */
...
@@ -2269,7 +2269,7 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcna
...
@@ -2269,7 +2269,7 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcna
close
(
pipefd
[
1
]);
close
(
pipefd
[
1
]);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to duplicate std{err,out} file descriptor"
);
SYSERROR
(
"Failed to duplicate std{err,out} file descriptor"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
if
(
netdev
->
priv
.
veth_attr
.
pair
[
0
]
!=
'\0'
)
if
(
netdev
->
priv
.
veth_attr
.
pair
[
0
]
!=
'\0'
)
...
@@ -2278,13 +2278,13 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcna
...
@@ -2278,13 +2278,13 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcna
hostveth
=
netdev
->
priv
.
veth_attr
.
veth1
;
hostveth
=
netdev
->
priv
.
veth_attr
.
veth1
;
if
(
hostveth
[
0
]
==
'\0'
)
{
if
(
hostveth
[
0
]
==
'\0'
)
{
SYSERROR
(
"Host side veth device name is missing"
);
SYSERROR
(
"Host side veth device name is missing"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
if
(
netdev
->
link
[
0
]
==
'\0'
)
{
if
(
netdev
->
link
[
0
]
==
'\0'
)
{
SYSERROR
(
"Network link for network device
\"
%s
\"
is "
SYSERROR
(
"Network link for network device
\"
%s
\"
is "
"missing"
,
netdev
->
priv
.
veth_attr
.
veth1
);
"missing"
,
netdev
->
priv
.
veth_attr
.
veth1
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
INFO
(
"Execing lxc-user-nic delete %s %s %s veth %s %s"
,
lxcpath
,
INFO
(
"Execing lxc-user-nic delete %s %s %s veth %s %s"
,
lxcpath
,
...
@@ -2293,7 +2293,7 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcna
...
@@ -2293,7 +2293,7 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcna
lxcname
,
netns_path
,
"veth"
,
netdev
->
link
,
hostveth
,
lxcname
,
netns_path
,
"veth"
,
netdev
->
link
,
hostveth
,
(
char
*
)
NULL
);
(
char
*
)
NULL
);
SYSERROR
(
"Failed to exec lxc-user-nic."
);
SYSERROR
(
"Failed to exec lxc-user-nic."
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
close
(
pipefd
[
1
]);
close
(
pipefd
[
1
]);
...
...
src/lxc/parse.c
View file @
c8a5adcd
...
@@ -20,13 +20,15 @@
...
@@ -20,13 +20,15 @@
* License along with this library; if not, write to the Free Software
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/
#define _GNU_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <stdio.h>
#undef _GNU_SOURCE
#undef _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include "parse.h"
#include "parse.h"
#include "config.h"
#include "config.h"
...
@@ -35,6 +37,77 @@
...
@@ -35,6 +37,77 @@
lxc_log_define
(
lxc_parse
,
lxc
);
lxc_log_define
(
lxc_parse
,
lxc
);
void
*
lxc_strmmap
(
void
*
addr
,
size_t
length
,
int
prot
,
int
flags
,
int
fd
,
off_t
offset
)
{
void
*
tmp
=
NULL
,
*
overlap
=
NULL
;
/* We establish an anonymous mapping that is one byte larger than the
* underlying file. The pages handed to us are zero filled. */
tmp
=
mmap
(
addr
,
length
+
1
,
PROT_READ
,
MAP_PRIVATE
|
MAP_ANONYMOUS
,
-
1
,
0
);
if
(
tmp
==
MAP_FAILED
)
return
tmp
;
/* Now we establish a fixed-address mapping starting at the address we
* received from our anonymous mapping and replace all bytes excluding
* the additional \0-byte with the file. This allows us to use normal
* string-handling functions. */
overlap
=
mmap
(
tmp
,
length
,
prot
,
MAP_FIXED
|
flags
,
fd
,
offset
);
if
(
overlap
==
MAP_FAILED
)
munmap
(
tmp
,
length
+
1
);
return
overlap
;
}
int
lxc_strmunmap
(
void
*
addr
,
size_t
length
)
{
return
munmap
(
addr
,
length
+
1
);
}
int
lxc_file_for_each_line_mmap
(
const
char
*
file
,
lxc_file_cb
callback
,
void
*
data
)
{
int
fd
,
ret
;
char
*
buf
,
*
line
;
struct
stat
st
;
char
*
saveptr
=
NULL
;
fd
=
open
(
file
,
O_RDONLY
|
O_CLOEXEC
);
if
(
fd
<
0
)
return
-
1
;
ret
=
fstat
(
fd
,
&
st
);
if
(
ret
<
0
)
{
close
(
fd
);
return
-
1
;
}
if
(
st
.
st_size
==
0
)
return
0
;
buf
=
lxc_strmmap
(
NULL
,
st
.
st_size
,
PROT_READ
|
PROT_WRITE
,
MAP_PRIVATE
,
fd
,
0
);
if
(
buf
==
MAP_FAILED
)
{
close
(
fd
);
return
-
1
;
}
for
(;
(
line
=
strtok_r
(
buf
,
"
\n\0
"
,
&
saveptr
));
buf
=
NULL
)
{
ret
=
callback
(
line
,
data
);
if
(
ret
)
{
/* Callback rv > 0 means stop here callback rv < 0 means
* error.
*/
if
(
ret
<
0
)
ERROR
(
"Failed to parse config: %s"
,
line
);
break
;
}
}
lxc_strmunmap
(
buf
,
st
.
st_size
);
close
(
fd
);
return
0
;
}
int
lxc_file_for_each_line
(
const
char
*
file
,
lxc_file_cb
callback
,
void
*
data
)
int
lxc_file_for_each_line
(
const
char
*
file
,
lxc_file_cb
callback
,
void
*
data
)
{
{
FILE
*
f
;
FILE
*
f
;
...
...
src/lxc/parse.h
View file @
c8a5adcd
...
@@ -23,6 +23,9 @@
...
@@ -23,6 +23,9 @@
#ifndef __LXC_PARSE_H
#ifndef __LXC_PARSE_H
#define __LXC_PARSE_H
#define __LXC_PARSE_H
#include <stdio.h>
#include <sys/types.h>
typedef
int
(
*
lxc_dir_cb
)(
const
char
*
name
,
const
char
*
directory
,
typedef
int
(
*
lxc_dir_cb
)(
const
char
*
name
,
const
char
*
directory
,
const
char
*
file
,
void
*
data
);
const
char
*
file
,
void
*
data
);
...
@@ -31,10 +34,20 @@ typedef int (*lxc_file_cb)(char *buffer, void *data);
...
@@ -31,10 +34,20 @@ typedef int (*lxc_file_cb)(char *buffer, void *data);
extern
int
lxc_file_for_each_line
(
const
char
*
file
,
lxc_file_cb
callback
,
extern
int
lxc_file_for_each_line
(
const
char
*
file
,
lxc_file_cb
callback
,
void
*
data
);
void
*
data
);
extern
int
lxc_file_for_each_line_mmap
(
const
char
*
file
,
lxc_file_cb
callback
,
void
*
data
);
extern
int
lxc_char_left_gc
(
const
char
*
buffer
,
size_t
len
);
extern
int
lxc_char_left_gc
(
const
char
*
buffer
,
size_t
len
);
extern
int
lxc_char_right_gc
(
const
char
*
buffer
,
size_t
len
);
extern
int
lxc_char_right_gc
(
const
char
*
buffer
,
size_t
len
);
extern
int
lxc_is_line_empty
(
const
char
*
line
);
extern
int
lxc_is_line_empty
(
const
char
*
line
);
/* mmap() wrapper. lxc_strmmap() will take care to \0-terminate files so that
* normal string-handling functions can be used on the buffer. */
extern
void
*
lxc_strmmap
(
void
*
addr
,
size_t
length
,
int
prot
,
int
flags
,
int
fd
,
off_t
offset
);
/* munmap() wrapper. Use it to free memory mmap()ed with lxc_strmmap(). */
extern
int
lxc_strmunmap
(
void
*
addr
,
size_t
length
);
#endif
#endif
src/lxc/utils.c
View file @
c8a5adcd
...
@@ -478,7 +478,7 @@ struct lxc_popen_FILE *lxc_popen(const char *command)
...
@@ -478,7 +478,7 @@ struct lxc_popen_FILE *lxc_popen(const char *command)
ret
=
fcntl
(
pipe_fds
[
1
],
F_SETFD
,
0
);
ret
=
fcntl
(
pipe_fds
[
1
],
F_SETFD
,
0
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
close
(
pipe_fds
[
1
]);
close
(
pipe_fds
[
1
]);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* duplicate stderr */
/* duplicate stderr */
...
@@ -488,19 +488,19 @@ struct lxc_popen_FILE *lxc_popen(const char *command)
...
@@ -488,19 +488,19 @@ struct lxc_popen_FILE *lxc_popen(const char *command)
ret
=
fcntl
(
pipe_fds
[
1
],
F_SETFD
,
0
);
ret
=
fcntl
(
pipe_fds
[
1
],
F_SETFD
,
0
);
close
(
pipe_fds
[
1
]);
close
(
pipe_fds
[
1
]);
if
(
ret
<
0
)
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
/* unblock all signals */
/* unblock all signals */
ret
=
sigfillset
(
&
mask
);
ret
=
sigfillset
(
&
mask
);
if
(
ret
<
0
)
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
ret
=
sigprocmask
(
SIG_UNBLOCK
,
&
mask
,
NULL
);
ret
=
sigprocmask
(
SIG_UNBLOCK
,
&
mask
,
NULL
);
if
(
ret
<
0
)
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
execl
(
"/bin/sh"
,
"sh"
,
"-c"
,
command
,
(
char
*
)
NULL
);
execl
(
"/bin/sh"
,
"sh"
,
"-c"
,
command
,
(
char
*
)
NULL
);
exit
(
127
);
_
exit
(
127
);
}
}
close
(
pipe_fds
[
1
]);
close
(
pipe_fds
[
1
]);
...
@@ -1810,33 +1810,6 @@ int lxc_count_file_lines(const char *fn)
...
@@ -1810,33 +1810,6 @@ int lxc_count_file_lines(const char *fn)
return
n
;
return
n
;
}
}
void
*
lxc_strmmap
(
void
*
addr
,
size_t
length
,
int
prot
,
int
flags
,
int
fd
,
off_t
offset
)
{
void
*
tmp
=
NULL
,
*
overlap
=
NULL
;
/* We establish an anonymous mapping that is one byte larger than the
* underlying file. The pages handed to us are zero filled. */
tmp
=
mmap
(
addr
,
length
+
1
,
PROT_READ
,
MAP_PRIVATE
|
MAP_ANONYMOUS
,
-
1
,
0
);
if
(
tmp
==
MAP_FAILED
)
return
tmp
;
/* Now we establish a fixed-address mapping starting at the address we
* received from our anonymous mapping and replace all bytes excluding
* the additional \0-byte with the file. This allows us to use normal
* string-handling functions. */
overlap
=
mmap
(
tmp
,
length
,
prot
,
MAP_FIXED
|
flags
,
fd
,
offset
);
if
(
overlap
==
MAP_FAILED
)
munmap
(
tmp
,
length
+
1
);
return
overlap
;
}
int
lxc_strmunmap
(
void
*
addr
,
size_t
length
)
{
return
munmap
(
addr
,
length
+
1
);
}
/* Check whether a signal is blocked by a process. */
/* Check whether a signal is blocked by a process. */
/* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */
/* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */
#define __PROC_STATUS_LEN (5 + (LXC_NUMSTRLEN64) + 7 + 1)
#define __PROC_STATUS_LEN (5 + (LXC_NUMSTRLEN64) + 7 + 1)
...
@@ -2269,13 +2242,13 @@ int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void *args)
...
@@ -2269,13 +2242,13 @@ int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void *args)
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"failed to duplicate std{err,out} file descriptor"
);
SYSERROR
(
"failed to duplicate std{err,out} file descriptor"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* Does not return. */
/* Does not return. */
child_fn
(
args
);
child_fn
(
args
);
ERROR
(
"failed to exec command"
);
ERROR
(
"failed to exec command"
);
exit
(
EXIT_FAILURE
);
_
exit
(
EXIT_FAILURE
);
}
}
/* close the write-end of the pipe */
/* close the write-end of the pipe */
...
...
src/lxc/utils.h
View file @
c8a5adcd
...
@@ -100,6 +100,7 @@
...
@@ -100,6 +100,7 @@
#define LXC_NUMSTRLEN64 21
#define LXC_NUMSTRLEN64 21
#define LXC_LINELEN 4096
#define LXC_LINELEN 4096
#define LXC_IDMAPLEN 4096
#define LXC_IDMAPLEN 4096
#define LXC_MAX_BUFFER 4096
/* returns 1 on success, 0 if there were any failures */
/* returns 1 on success, 0 if there were any failures */
extern
int
lxc_rmdir_onedev
(
const
char
*
path
,
const
char
*
exclude
);
extern
int
lxc_rmdir_onedev
(
const
char
*
path
,
const
char
*
exclude
);
...
@@ -426,13 +427,6 @@ extern size_t lxc_array_len(void **array);
...
@@ -426,13 +427,6 @@ extern size_t lxc_array_len(void **array);
extern
void
**
lxc_append_null_to_array
(
void
**
array
,
size_t
count
);
extern
void
**
lxc_append_null_to_array
(
void
**
array
,
size_t
count
);
/* mmap() wrapper. lxc_strmmap() will take care to \0-terminate files so that
* normal string-handling functions can be used on the buffer. */
extern
void
*
lxc_strmmap
(
void
*
addr
,
size_t
length
,
int
prot
,
int
flags
,
int
fd
,
off_t
offset
);
/* munmap() wrapper. Use it to free memory mmap()ed with lxc_strmmap(). */
extern
int
lxc_strmunmap
(
void
*
addr
,
size_t
length
);
/* initialize rand with urandom */
/* initialize rand with urandom */
extern
int
randseed
(
bool
);
extern
int
randseed
(
bool
);
...
...
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