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
ca3592eb
Commit
ca3592eb
authored
Jun 01, 2017
by
Serge Hallyn
Committed by
GitHub
Jun 01, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1599 from brauner/2017-05-30/use_minimal_idmap_set
conf: use minimal {g,u}id map
parents
493c6236
f8aa4bf3
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
203 additions
and
75 deletions
+203
-75
conf.c
src/lxc/conf.c
+203
-75
No files found.
src/lxc/conf.c
View file @
ca3592eb
...
@@ -4628,108 +4628,158 @@ static int run_userns_fn(void *data)
...
@@ -4628,108 +4628,158 @@ static int run_userns_fn(void *data)
{
{
struct
userns_fn_data
*
d
=
data
;
struct
userns_fn_data
*
d
=
data
;
char
c
;
char
c
;
// we're not sharing with the parent any more, if it was a thread
/* Close write end of the pipe. */
close
(
d
->
p
[
1
]);
close
(
d
->
p
[
1
]);
/* Wait for parent to finish establishing a new mapping in the user
* namespace we are executing in.
*/
if
(
read
(
d
->
p
[
0
],
&
c
,
1
)
!=
1
)
if
(
read
(
d
->
p
[
0
],
&
c
,
1
)
!=
1
)
return
-
1
;
return
-
1
;
/* Close read end of the pipe. */
close
(
d
->
p
[
0
]);
close
(
d
->
p
[
0
]);
/* Call function to run. */
return
d
->
fn
(
d
->
arg
);
return
d
->
fn
(
d
->
arg
);
}
}
static
struct
id_map
*
mapped_hostid_entry
(
unsigned
id
,
struct
lxc_conf
*
conf
,
enum
idtype
idtype
)
{
struct
lxc_list
*
it
;
struct
id_map
*
map
;
struct
id_map
*
retmap
=
NULL
;
lxc_list_for_each
(
it
,
&
conf
->
id_map
)
{
map
=
it
->
elem
;
if
(
map
->
idtype
!=
idtype
)
continue
;
if
(
id
>=
map
->
hostid
&&
id
<
map
->
hostid
+
map
->
range
)
{
retmap
=
map
;
break
;
}
}
if
(
!
retmap
)
return
NULL
;
retmap
=
malloc
(
sizeof
(
*
retmap
));
if
(
!
retmap
)
return
NULL
;
memcpy
(
retmap
,
map
,
sizeof
(
*
retmap
));
return
retmap
;
}
/*
/*
* A
dd ID_TYPE_UID/ID_TYPE_GID entries to an existing lxc_conf,
* A
llocate a new {g,u}id mapping for the given {g,u}id. Re-use an already
*
if they are not already ther
e.
*
existing one or establish a new on
e.
*/
*/
static
struct
lxc_list
*
idmap_add_id
(
struct
lxc_conf
*
conf
,
static
struct
lxc_list
*
idmap_add_id
(
struct
lxc_conf
*
conf
,
uid_t
uid
,
uid_t
uid
,
gid_t
gid
)
gid_t
gid
)
{
{
int
hostuid_mapped
=
mapped_hostid
(
uid
,
conf
,
ID_TYPE_UID
);
int
hostuid_mapped
,
hostgid_mapped
;
int
hostgid_mapped
=
mapped_hostid
(
gid
,
conf
,
ID_TYPE_GID
);
struct
id_map
*
hostuid_idmap
,
*
hostgid_idmap
;
struct
lxc_list
*
new
=
NULL
,
*
tmp
,
*
it
,
*
next
;
struct
id_map
*
entry
=
NULL
;
struct
id_map
*
entry
;
struct
lxc_list
*
new
=
NULL
;
struct
lxc_list
*
tmp
=
NULL
;
hostuid_idmap
=
mapped_hostid_entry
(
uid
,
conf
,
ID_TYPE_UID
);
hostgid_idmap
=
mapped_hostid_entry
(
gid
,
conf
,
ID_TYPE_GID
);
/* Allocate new {g,u}id map list. */
new
=
malloc
(
sizeof
(
*
new
));
new
=
malloc
(
sizeof
(
*
new
));
if
(
!
new
)
{
if
(
!
new
)
ERROR
(
"Out of memory building id map"
);
goto
on_error
;
return
NULL
;
}
lxc_list_init
(
new
);
lxc_list_init
(
new
);
if
(
hostuid_mapped
<
0
)
{
tmp
=
malloc
(
sizeof
(
*
tmp
));
if
(
!
tmp
)
goto
on_error
;
entry
=
hostuid_idmap
;
if
(
!
hostuid_idmap
)
{
hostuid_mapped
=
find_unmapped_nsuid
(
conf
,
ID_TYPE_UID
);
hostuid_mapped
=
find_unmapped_nsuid
(
conf
,
ID_TYPE_UID
);
if
(
hostuid_mapped
<
0
)
if
(
hostuid_mapped
<
0
)
goto
err
;
goto
on_error
;
tmp
=
malloc
(
sizeof
(
*
tmp
));
if
(
!
tmp
)
goto
err
;
entry
=
malloc
(
sizeof
(
*
entry
));
entry
=
malloc
(
sizeof
(
*
entry
));
if
(
!
entry
)
{
if
(
!
entry
)
free
(
tmp
);
goto
on_error
;
goto
err
;
}
tmp
->
elem
=
entry
;
tmp
->
elem
=
entry
;
entry
->
idtype
=
ID_TYPE_UID
;
entry
->
idtype
=
ID_TYPE_UID
;
entry
->
nsid
=
hostuid_mapped
;
entry
->
nsid
=
hostuid_mapped
;
entry
->
hostid
=
(
unsigned
long
)
uid
;
entry
->
hostid
=
(
unsigned
long
)
uid
;
entry
->
range
=
1
;
entry
->
range
=
1
;
lxc_list_add_tail
(
new
,
tmp
);
DEBUG
(
"adding uid mapping: nsid %lu hostid %lu range %lu"
,
}
entry
->
nsid
,
entry
->
hostid
,
entry
->
range
);
if
(
hostgid_mapped
<
0
)
{
}
lxc_list_add_tail
(
new
,
tmp
);
entry
=
NULL
;
tmp
=
NULL
;
tmp
=
malloc
(
sizeof
(
*
tmp
));
if
(
!
tmp
)
goto
on_error
;
entry
=
hostgid_idmap
;
if
(
!
hostgid_idmap
)
{
hostgid_mapped
=
find_unmapped_nsuid
(
conf
,
ID_TYPE_GID
);
hostgid_mapped
=
find_unmapped_nsuid
(
conf
,
ID_TYPE_GID
);
if
(
hostgid_mapped
<
0
)
if
(
hostgid_mapped
<
0
)
goto
err
;
goto
on_error
;
tmp
=
malloc
(
sizeof
(
*
tmp
));
if
(
!
tmp
)
goto
err
;
entry
=
malloc
(
sizeof
(
*
entry
));
entry
=
malloc
(
sizeof
(
*
entry
));
if
(
!
entry
)
{
if
(
!
entry
)
free
(
tmp
);
goto
on_error
;
goto
err
;
}
tmp
->
elem
=
entry
;
tmp
->
elem
=
entry
;
entry
->
idtype
=
ID_TYPE_GID
;
entry
->
idtype
=
ID_TYPE_GID
;
entry
->
nsid
=
hostgid_mapped
;
entry
->
nsid
=
hostgid_mapped
;
entry
->
hostid
=
(
unsigned
long
)
gid
;
entry
->
hostid
=
(
unsigned
long
)
gid
;
entry
->
range
=
1
;
entry
->
range
=
1
;
lxc_list_add_tail
(
new
,
tmp
);
DEBUG
(
"adding gid mapping: nsid %lu hostid %lu range %lu"
,
}
entry
->
nsid
,
entry
->
hostid
,
entry
->
range
);
lxc_list_for_each_safe
(
it
,
&
conf
->
id_map
,
next
)
{
tmp
=
malloc
(
sizeof
(
*
tmp
));
if
(
!
tmp
)
goto
err
;
entry
=
malloc
(
sizeof
(
*
entry
));
if
(
!
entry
)
{
free
(
tmp
);
goto
err
;
}
memset
(
entry
,
0
,
sizeof
(
*
entry
));
memcpy
(
entry
,
it
->
elem
,
sizeof
(
*
entry
));
tmp
->
elem
=
entry
;
lxc_list_add_tail
(
new
,
tmp
);
}
}
lxc_list_add_tail
(
new
,
tmp
);
return
new
;
return
new
;
er
r:
on_erro
r:
ERROR
(
"
Out of memory building a new uid/g
id map"
);
ERROR
(
"
failed to allocate memory for new
id map"
);
if
(
new
)
if
(
new
)
lxc_free_idmap
(
new
);
lxc_free_idmap
(
new
);
free
(
new
);
free
(
new
);
free
(
tmp
);
if
(
entry
)
free
(
entry
);
return
NULL
;
return
NULL
;
}
}
/*
/* Run a function in a new user namespace.
* Run a function in a new user namespace.
* The caller's euid/egid will be mapped if it is not already.
* The caller's euid/egid will be mapped in 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
)
int
userns_exec_1
(
struct
lxc_conf
*
conf
,
int
(
*
fn
)(
void
*
),
void
*
data
)
{
{
int
ret
,
pid
;
pid_t
pid
;
uid_t
euid
,
egid
;
struct
userns_fn_data
d
;
struct
userns_fn_data
d
;
char
c
=
'1'
;
int
p
[
2
];
int
p
[
2
];
struct
lxc_list
*
idmap
;
struct
lxc_list
*
it
;
struct
id_map
*
map
;
char
c
=
'1'
;
int
ret
=
-
1
;
struct
lxc_list
*
idmap
=
NULL
,
*
tmplist
=
NULL
;
struct
id_map
*
container_root_uid
=
NULL
,
*
container_root_gid
=
NULL
;
ret
=
pipe
(
p
);
ret
=
pipe
(
p
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
...
@@ -4740,41 +4790,119 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data)
...
@@ -4740,41 +4790,119 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data)
d
.
arg
=
data
;
d
.
arg
=
data
;
d
.
p
[
0
]
=
p
[
0
];
d
.
p
[
0
]
=
p
[
0
];
d
.
p
[
1
]
=
p
[
1
];
d
.
p
[
1
]
=
p
[
1
];
/* Clone child in new user namespace. */
pid
=
lxc_clone
(
run_userns_fn
,
&
d
,
CLONE_NEWUSER
);
pid
=
lxc_clone
(
run_userns_fn
,
&
d
,
CLONE_NEWUSER
);
if
(
pid
<
0
)
if
(
pid
<
0
)
{
goto
err
;
ERROR
(
"failed to clone child process in new user namespace"
);
goto
on_error
;
}
close
(
p
[
0
]);
close
(
p
[
0
]);
p
[
0
]
=
-
1
;
p
[
0
]
=
-
1
;
if
((
idmap
=
idmap_add_id
(
conf
,
geteuid
(),
getegid
()))
==
NULL
)
{
/* Find container root. */
ERROR
(
"Error adding self to container uid/gid map"
);
lxc_list_for_each
(
it
,
&
conf
->
id_map
)
{
goto
err
;
map
=
it
->
elem
;
if
(
map
->
nsid
!=
0
)
continue
;
if
(
map
->
idtype
==
ID_TYPE_UID
&&
container_root_uid
==
NULL
)
{
container_root_uid
=
malloc
(
sizeof
(
*
container_root_uid
));
if
(
!
container_root_uid
)
goto
on_error
;
container_root_uid
->
idtype
=
map
->
idtype
;
container_root_uid
->
hostid
=
map
->
hostid
;
container_root_uid
->
nsid
=
0
;
container_root_uid
->
range
=
map
->
range
;
}
else
if
(
map
->
idtype
==
ID_TYPE_GID
&&
container_root_gid
==
NULL
)
{
container_root_gid
=
malloc
(
sizeof
(
*
container_root_gid
));
if
(
!
container_root_gid
)
goto
on_error
;
container_root_gid
->
idtype
=
map
->
idtype
;
container_root_gid
->
hostid
=
map
->
hostid
;
container_root_gid
->
nsid
=
0
;
container_root_gid
->
range
=
map
->
range
;
}
/* Found container root. */
if
(
container_root_uid
&&
container_root_gid
)
break
;
}
/* This is actually checked earlier but it can't hurt. */
if
(
!
container_root_uid
||
!
container_root_gid
)
{
ERROR
(
"no mapping for container root found"
);
goto
on_error
;
}
/* Check whether the {g,u}id of the user has a mapping. */
euid
=
geteuid
();
egid
=
getegid
();
idmap
=
idmap_add_id
(
conf
,
euid
,
egid
);
if
(
!
idmap
)
{
ERROR
(
"failed to prepare id mapping for uid %d and gid %d"
,
euid
,
egid
);
goto
on_error
;
}
/* Add container root to the map. */
tmplist
=
malloc
(
sizeof
(
*
tmplist
));
if
(
!
tmplist
)
goto
on_error
;
lxc_list_add_elem
(
tmplist
,
container_root_uid
);
lxc_list_add_tail
(
idmap
,
tmplist
);
/* idmap will now keep track of that memory. */
container_root_uid
=
NULL
;
tmplist
=
malloc
(
sizeof
(
*
tmplist
));
if
(
!
tmplist
)
goto
on_error
;
lxc_list_add_elem
(
tmplist
,
container_root_gid
);
lxc_list_add_tail
(
idmap
,
tmplist
);
/* idmap will now keep track of that memory. */
container_root_gid
=
NULL
;
if
(
lxc_log_get_level
()
==
LXC_LOG_PRIORITY_TRACE
)
{
lxc_list_for_each
(
it
,
idmap
)
{
map
=
it
->
elem
;
TRACE
(
"establishing %cid mapping for
\"
%d
\"
in new "
"user namespace: nsuid %lu - hostid %lu - range "
"%lu"
,
(
map
->
idtype
==
ID_TYPE_UID
)
?
'u'
:
'g'
,
pid
,
map
->
nsid
,
map
->
hostid
,
map
->
range
);
}
}
}
/* Set up {g,u}id mapping for user namespace of child process. */
ret
=
lxc_map_ids
(
idmap
,
pid
);
ret
=
lxc_map_ids
(
idmap
,
pid
);
lxc_free_idmap
(
idmap
);
if
(
ret
<
0
)
{
free
(
idmap
);
ERROR
(
"error setting up {g,u}id mappings for child process "
if
(
ret
)
{
"
\"
%d
\"
"
,
ERROR
(
"Error setting up child mappings"
);
pid
);
goto
er
r
;
goto
on_erro
r
;
}
}
/
/ kick the child
/
* Tell child to proceed. */
if
(
write
(
p
[
1
],
&
c
,
1
)
!=
1
)
{
if
(
write
(
p
[
1
],
&
c
,
1
)
!=
1
)
{
SYSERROR
(
"
writing to pipe to child"
);
SYSERROR
(
"
failed telling child process
\"
%d
\"
to proceed"
,
pid
);
goto
er
r
;
goto
on_erro
r
;
}
}
/* Wait for child to finish. */
ret
=
wait_for_pid
(
pid
);
ret
=
wait_for_pid
(
pid
);
close
(
p
[
1
]);
on_error:
return
ret
;
lxc_free_idmap
(
idmap
);
free
(
container_root_uid
);
free
(
container_root_gid
);
err:
if
(
p
[
0
]
!=
-
1
)
if
(
p
[
0
]
!=
-
1
)
close
(
p
[
0
]);
close
(
p
[
0
]);
close
(
p
[
1
]);
close
(
p
[
1
]);
return
-
1
;
return
ret
;
}
}
/* not thread-safe, do not use from api without first forking */
/* not thread-safe, do not use from api without first forking */
...
...
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