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
dcf0ffdf
Unverified
Commit
dcf0ffdf
authored
Jan 04, 2018
by
Christian Brauner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
conf: rework userns_exec_1()
Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
c7e345ae
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
92 additions
and
68 deletions
+92
-68
conf.c
src/lxc/conf.c
+92
-68
No files found.
src/lxc/conf.c
View file @
dcf0ffdf
...
@@ -1423,6 +1423,15 @@ static struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf, unsigned id,
...
@@ -1423,6 +1423,15 @@ static struct id_map *find_mapped_nsid_entry(struct lxc_conf *conf, unsigned id,
struct
id_map
*
map
;
struct
id_map
*
map
;
struct
id_map
*
retmap
=
NULL
;
struct
id_map
*
retmap
=
NULL
;
/* Shortcut for container's root mappings. */
if
(
id
==
0
)
{
if
(
idtype
==
ID_TYPE_UID
)
return
conf
->
root_nsuid_map
;
if
(
idtype
==
ID_TYPE_GID
)
return
conf
->
root_nsgid_map
;
}
lxc_list_for_each
(
it
,
&
conf
->
id_map
)
{
lxc_list_for_each
(
it
,
&
conf
->
id_map
)
{
map
=
it
->
elem
;
map
=
it
->
elem
;
if
(
map
->
idtype
!=
idtype
)
if
(
map
->
idtype
!=
idtype
)
...
@@ -3857,86 +3866,46 @@ static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id, enum id
...
@@ -3857,86 +3866,46 @@ static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id, enum id
return
entry
;
return
entry
;
}
}
/* Run a function in a new user namespace.
struct
lxc_list
*
get_minimal_idmap
(
struct
lxc_conf
*
conf
)
* The caller's euid/egid will be mapped if it is not already.
* Afaict, userns_exec_1() is only used to operate based on privileges for the
* user's own {g,u}id on the host and for the container root's unmapped {g,u}id.
* This means we require only to establish a mapping from:
* - the container root {g,u}id as seen from the host > user's host {g,u}id
* - the container root -> some sub{g,u}id
* The former we add, if the user did not specifiy a mapping. The latter we
* retrieve from the ontainer's configured {g,u}id mappings as it must have been
* there to start the container in the first place.
*/
int
userns_exec_1
(
struct
lxc_conf
*
conf
,
int
(
*
fn
)(
void
*
),
void
*
data
,
const
char
*
fn_name
)
{
{
pid_t
pid
;
uid_t
euid
,
egid
;
uid_t
euid
,
egid
;
struct
userns_fn_data
d
;
int
p
[
2
];
struct
lxc_list
*
it
;
struct
id_map
*
map
;
char
c
=
'1'
;
int
ret
=
-
1
,
status
=
-
1
;
uid_t
nsuid
=
(
conf
->
root_nsuid_map
!=
NULL
)
?
0
:
conf
->
init_uid
;
uid_t
nsuid
=
(
conf
->
root_nsuid_map
!=
NULL
)
?
0
:
conf
->
init_uid
;
gid_t
nsgid
=
(
conf
->
root_nsgid_map
!=
NULL
)
?
0
:
conf
->
init_gid
;
gid_t
nsgid
=
(
conf
->
root_nsgid_map
!=
NULL
)
?
0
:
conf
->
init_gid
;
struct
lxc_list
*
idmap
=
NULL
,
*
tmplist
=
NULL
;
struct
lxc_list
*
idmap
=
NULL
,
*
tmplist
=
NULL
;
struct
id_map
*
container_root_uid
=
NULL
,
*
container_root_gid
=
NULL
,
struct
id_map
*
container_root_uid
=
NULL
,
*
container_root_gid
=
NULL
,
*
host_uid_map
=
NULL
,
*
host_gid_map
=
NULL
;
*
host_uid_map
=
NULL
,
*
host_gid_map
=
NULL
;
ret
=
pipe
(
p
);
if
(
ret
<
0
)
{
SYSERROR
(
"opening pipe"
);
return
-
1
;
}
d
.
fn
=
fn
;
d
.
fn_name
=
fn_name
;
d
.
arg
=
data
;
d
.
p
[
0
]
=
p
[
0
];
d
.
p
[
1
]
=
p
[
1
];
/* Clone child in new user namespace. */
pid
=
lxc_clone
(
run_userns_fn
,
&
d
,
CLONE_NEWUSER
);
if
(
pid
<
0
)
{
ERROR
(
"failed to clone child process in new user namespace"
);
goto
on_error
;
}
close
(
p
[
0
]);
p
[
0
]
=
-
1
;
/* Find container root mappings. */
/* Find container root mappings. */
euid
=
geteuid
();
container_root_uid
=
mapped_nsid_add
(
conf
,
nsuid
,
ID_TYPE_UID
);
container_root_uid
=
mapped_nsid_add
(
conf
,
nsuid
,
ID_TYPE_UID
);
if
(
!
container_root_uid
)
{
if
(
!
container_root_uid
)
{
DEBUG
(
"Failed to find mapping for
container root
uid %d"
,
0
);
DEBUG
(
"Failed to find mapping for
namespace
uid %d"
,
0
);
goto
on_error
;
goto
on_error
;
}
}
if
(
euid
>=
container_root_uid
->
hostid
&&
euid
<
container_root_uid
->
hostid
+
container_root_uid
->
range
)
euid
=
geteuid
();
if
(
euid
>=
container_root_uid
->
hostid
&&
euid
<
(
container_root_uid
->
hostid
+
container_root_uid
->
range
))
host_uid_map
=
container_root_uid
;
host_uid_map
=
container_root_uid
;
egid
=
getegid
();
container_root_gid
=
mapped_nsid_add
(
conf
,
nsgid
,
ID_TYPE_GID
);
container_root_gid
=
mapped_nsid_add
(
conf
,
nsgid
,
ID_TYPE_GID
);
if
(
!
container_root_gid
)
{
if
(
!
container_root_gid
)
{
DEBUG
(
"Failed to find mapping for
container root
gid %d"
,
0
);
DEBUG
(
"Failed to find mapping for
namespace
gid %d"
,
0
);
goto
on_error
;
goto
on_error
;
}
}
if
(
egid
>=
container_root_gid
->
hostid
&&
egid
<
container_root_gid
->
hostid
+
container_root_gid
->
range
)
egid
=
getegid
();
if
(
egid
>=
container_root_gid
->
hostid
&&
egid
<
(
container_root_gid
->
hostid
+
container_root_gid
->
range
))
host_gid_map
=
container_root_gid
;
host_gid_map
=
container_root_gid
;
/* Check whether the {g,u}id of the user has a mapping. */
/* Check whether the {g,u}id of the user has a mapping. */
if
(
!
host_uid_map
)
if
(
!
host_uid_map
)
host_uid_map
=
mapped_hostid_add
(
conf
,
euid
,
ID_TYPE_UID
);
host_uid_map
=
mapped_hostid_add
(
conf
,
euid
,
ID_TYPE_UID
);
if
(
!
host_gid_map
)
host_gid_map
=
mapped_hostid_add
(
conf
,
egid
,
ID_TYPE_GID
);
if
(
!
host_uid_map
)
{
if
(
!
host_uid_map
)
{
DEBUG
(
"Failed to find mapping for uid %d"
,
euid
);
DEBUG
(
"Failed to find mapping for uid %d"
,
euid
);
goto
on_error
;
goto
on_error
;
}
}
if
(
!
host_gid_map
)
host_gid_map
=
mapped_hostid_add
(
conf
,
egid
,
ID_TYPE_GID
);
if
(
!
host_gid_map
)
{
if
(
!
host_gid_map
)
{
DEBUG
(
"Failed to find mapping for gid %d"
,
egid
);
DEBUG
(
"Failed to find mapping for gid %d"
,
egid
);
goto
on_error
;
goto
on_error
;
...
@@ -3992,29 +3961,95 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
...
@@ -3992,29 +3961,95 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
/* idmap will now keep track of that memory. */
/* idmap will now keep track of that memory. */
host_gid_map
=
NULL
;
host_gid_map
=
NULL
;
TRACE
(
"Allocated minimal idmapping"
);
return
idmap
;
on_error:
if
(
idmap
)
lxc_free_idmap
(
idmap
);
if
(
container_root_uid
)
free
(
container_root_uid
);
if
(
container_root_gid
)
free
(
container_root_gid
);
if
(
host_uid_map
&&
(
host_uid_map
!=
container_root_uid
))
free
(
host_uid_map
);
if
(
host_gid_map
&&
(
host_gid_map
!=
container_root_gid
))
free
(
host_gid_map
);
return
NULL
;
}
/* Run a function in a new user namespace.
* The caller's euid/egid will be mapped if it is not already.
* Afaict, userns_exec_1() is only used to operate based on privileges for the
* user's own {g,u}id on the host and for the container root's unmapped {g,u}id.
* This means we require only to establish a mapping from:
* - the container root {g,u}id as seen from the host > user's host {g,u}id
* - the container root -> some sub{g,u}id
* The former we add, if the user did not specifiy a mapping. The latter we
* retrieve from the ontainer's configured {g,u}id mappings as it must have been
* there to start the container in the first place.
*/
int
userns_exec_1
(
struct
lxc_conf
*
conf
,
int
(
*
fn
)(
void
*
),
void
*
data
,
const
char
*
fn_name
)
{
pid_t
pid
;
struct
userns_fn_data
d
;
int
p
[
2
];
char
c
=
'1'
;
int
ret
=
-
1
,
status
=
-
1
;
struct
lxc_list
*
idmap
;
idmap
=
get_minimal_idmap
(
conf
);
if
(
!
idmap
)
return
-
1
;
ret
=
pipe
(
p
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create pipe"
);
return
-
1
;
}
d
.
fn
=
fn
;
d
.
fn_name
=
fn_name
;
d
.
arg
=
data
;
d
.
p
[
0
]
=
p
[
0
];
d
.
p
[
1
]
=
p
[
1
];
/* Clone child in new user namespace. */
pid
=
lxc_raw_clone_cb
(
run_userns_fn
,
&
d
,
CLONE_NEWUSER
);
if
(
pid
<
0
)
{
ERROR
(
"failed to clone child process in new user namespace"
);
goto
on_error
;
}
close
(
p
[
0
]);
p
[
0
]
=
-
1
;
if
(
lxc_log_get_level
()
==
LXC_LOG_LEVEL_TRACE
||
if
(
lxc_log_get_level
()
==
LXC_LOG_LEVEL_TRACE
||
conf
->
loglevel
==
LXC_LOG_LEVEL_TRACE
)
{
conf
->
loglevel
==
LXC_LOG_LEVEL_TRACE
)
{
struct
lxc_list
*
it
;
struct
id_map
*
map
;
lxc_list_for_each
(
it
,
idmap
)
{
lxc_list_for_each
(
it
,
idmap
)
{
map
=
it
->
elem
;
map
=
it
->
elem
;
TRACE
(
"
e
stablishing %cid mapping for
\"
%d
\"
in new "
TRACE
(
"
E
stablishing %cid mapping for
\"
%d
\"
in new "
"user namespace: nsuid %lu - hostid %lu - range "
"user namespace: nsuid %lu - hostid %lu - range "
"%lu"
,
"%lu"
,
(
map
->
idtype
==
ID_TYPE_UID
)
?
'u'
:
'g'
,
(
map
->
idtype
==
ID_TYPE_UID
)
?
'u'
:
'g'
,
pid
,
pid
,
map
->
nsid
,
map
->
hostid
,
map
->
range
);
map
->
nsid
,
map
->
hostid
,
map
->
range
);
}
}
}
}
/* Set up {g,u}id mapping for user namespace of child process. */
/* Set up {g,u}id mapping for user namespace of child process. */
ret
=
lxc_map_ids
(
idmap
,
pid
);
ret
=
lxc_map_ids
(
idmap
,
pid
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"
e
rror setting up {g,u}id mappings for child process "
ERROR
(
"
E
rror setting up {g,u}id mappings for child process "
"
\"
%d
\"
"
,
pid
);
"
\"
%d
\"
"
,
pid
);
goto
on_error
;
goto
on_error
;
}
}
/* Tell child to proceed. */
/* Tell child to proceed. */
if
(
write
(
p
[
1
],
&
c
,
1
)
!=
1
)
{
if
(
write
(
p
[
1
],
&
c
,
1
)
!=
1
)
{
SYSERROR
(
"
f
ailed telling child process
\"
%d
\"
to proceed"
,
pid
);
SYSERROR
(
"
F
ailed telling child process
\"
%d
\"
to proceed"
,
pid
);
goto
on_error
;
goto
on_error
;
}
}
...
@@ -4023,17 +4058,6 @@ on_error:
...
@@ -4023,17 +4058,6 @@ on_error:
if
(
pid
>
0
)
if
(
pid
>
0
)
status
=
wait_for_pid
(
pid
);
status
=
wait_for_pid
(
pid
);
if
(
idmap
)
lxc_free_idmap
(
idmap
);
if
(
container_root_uid
)
free
(
container_root_uid
);
if
(
container_root_gid
)
free
(
container_root_gid
);
if
(
host_uid_map
&&
(
host_uid_map
!=
container_root_uid
))
free
(
host_uid_map
);
if
(
host_gid_map
&&
(
host_gid_map
!=
container_root_gid
))
free
(
host_gid_map
);
if
(
p
[
0
]
!=
-
1
)
if
(
p
[
0
]
!=
-
1
)
close
(
p
[
0
]);
close
(
p
[
0
]);
close
(
p
[
1
]);
close
(
p
[
1
]);
...
...
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