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
9ddc6b44
Unverified
Commit
9ddc6b44
authored
Jul 22, 2018
by
Christian Brauner
Committed by
GitHub
Jul 22, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2300 from LizaTretyakova/mount_injection
Mount injection API
parents
a633a1ed
54fc984b
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
459 additions
and
14 deletions
+459
-14
conf.c
src/lxc/conf.c
+31
-0
conf.h
src/lxc/conf.h
+10
-0
confile.c
src/lxc/confile.c
+31
-0
confile.h
src/lxc/confile.h
+4
-0
lxccontainer.c
src/lxc/lxccontainer.c
+251
-0
lxccontainer.h
src/lxc/lxccontainer.h
+19
-0
start.c
src/lxc/start.c
+88
-0
utils.c
src/lxc/utils.c
+20
-13
utils.h
src/lxc/utils.h
+1
-0
Makefile.am
src/tests/Makefile.am
+4
-1
mount_injection.c
src/tests/mount_injection.c
+0
-0
No files found.
src/lxc/conf.c
View file @
9ddc6b44
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
#define _GNU_SOURCE
#define _GNU_SOURCE
#include "config.h"
#include "config.h"
#include "confile.h"
#include <arpa/inet.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <dirent.h>
...
@@ -647,6 +648,23 @@ unsigned long add_required_remount_flags(const char *s, const char *d,
...
@@ -647,6 +648,23 @@ unsigned long add_required_remount_flags(const char *s, const char *d,
#endif
#endif
}
}
static
int
add_shmount_to_list
(
struct
lxc_conf
*
conf
)
{
char
new_mount
[
MAXPATHLEN
];
/* Offset for the leading '/' since the path_cont
* is absolute inside the container.
*/
int
offset
=
1
,
ret
=
-
1
;
ret
=
snprintf
(
new_mount
,
sizeof
(
new_mount
),
"%s %s none bind,create=dir 0 0"
,
conf
->
shmount
.
path_host
,
conf
->
shmount
.
path_cont
+
offset
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
new_mount
))
return
-
1
;
return
add_elem_to_mount_list
(
new_mount
,
conf
);
}
static
int
lxc_mount_auto_mounts
(
struct
lxc_conf
*
conf
,
int
flags
,
struct
lxc_handler
*
handler
)
static
int
lxc_mount_auto_mounts
(
struct
lxc_conf
*
conf
,
int
flags
,
struct
lxc_handler
*
handler
)
{
{
int
i
,
r
;
int
i
,
r
;
...
@@ -783,6 +801,14 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
...
@@ -783,6 +801,14 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
}
}
}
}
if
(
flags
&
LXC_AUTO_SHMOUNTS_MASK
)
{
int
ret
=
add_shmount_to_list
(
conf
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to add shmount entry to container config"
);
return
-
1
;
}
}
return
0
;
return
0
;
}
}
...
@@ -2714,6 +2740,9 @@ struct lxc_conf *lxc_conf_init(void)
...
@@ -2714,6 +2740,9 @@ struct lxc_conf *lxc_conf_init(void)
new
->
lsm_aa_profile
=
NULL
;
new
->
lsm_aa_profile
=
NULL
;
new
->
lsm_se_context
=
NULL
;
new
->
lsm_se_context
=
NULL
;
new
->
tmp_umount_proc
=
false
;
new
->
tmp_umount_proc
=
false
;
new
->
tmp_umount_proc
=
0
;
new
->
shmount
.
path_host
=
NULL
;
new
->
shmount
.
path_cont
=
NULL
;
/* if running in a new user namespace, init and COMMAND
/* if running in a new user namespace, init and COMMAND
* default to running as UID/GID 0 when using lxc-execute */
* default to running as UID/GID 0 when using lxc-execute */
...
@@ -4041,6 +4070,8 @@ void lxc_conf_free(struct lxc_conf *conf)
...
@@ -4041,6 +4070,8 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_procs
(
conf
,
"lxc.proc"
);
lxc_clear_procs
(
conf
,
"lxc.proc"
);
free
(
conf
->
cgroup_meta
.
dir
);
free
(
conf
->
cgroup_meta
.
dir
);
free
(
conf
->
cgroup_meta
.
controllers
);
free
(
conf
->
cgroup_meta
.
controllers
);
free
(
conf
->
shmount
.
path_host
);
free
(
conf
->
shmount
.
path_cont
);
free
(
conf
);
free
(
conf
);
}
}
...
...
src/lxc/conf.h
View file @
9ddc6b44
...
@@ -189,6 +189,9 @@ enum {
...
@@ -189,6 +189,9 @@ enum {
LXC_AUTO_CGROUP_FULL_NOSPEC
=
0x0E0
,
/* /sys/fs/cgroup (full mount, r/w or mixed, depending on caps) */
LXC_AUTO_CGROUP_FULL_NOSPEC
=
0x0E0
,
/* /sys/fs/cgroup (full mount, r/w or mixed, depending on caps) */
LXC_AUTO_CGROUP_FORCE
=
0x100
,
/* mount cgroups even when cgroup namespaces are supported */
LXC_AUTO_CGROUP_FORCE
=
0x100
,
/* mount cgroups even when cgroup namespaces are supported */
LXC_AUTO_CGROUP_MASK
=
0x1F0
,
/* all known cgroup options, doe not contain LXC_AUTO_CGROUP_FORCE */
LXC_AUTO_CGROUP_MASK
=
0x1F0
,
/* all known cgroup options, doe not contain LXC_AUTO_CGROUP_FORCE */
LXC_AUTO_SHMOUNTS
=
0x200
,
/* shared mount point */
LXC_AUTO_SHMOUNTS_MASK
=
0x200
,
/* shared mount point mask */
LXC_AUTO_ALL_MASK
=
0x1FF
,
/* all known settings */
LXC_AUTO_ALL_MASK
=
0x1FF
,
/* all known settings */
};
};
...
@@ -367,6 +370,13 @@ struct lxc_conf {
...
@@ -367,6 +370,13 @@ struct lxc_conf {
/* procs */
/* procs */
struct
lxc_list
procs
;
struct
lxc_list
procs
;
struct
shmount
{
/* Absolute path to the shared mount point on the host */
char
*
path_host
;
/* Absolute path (in the container) to the shared mount point */
char
*
path_cont
;
}
shmount
;
};
};
extern
int
write_id_mapping
(
enum
idtype
idtype
,
pid_t
pid
,
const
char
*
buf
,
extern
int
write_id_mapping
(
enum
idtype
idtype
,
pid_t
pid
,
const
char
*
buf
,
...
...
src/lxc/confile.c
View file @
9ddc6b44
...
@@ -1659,6 +1659,7 @@ static int set_config_mount_auto(const char *key, const char *value,
...
@@ -1659,6 +1659,7 @@ static int set_config_mount_auto(const char *key, const char *value,
{
"cgroup-full:mixed:force"
,
LXC_AUTO_CGROUP_MASK
,
LXC_AUTO_CGROUP_FULL_MIXED
|
LXC_AUTO_CGROUP_FORCE
},
{
"cgroup-full:mixed:force"
,
LXC_AUTO_CGROUP_MASK
,
LXC_AUTO_CGROUP_FULL_MIXED
|
LXC_AUTO_CGROUP_FORCE
},
{
"cgroup-full:ro:force"
,
LXC_AUTO_CGROUP_MASK
,
LXC_AUTO_CGROUP_FULL_RO
|
LXC_AUTO_CGROUP_FORCE
},
{
"cgroup-full:ro:force"
,
LXC_AUTO_CGROUP_MASK
,
LXC_AUTO_CGROUP_FULL_RO
|
LXC_AUTO_CGROUP_FORCE
},
{
"cgroup-full:rw:force"
,
LXC_AUTO_CGROUP_MASK
,
LXC_AUTO_CGROUP_FULL_RW
|
LXC_AUTO_CGROUP_FORCE
},
{
"cgroup-full:rw:force"
,
LXC_AUTO_CGROUP_MASK
,
LXC_AUTO_CGROUP_FULL_RW
|
LXC_AUTO_CGROUP_FORCE
},
{
"shmounts:"
,
LXC_AUTO_SHMOUNTS_MASK
,
LXC_AUTO_SHMOUNTS
},
/* For adding anything that is just a single on/off, but has no
/* For adding anything that is just a single on/off, but has no
* options: keep mask and flag identical and just define the enum
* options: keep mask and flag identical and just define the enum
* value as an unused bit so far
* value as an unused bit so far
...
@@ -1676,6 +1677,8 @@ static int set_config_mount_auto(const char *key, const char *value,
...
@@ -1676,6 +1677,8 @@ static int set_config_mount_auto(const char *key, const char *value,
return
-
1
;
return
-
1
;
for
(
autoptr
=
autos
;;
autoptr
=
NULL
)
{
for
(
autoptr
=
autos
;;
autoptr
=
NULL
)
{
bool
is_shmounts
=
false
;
token
=
strtok_r
(
autoptr
,
"
\t
"
,
&
sptr
);
token
=
strtok_r
(
autoptr
,
"
\t
"
,
&
sptr
);
if
(
!
token
)
{
if
(
!
token
)
{
ret
=
0
;
ret
=
0
;
...
@@ -1685,6 +1688,12 @@ static int set_config_mount_auto(const char *key, const char *value,
...
@@ -1685,6 +1688,12 @@ static int set_config_mount_auto(const char *key, const char *value,
for
(
i
=
0
;
allowed_auto_mounts
[
i
].
token
;
i
++
)
{
for
(
i
=
0
;
allowed_auto_mounts
[
i
].
token
;
i
++
)
{
if
(
!
strcmp
(
allowed_auto_mounts
[
i
].
token
,
token
))
if
(
!
strcmp
(
allowed_auto_mounts
[
i
].
token
,
token
))
break
;
break
;
if
(
strcmp
(
"shmounts:"
,
allowed_auto_mounts
[
i
].
token
)
==
0
&&
strncmp
(
"shmounts:"
,
token
,
sizeof
(
"shmounts:"
)
-
1
)
==
0
)
{
is_shmounts
=
true
;
break
;
}
}
}
if
(
!
allowed_auto_mounts
[
i
].
token
)
{
if
(
!
allowed_auto_mounts
[
i
].
token
)
{
...
@@ -1694,6 +1703,24 @@ static int set_config_mount_auto(const char *key, const char *value,
...
@@ -1694,6 +1703,24 @@ static int set_config_mount_auto(const char *key, const char *value,
lxc_conf
->
auto_mounts
&=
~
allowed_auto_mounts
[
i
].
mask
;
lxc_conf
->
auto_mounts
&=
~
allowed_auto_mounts
[
i
].
mask
;
lxc_conf
->
auto_mounts
|=
allowed_auto_mounts
[
i
].
flag
;
lxc_conf
->
auto_mounts
|=
allowed_auto_mounts
[
i
].
flag
;
if
(
is_shmounts
)
{
lxc_conf
->
shmount
.
path_host
=
strdup
(
token
+
(
sizeof
(
"shmounts:"
)
-
1
));
if
(
!
lxc_conf
->
shmount
.
path_host
)
{
SYSERROR
(
"Failed to copy shmounts host path"
);
break
;
}
if
(
strcmp
(
lxc_conf
->
shmount
.
path_host
,
""
)
==
0
)
{
ERROR
(
"Invalid shmounts path: empty"
);
break
;
}
lxc_conf
->
shmount
.
path_cont
=
strdup
(
"/dev/.lxc-mounts"
);
if
(
!
lxc_conf
->
shmount
.
path_cont
)
{
SYSERROR
(
"Failed to copy shmounts container path"
);
break
;
}
}
}
}
free
(
autos
);
free
(
autos
);
...
@@ -1725,6 +1752,10 @@ static int set_config_mount(const char *key, const char *value,
...
@@ -1725,6 +1752,10 @@ static int set_config_mount(const char *key, const char *value,
return
0
;
return
0
;
}
}
int
add_elem_to_mount_list
(
const
char
*
value
,
struct
lxc_conf
*
lxc_conf
)
{
return
set_config_mount
(
NULL
,
value
,
lxc_conf
,
NULL
);
}
static
int
set_config_cap_keep
(
const
char
*
key
,
const
char
*
value
,
static
int
set_config_cap_keep
(
const
char
*
key
,
const
char
*
value
,
struct
lxc_conf
*
lxc_conf
,
void
*
data
)
struct
lxc_conf
*
lxc_conf
,
void
*
data
)
{
{
...
...
src/lxc/confile.h
View file @
9ddc6b44
...
@@ -28,7 +28,9 @@
...
@@ -28,7 +28,9 @@
#include <stdbool.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdio.h>
#include <lxc/attach_options.h>
#include <lxc/attach_options.h>
#include <lxc/lxccontainer.h>
struct
lxc_conf
;
struct
lxc_conf
;
struct
lxc_list
;
struct
lxc_list
;
...
@@ -121,4 +123,6 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
...
@@ -121,4 +123,6 @@ bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath,
extern
bool
network_new_hwaddrs
(
struct
lxc_conf
*
conf
);
extern
bool
network_new_hwaddrs
(
struct
lxc_conf
*
conf
);
extern
int
add_elem_to_mount_list
(
const
char
*
value
,
struct
lxc_conf
*
lxc_conf
);
#endif
/* __LXC_CONFILE_H */
#endif
/* __LXC_CONFILE_H */
src/lxc/lxccontainer.c
View file @
9ddc6b44
...
@@ -30,9 +30,11 @@
...
@@ -30,9 +30,11 @@
#include <stdarg.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdint.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/types.h>
...
@@ -460,6 +462,25 @@ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3) \
...
@@ -460,6 +462,25 @@ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3) \
return ret; \
return ret; \
}
}
#define WRAP_API_6(rettype, fnname, t1, t2, t3, t4, t5, t6) \
static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3, \
t4 a4, t5 a5, t6 a6) \
{ \
rettype ret; \
bool reset_config = false; \
\
if (!current_config && c && c->lxc_conf) { \
current_config = c->lxc_conf; \
reset_config = true; \
} \
\
ret = do_##fnname(c, a1, a2, a3, a4, a5, a6); \
if (reset_config) \
current_config = NULL; \
\
return ret; \
}
WRAP_API
(
bool
,
lxcapi_is_defined
)
WRAP_API
(
bool
,
lxcapi_is_defined
)
static
const
char
*
do_lxcapi_state
(
struct
lxc_container
*
c
)
static
const
char
*
do_lxcapi_state
(
struct
lxc_container
*
c
)
...
@@ -4893,6 +4914,234 @@ static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool ver
...
@@ -4893,6 +4914,234 @@ static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool ver
WRAP_API_2
(
bool
,
lxcapi_restore
,
char
*
,
bool
)
WRAP_API_2
(
bool
,
lxcapi_restore
,
char
*
,
bool
)
/* @st_mode is the st_mode field of the stat(source) return struct */
static
int
create_mount_target
(
const
char
*
dest
,
mode_t
st_mode
)
{
char
*
dirdup
,
*
destdirname
;
int
ret
;
dirdup
=
strdup
(
dest
);
if
(
!
dirdup
)
{
SYSERROR
(
"Failed to duplicate target name
\"
%s
\"
"
,
dest
);
return
-
1
;
}
destdirname
=
dirname
(
dirdup
);
ret
=
mkdir_p
(
destdirname
,
0755
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create
\"
%s
\"
"
,
destdirname
);
free
(
dirdup
);
return
ret
;
}
free
(
dirdup
);
(
void
)
remove
(
dest
);
if
(
S_ISDIR
(
st_mode
))
ret
=
mkdir
(
dest
,
0000
);
else
ret
=
mknod
(
dest
,
S_IFREG
|
0000
,
0
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create mount target
\"
%s
\"
"
,
dest
);
return
-
1
;
}
return
0
;
}
static
int
do_lxcapi_mount
(
struct
lxc_container
*
c
,
const
char
*
source
,
const
char
*
target
,
const
char
*
filesystemtype
,
unsigned
long
mountflags
,
const
void
*
data
,
struct
lxc_mount
*
mnt
)
{
char
*
suff
,
*
sret
;
char
template
[
MAXPATHLEN
],
path
[
MAXPATHLEN
];
pid_t
pid
,
init_pid
;
struct
stat
sb
;
int
ret
=
-
1
,
fd
=
-
EBADF
;
if
(
!
c
||
!
c
->
lxc_conf
)
{
ERROR
(
"Container or configuration is NULL"
);
return
-
EINVAL
;
}
if
(
!
c
->
lxc_conf
->
shmount
.
path_host
)
{
ERROR
(
"Host path to shared mountpoint must be specified in the config
\n
"
);
return
-
EINVAL
;
}
ret
=
snprintf
(
template
,
sizeof
(
template
),
"%s/.lxcmount_XXXXXX"
,
c
->
lxc_conf
->
shmount
.
path_host
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
template
))
{
SYSERROR
(
"Error writing shmounts tempdir name"
);
goto
out
;
}
/* Create a temporary file / dir under the shared mountpoint */
if
(
!
source
||
strcmp
(
source
,
""
)
==
0
)
{
/* If source is not specified, maybe we want to mount a filesystem? */
sb
.
st_mode
=
S_IFDIR
;
}
else
{
ret
=
stat
(
source
,
&
sb
);
if
(
ret
<
0
)
{
SYSERROR
(
"Error getting stat info about the source
\"
%s
\"
"
,
source
);
goto
out
;
}
}
if
(
S_ISDIR
(
sb
.
st_mode
))
{
sret
=
mkdtemp
(
template
);
if
(
!
sret
)
{
SYSERROR
(
"Could not create shmounts temporary dir"
);
goto
out
;
}
}
else
{
fd
=
lxc_make_tmpfile
(
template
,
false
);
if
(
fd
<
0
)
{
SYSERROR
(
"Could not create shmounts temporary file"
);
goto
out
;
}
}
/* Do the fork */
pid
=
fork
();
if
(
pid
<
0
)
{
SYSERROR
(
"Could not fork"
);
goto
out
;
}
if
(
pid
==
0
)
{
/* Do the mount */
ret
=
mount
(
source
,
template
,
filesystemtype
,
mountflags
,
data
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to mount onto
\"
%s
\"
"
,
template
);
_exit
(
EXIT_FAILURE
);
}
TRACE
(
"Mounted
\"
%s
\"
onto
\"
%s
\"
"
,
source
,
template
);
init_pid
=
do_lxcapi_init_pid
(
c
);
if
(
init_pid
<
0
)
{
ERROR
(
"Failed to obtain container's init pid"
);
_exit
(
EXIT_FAILURE
);
}
/* Enter the container namespaces */
if
(
!
lxc_list_empty
(
&
c
->
lxc_conf
->
id_map
))
{
if
(
!
switch_to_ns
(
init_pid
,
"user"
)){
ERROR
(
"Failed to enter user namespace"
);
_exit
(
EXIT_FAILURE
);
}
}
if
(
!
switch_to_ns
(
init_pid
,
"mnt"
))
{
ERROR
(
"Failed to enter mount namespace"
);
_exit
(
EXIT_FAILURE
);
}
ret
=
create_mount_target
(
target
,
sb
.
st_mode
);
if
(
ret
<
0
)
_exit
(
EXIT_FAILURE
);
TRACE
(
"Created mount target
\"
%s
\"
"
,
target
);
suff
=
strrchr
(
template
,
'/'
);
if
(
!
suff
)
_exit
(
EXIT_FAILURE
);
ret
=
snprintf
(
path
,
sizeof
(
path
),
"%s%s"
,
c
->
lxc_conf
->
shmount
.
path_cont
,
suff
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
path
))
{
SYSERROR
(
"Error writing container mountpoint name"
);
_exit
(
EXIT_FAILURE
);
}
ret
=
mount
(
path
,
target
,
NULL
,
MS_MOVE
|
MS_REC
,
NULL
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to move the mount from
\"
%s
\"
to
\"
%s
\"
"
,
path
,
target
);
_exit
(
EXIT_FAILURE
);
}
TRACE
(
"Moved mount from
\"
%s
\"
to
\"
%s
\"
"
,
path
,
target
);
_exit
(
EXIT_SUCCESS
);
}
ret
=
wait_for_pid
(
pid
);
if
(
ret
<
0
)
{
SYSERROR
(
"Wait for the child with pid %ld failed"
,
(
long
)
pid
);
goto
out
;
}
ret
=
0
;
(
void
)
umount2
(
template
,
MNT_DETACH
);
(
void
)
unlink
(
template
);
out
:
if
(
fd
>=
0
)
close
(
fd
);
return
ret
;
}
WRAP_API_6
(
int
,
lxcapi_mount
,
const
char
*
,
const
char
*
,
const
char
*
,
unsigned
long
,
const
void
*
,
struct
lxc_mount
*
)
static
int
do_lxcapi_umount
(
struct
lxc_container
*
c
,
const
char
*
target
,
unsigned
long
flags
,
struct
lxc_mount
*
mnt
)
{
pid_t
pid
,
init_pid
;
int
ret
=
-
1
;
if
(
!
c
||
!
c
->
lxc_conf
)
{
ERROR
(
"Container or configuration is NULL"
);
return
-
EINVAL
;
}
/* Do the fork */
pid
=
fork
();
if
(
pid
<
0
)
{
SYSERROR
(
"Could not fork"
);
return
-
1
;
}
if
(
pid
==
0
)
{
init_pid
=
do_lxcapi_init_pid
(
c
);
if
(
init_pid
<
0
)
{
ERROR
(
"Failed to obtain container's init pid"
);
_exit
(
EXIT_FAILURE
);
}
/* Enter the container namespaces */
if
(
!
lxc_list_empty
(
&
c
->
lxc_conf
->
id_map
))
{
if
(
!
switch_to_ns
(
init_pid
,
"user"
))
{
ERROR
(
"Failed to enter user namespace"
);
_exit
(
EXIT_FAILURE
);
}
}
if
(
!
switch_to_ns
(
init_pid
,
"mnt"
))
{
ERROR
(
"Failed to enter mount namespace"
);
_exit
(
EXIT_FAILURE
);
}
/* Do the unmount */
ret
=
umount2
(
target
,
flags
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to umount
\"
%s
\"
"
,
target
);
_exit
(
EXIT_FAILURE
);
}
_exit
(
EXIT_SUCCESS
);
}
ret
=
wait_for_pid
(
pid
);
if
(
ret
<
0
)
{
SYSERROR
(
"Wait for the child with pid %ld failed"
,
(
long
)
pid
);
return
-
ret
;
}
return
0
;
}
WRAP_API_3
(
int
,
lxcapi_umount
,
const
char
*
,
unsigned
long
,
struct
lxc_mount
*
)
static
int
lxcapi_attach_run_waitl
(
struct
lxc_container
*
c
,
lxc_attach_options_t
*
options
,
const
char
*
program
,
const
char
*
arg
,
...)
static
int
lxcapi_attach_run_waitl
(
struct
lxc_container
*
c
,
lxc_attach_options_t
*
options
,
const
char
*
program
,
const
char
*
arg
,
...)
{
{
va_list
ap
;
va_list
ap
;
...
@@ -5045,6 +5294,8 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
...
@@ -5045,6 +5294,8 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
c
->
restore
=
lxcapi_restore
;
c
->
restore
=
lxcapi_restore
;
c
->
migrate
=
lxcapi_migrate
;
c
->
migrate
=
lxcapi_migrate
;
c
->
console_log
=
lxcapi_console_log
;
c
->
console_log
=
lxcapi_console_log
;
c
->
mount
=
lxcapi_mount
;
c
->
umount
=
lxcapi_umount
;
return
c
;
return
c
;
...
...
src/lxc/lxccontainer.h
View file @
9ddc6b44
...
@@ -42,6 +42,7 @@ extern "C" {
...
@@ -42,6 +42,7 @@ extern "C" {
#define LXC_CLONE_MAXFLAGS (1 << 5)
/*!< Number of \c LXC_CLONE_* flags */
#define LXC_CLONE_MAXFLAGS (1 << 5)
/*!< Number of \c LXC_CLONE_* flags */
#define LXC_CREATE_QUIET (1 << 0)
/*!< Redirect \c stdin to \c /dev/zero and \c stdout and \c stderr to \c /dev/null */
#define LXC_CREATE_QUIET (1 << 0)
/*!< Redirect \c stdin to \c /dev/zero and \c stdout and \c stderr to \c /dev/null */
#define LXC_CREATE_MAXFLAGS (1 << 1)
/*!< Number of \c LXC_CREATE* flags */
#define LXC_CREATE_MAXFLAGS (1 << 1)
/*!< Number of \c LXC_CREATE* flags */
#define LXC_MOUNT_API_V1 1
struct
bdev_specs
;
struct
bdev_specs
;
...
@@ -53,6 +54,10 @@ struct migrate_opts;
...
@@ -53,6 +54,10 @@ struct migrate_opts;
struct
lxc_console_log
;
struct
lxc_console_log
;
struct
lxc_mount
{
int
version
;
};
/*!
/*!
* An LXC container.
* An LXC container.
*
*
...
@@ -846,6 +851,20 @@ struct lxc_container {
...
@@ -846,6 +851,20 @@ struct lxc_container {
* \return \c true if the container was rebooted successfully, else \c false.
* \return \c true if the container was rebooted successfully, else \c false.
*/
*/
bool
(
*
reboot2
)(
struct
lxc_container
*
c
,
int
timeout
);
bool
(
*
reboot2
)(
struct
lxc_container
*
c
,
int
timeout
);
/*!
* \brief Mount the host's path `source` onto the container's path `target`.
*/
int
(
*
mount
)(
struct
lxc_container
*
c
,
const
char
*
source
,
const
char
*
target
,
const
char
*
filesystemtype
,
unsigned
long
mountflags
,
const
void
*
data
,
struct
lxc_mount
*
mnt
);
/*!
* \brief Unmount the container's path `target`.
*/
int
(
*
umount
)(
struct
lxc_container
*
c
,
const
char
*
target
,
unsigned
long
mountflags
,
struct
lxc_mount
*
mnt
);
};
};
/*!
/*!
...
...
src/lxc/start.c
View file @
9ddc6b44
...
@@ -1529,6 +1529,75 @@ static inline int do_share_ns(void *arg)
...
@@ -1529,6 +1529,75 @@ static inline int do_share_ns(void *arg)
return
0
;
return
0
;
}
}
static
int
lxc_setup_shmount
(
struct
lxc_conf
*
conf
)
{
size_t
len_cont
;
char
*
full_cont_path
;
int
ret
=
-
1
;
/* Construct the shmount path under the container root. */
len_cont
=
strlen
(
conf
->
rootfs
.
mount
)
+
1
+
strlen
(
conf
->
shmount
.
path_cont
);
/* +1 for the terminating '\0' */
full_cont_path
=
malloc
(
len_cont
+
1
);
if
(
!
full_cont_path
)
{
SYSERROR
(
"Not enough memory"
);
return
-
ENOMEM
;
}
ret
=
snprintf
(
full_cont_path
,
len_cont
+
1
,
"%s/%s"
,
conf
->
rootfs
.
mount
,
conf
->
shmount
.
path_cont
);
if
(
ret
<
0
||
ret
>=
len_cont
+
1
)
{
SYSERROR
(
"Failed to create filename"
);
free
(
full_cont_path
);
return
-
1
;
}
/* Check if shmount point is already set up. */
if
(
is_shared_mountpoint
(
conf
->
shmount
.
path_host
))
{
INFO
(
"Path
\"
%s
\"
is already MS_SHARED. Reusing"
,
conf
->
shmount
.
path_host
);
free
(
full_cont_path
);
return
0
;
}
/* Create host and cont mount paths */
ret
=
mkdir_p
(
conf
->
shmount
.
path_host
,
0711
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
conf
->
shmount
.
path_host
);
free
(
full_cont_path
);
return
ret
;
}
ret
=
mkdir_p
(
full_cont_path
,
0711
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
full_cont_path
);
free
(
full_cont_path
);
return
ret
;
}
/* Prepare host mountpoint */
ret
=
mount
(
"tmpfs"
,
conf
->
shmount
.
path_host
,
"tmpfs"
,
0
,
"size=100k,mode=0711"
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to mount
\"
%s
\"
"
,
conf
->
shmount
.
path_host
);
free
(
full_cont_path
);
return
ret
;
}
ret
=
mount
(
conf
->
shmount
.
path_host
,
conf
->
shmount
.
path_host
,
"none"
,
MS_REC
|
MS_SHARED
,
""
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to make shared
\"
%s
\"
"
,
conf
->
shmount
.
path_host
);
free
(
full_cont_path
);
return
ret
;
}
INFO
(
"Setup shared mount point
\"
%s
\"
"
,
conf
->
shmount
.
path_host
);
free
(
full_cont_path
);
return
0
;
}
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which
* exec()s the requested container binary.
* exec()s the requested container binary.
* Note that lxc_spawn() runs in the parent namespaces. Any operations performed
* Note that lxc_spawn() runs in the parent namespaces. Any operations performed
...
@@ -1606,6 +1675,25 @@ static int lxc_spawn(struct lxc_handler *handler)
...
@@ -1606,6 +1675,25 @@ static int lxc_spawn(struct lxc_handler *handler)
}
}
}
}
if
(
conf
->
shmount
.
path_host
)
{
if
(
!
conf
->
shmount
.
path_cont
)
{
lxc_sync_fini
(
handler
);
return
-
1
;
}
ret
=
lxc_setup_shmount
(
conf
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to setup shared mount point"
);
lxc_sync_fini
(
handler
);
return
-
1
;
}
}
if
(
!
cgroup_init
(
handler
))
{
ERROR
(
"Failed initializing cgroup support"
);
goto
out_delete_net
;
}
if
(
!
cgroup_ops
->
create
(
cgroup_ops
,
handler
))
{
if
(
!
cgroup_ops
->
create
(
cgroup_ops
,
handler
))
{
ERROR
(
"Failed creating cgroups"
);
ERROR
(
"Failed creating cgroups"
);
goto
out_delete_net
;
goto
out_delete_net
;
...
...
src/lxc/utils.c
View file @
9ddc6b44
...
@@ -1219,19 +1219,12 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
...
@@ -1219,19 +1219,12 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
return
hval
;
return
hval
;
}
}
/*
bool
is_shared_mountpoint
(
const
char
*
path
)
* Detect whether / is mounted MS_SHARED. The only way I know of to
* check that is through /proc/self/mountinfo.
* I'm only checking for /. If the container rootfs or mount location
* is MS_SHARED, but not '/', then you're out of luck - figuring that
* out would be too much work to be worth it.
*/
int
detect_shared_rootfs
(
void
)
{
{
char
buf
[
LXC_LINELEN
]
,
*
p
;
char
buf
[
LXC_LINELEN
];
FILE
*
f
;
FILE
*
f
;
int
i
;
int
i
;
char
*
p2
;
char
*
p
,
*
p
2
;
f
=
fopen
(
"/proc/self/mountinfo"
,
"r"
);
f
=
fopen
(
"/proc/self/mountinfo"
,
"r"
);
if
(
!
f
)
if
(
!
f
)
...
@@ -1248,17 +1241,31 @@ int detect_shared_rootfs(void)
...
@@ -1248,17 +1241,31 @@ int detect_shared_rootfs(void)
continue
;
continue
;
*
p2
=
'\0'
;
*
p2
=
'\0'
;
if
(
strcmp
(
p
+
1
,
"/"
)
==
0
)
{
if
(
strcmp
(
p
+
1
,
path
)
==
0
)
{
/* This is
'/'
. Is it shared? */
/* This is
the path
. Is it shared? */
p
=
strchr
(
p2
+
1
,
' '
);
p
=
strchr
(
p2
+
1
,
' '
);
if
(
p
&&
strstr
(
p
,
"shared:"
))
{
if
(
p
&&
strstr
(
p
,
"shared:"
))
{
fclose
(
f
);
fclose
(
f
);
return
1
;
return
true
;
}
}
}
}
}
}
fclose
(
f
);
fclose
(
f
);
return
false
;
}
/*
* Detect whether / is mounted MS_SHARED. The only way I know of to
* check that is through /proc/self/mountinfo.
* I'm only checking for /. If the container rootfs or mount location
* is MS_SHARED, but not '/', then you're out of luck - figuring that
* out would be too much work to be worth it.
*/
int
detect_shared_rootfs
(
void
)
{
if
(
is_shared_mountpoint
(
"/"
))
return
1
;
return
0
;
return
0
;
}
}
...
...
src/lxc/utils.h
View file @
9ddc6b44
...
@@ -502,6 +502,7 @@ extern bool dir_exists(const char *path);
...
@@ -502,6 +502,7 @@ extern bool dir_exists(const char *path);
#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
extern
uint64_t
fnv_64a_buf
(
void
*
buf
,
size_t
len
,
uint64_t
hval
);
extern
uint64_t
fnv_64a_buf
(
void
*
buf
,
size_t
len
,
uint64_t
hval
);
extern
bool
is_shared_mountpoint
(
const
char
*
path
);
extern
int
detect_shared_rootfs
(
void
);
extern
int
detect_shared_rootfs
(
void
);
extern
bool
detect_ramfs_rootfs
(
void
);
extern
bool
detect_ramfs_rootfs
(
void
);
extern
char
*
on_path
(
const
char
*
cmd
,
const
char
*
rootfs
);
extern
char
*
on_path
(
const
char
*
cmd
,
const
char
*
rootfs
);
...
...
src/tests/Makefile.am
View file @
9ddc6b44
...
@@ -33,6 +33,7 @@ lxc_test_state_server_SOURCES = state_server.c lxctest.h
...
@@ -33,6 +33,7 @@ lxc_test_state_server_SOURCES = state_server.c lxctest.h
lxc_test_share_ns_SOURCES
=
share_ns.c lxctest.h
lxc_test_share_ns_SOURCES
=
share_ns.c lxctest.h
lxc_test_criu_check_feature_SOURCES
=
criu_check_feature.c lxctest.h
lxc_test_criu_check_feature_SOURCES
=
criu_check_feature.c lxctest.h
lxc_test_raw_clone_SOURCES
=
lxc_raw_clone.c lxctest.h
lxc_test_raw_clone_SOURCES
=
lxc_raw_clone.c lxctest.h
lxc_test_mount_injection_SOURCES
=
mount_injection.c
AM_CFLAGS
=
-DLXCROOTFSMOUNT
=
\"
$(LXCROOTFSMOUNT)
\"
\
AM_CFLAGS
=
-DLXCROOTFSMOUNT
=
\"
$(LXCROOTFSMOUNT)
\"
\
-DLXCPATH
=
\"
$(LXCPATH)
\"
\
-DLXCPATH
=
\"
$(LXCPATH)
\"
\
...
@@ -64,7 +65,8 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
...
@@ -64,7 +65,8 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
lxc-test-apparmor lxc-test-utils lxc-test-parse-config-file
\
lxc-test-apparmor lxc-test-utils lxc-test-parse-config-file
\
lxc-test-config-jump-table lxc-test-shortlived
\
lxc-test-config-jump-table lxc-test-shortlived
\
lxc-test-api-reboot lxc-test-state-server lxc-test-share-ns
\
lxc-test-api-reboot lxc-test-state-server lxc-test-share-ns
\
lxc-test-criu-check-feature lxc-test-raw-clone
lxc-test-criu-check-feature lxc-test-raw-clone
\
lxc-test-mount-injection
bin_SCRIPTS
=
bin_SCRIPTS
=
if
ENABLE_TOOLS
if
ENABLE_TOOLS
...
@@ -121,6 +123,7 @@ EXTRA_DIST = \
...
@@ -121,6 +123,7 @@ EXTRA_DIST = \
lxc-test-unpriv
\
lxc-test-unpriv
\
lxc-test-utils.c
\
lxc-test-utils.c
\
may_control.c
\
may_control.c
\
mount_injection.c
\
parse_config_file.c
\
parse_config_file.c
\
saveconfig.c
\
saveconfig.c
\
shortlived.c
\
shortlived.c
\
...
...
src/tests/mount_injection.c
0 → 100644
View file @
9ddc6b44
This diff is collapsed.
Click to expand it.
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