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
208b3ee0
Unverified
Commit
208b3ee0
authored
Mar 10, 2020
by
Stéphane Graber
Committed by
GitHub
Mar 10, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3281 from brauner/2020-03-10/fixes
tree-wide: cleanup
parents
32a0f033
bbba37f7
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
560 additions
and
942 deletions
+560
-942
cgfsng.c
src/lxc/cgroups/cgfsng.c
+10
-34
commands.c
src/lxc/commands.c
+98
-129
commands_utils.c
src/lxc/commands_utils.c
+17
-36
conf.c
src/lxc/conf.c
+379
-709
memory_utils.h
src/lxc/memory_utils.h
+25
-6
pam_cgfs.c
src/lxc/pam/pam_cgfs.c
+0
-11
utils.h
src/lxc/utils.h
+7
-0
share_ns.c
src/tests/share_ns.c
+24
-17
No files found.
src/lxc/cgroups/cgfsng.c
View file @
208b3ee0
...
@@ -54,19 +54,6 @@
...
@@ -54,19 +54,6 @@
lxc_log_define
(
cgfsng
,
cgroup
);
lxc_log_define
(
cgfsng
,
cgroup
);
static
void
free_string_list
(
char
**
clist
)
{
int
i
;
if
(
!
clist
)
return
;
for
(
i
=
0
;
clist
[
i
];
i
++
)
free
(
clist
[
i
]);
free
(
clist
);
}
/* Given a pointer to a null-terminated array of pointers, realloc to add one
/* Given a pointer to a null-terminated array of pointers, realloc to add one
* entry, and point the new entry to NULL. Do not fail. Return the index to the
* entry, and point the new entry to NULL. Do not fail. Return the index to the
* second-to-last entry - that is, the one which is now available for use
* second-to-last entry - that is, the one which is now available for use
...
@@ -2940,12 +2927,11 @@ static void cg_unified_delegate(char ***delegate)
...
@@ -2940,12 +2927,11 @@ static void cg_unified_delegate(char ***delegate)
*/
*/
static
int
cg_hybrid_init
(
struct
cgroup_ops
*
ops
,
bool
relative
,
bool
unprivileged
)
static
int
cg_hybrid_init
(
struct
cgroup_ops
*
ops
,
bool
relative
,
bool
unprivileged
)
{
{
__do_free
char
*
basecginfo
=
NULL
;
__do_free
char
*
basecginfo
=
NULL
,
*
line
=
NULL
;
__do_free
char
*
line
=
NULL
;
__do_free
_string_list
char
**
klist
=
NULL
,
**
nlist
=
NULL
;
__do_fclose
FILE
*
f
=
NULL
;
__do_fclose
FILE
*
f
=
NULL
;
int
ret
;
int
ret
;
size_t
len
=
0
;
size_t
len
=
0
;
char
**
klist
=
NULL
,
**
nlist
=
NULL
;
/* Root spawned containers escape the current cgroup, so use init's
/* Root spawned containers escape the current cgroup, so use init's
* cgroups as our base in that case.
* cgroups as our base in that case.
...
@@ -2968,11 +2954,11 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
...
@@ -2968,11 +2954,11 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
lxc_cgfsng_print_basecg_debuginfo
(
basecginfo
,
klist
,
nlist
);
lxc_cgfsng_print_basecg_debuginfo
(
basecginfo
,
klist
,
nlist
);
while
(
getline
(
&
line
,
&
len
,
f
)
!=
-
1
)
{
while
(
getline
(
&
line
,
&
len
,
f
)
!=
-
1
)
{
__do_free
char
*
base_cgroup
=
NULL
,
*
mountpoint
=
NULL
;
__do_free_string_list
char
**
controller_list
=
NULL
;
int
type
;
int
type
;
bool
writeable
;
bool
writeable
;
struct
hierarchy
*
new
;
struct
hierarchy
*
new
;
char
*
base_cgroup
=
NULL
,
*
mountpoint
=
NULL
;
char
**
controller_list
=
NULL
;
type
=
get_cgroup_version
(
line
);
type
=
get_cgroup_version
(
line
);
if
(
type
==
0
)
if
(
type
==
0
)
...
@@ -3000,18 +2986,18 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
...
@@ -3000,18 +2986,18 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
if
(
type
==
CGROUP_SUPER_MAGIC
)
if
(
type
==
CGROUP_SUPER_MAGIC
)
if
(
controller_list_is_dup
(
ops
->
hierarchies
,
controller_list
))
if
(
controller_list_is_dup
(
ops
->
hierarchies
,
controller_list
))
log_trace_errno
(
goto
next
,
EEXIST
,
"Skipping duplicating controller"
);
log_trace_errno
(
continue
,
EEXIST
,
"Skipping duplicating controller"
);
mountpoint
=
cg_hybrid_get_mountpoint
(
line
);
mountpoint
=
cg_hybrid_get_mountpoint
(
line
);
if
(
!
mountpoint
)
if
(
!
mountpoint
)
log_error_errno
(
goto
next
,
EINVAL
,
"Failed parsing mountpoint from
\"
%s
\"
"
,
line
);
log_error_errno
(
continue
,
EINVAL
,
"Failed parsing mountpoint from
\"
%s
\"
"
,
line
);
if
(
type
==
CGROUP_SUPER_MAGIC
)
if
(
type
==
CGROUP_SUPER_MAGIC
)
base_cgroup
=
cg_hybrid_get_current_cgroup
(
basecginfo
,
controller_list
[
0
],
CGROUP_SUPER_MAGIC
);
base_cgroup
=
cg_hybrid_get_current_cgroup
(
basecginfo
,
controller_list
[
0
],
CGROUP_SUPER_MAGIC
);
else
else
base_cgroup
=
cg_hybrid_get_current_cgroup
(
basecginfo
,
NULL
,
CGROUP2_SUPER_MAGIC
);
base_cgroup
=
cg_hybrid_get_current_cgroup
(
basecginfo
,
NULL
,
CGROUP2_SUPER_MAGIC
);
if
(
!
base_cgroup
)
if
(
!
base_cgroup
)
log_error_errno
(
goto
next
,
EINVAL
,
"Failed to find current cgroup"
);
log_error_errno
(
continue
,
EINVAL
,
"Failed to find current cgroup"
);
trim
(
base_cgroup
);
trim
(
base_cgroup
);
prune_init_scope
(
base_cgroup
);
prune_init_scope
(
base_cgroup
);
...
@@ -3020,7 +3006,7 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
...
@@ -3020,7 +3006,7 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
else
else
writeable
=
test_writeable_v1
(
mountpoint
,
base_cgroup
);
writeable
=
test_writeable_v1
(
mountpoint
,
base_cgroup
);
if
(
!
writeable
)
if
(
!
writeable
)
log_trace_errno
(
goto
next
,
EROFS
,
"The %s group is not writeable"
,
base_cgroup
);
log_trace_errno
(
continue
,
EROFS
,
"The %s group is not writeable"
,
base_cgroup
);
if
(
type
==
CGROUP2_SUPER_MAGIC
)
{
if
(
type
==
CGROUP2_SUPER_MAGIC
)
{
char
*
cgv2_ctrl_path
;
char
*
cgv2_ctrl_path
;
...
@@ -3040,26 +3026,16 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
...
@@ -3040,26 +3026,16 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
/* Exclude all controllers that cgroup use does not want. */
/* Exclude all controllers that cgroup use does not want. */
if
(
!
cgroup_use_wants_controllers
(
ops
,
controller_list
))
if
(
!
cgroup_use_wants_controllers
(
ops
,
controller_list
))
log_trace_errno
(
goto
next
,
EINVAL
,
"Skipping controller"
);
log_trace_errno
(
continue
,
EINVAL
,
"Skipping controller"
);
new
=
add_hierarchy
(
&
ops
->
hierarchies
,
controller_list
,
mountpoint
,
base_cgroup
,
type
);
new
=
add_hierarchy
(
&
ops
->
hierarchies
,
move_ptr
(
controller_list
),
move_ptr
(
mountpoint
),
move_ptr
(
base_cgroup
)
,
type
);
if
(
type
==
CGROUP2_SUPER_MAGIC
&&
!
ops
->
unified
)
{
if
(
type
==
CGROUP2_SUPER_MAGIC
&&
!
ops
->
unified
)
{
if
(
unprivileged
)
if
(
unprivileged
)
cg_unified_delegate
(
&
new
->
cgroup2_chown
);
cg_unified_delegate
(
&
new
->
cgroup2_chown
);
ops
->
unified
=
new
;
ops
->
unified
=
new
;
}
}
continue
;
next:
free_string_list
(
controller_list
);
free
(
mountpoint
);
free
(
base_cgroup
);
}
}
free_string_list
(
klist
);
free_string_list
(
nlist
);
TRACE
(
"Writable cgroup hierarchies:"
);
TRACE
(
"Writable cgroup hierarchies:"
);
lxc_cgfsng_print_hierarchies
(
ops
);
lxc_cgfsng_print_hierarchies
(
ops
);
...
...
src/lxc/commands.c
View file @
208b3ee0
...
@@ -191,20 +191,16 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
...
@@ -191,20 +191,16 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
errno
=
EMSGSIZE
;
errno
=
EMSGSIZE
;
ret
=
lxc_send_nointr
(
fd
,
rsp
,
sizeof
(
*
rsp
),
MSG_NOSIGNAL
);
ret
=
lxc_send_nointr
(
fd
,
rsp
,
sizeof
(
*
rsp
),
MSG_NOSIGNAL
);
if
(
ret
<
0
||
(
size_t
)
ret
!=
sizeof
(
*
rsp
))
{
if
(
ret
<
0
||
(
size_t
)
ret
!=
sizeof
(
*
rsp
))
SYSERROR
(
"Failed to send command response %zd"
,
ret
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to send command response %zd"
,
ret
);
return
-
1
;
}
if
(
!
rsp
->
data
||
rsp
->
datalen
<=
0
)
if
(
!
rsp
->
data
||
rsp
->
datalen
<=
0
)
return
0
;
return
0
;
errno
=
EMSGSIZE
;
errno
=
EMSGSIZE
;
ret
=
lxc_send_nointr
(
fd
,
rsp
->
data
,
rsp
->
datalen
,
MSG_NOSIGNAL
);
ret
=
lxc_send_nointr
(
fd
,
rsp
->
data
,
rsp
->
datalen
,
MSG_NOSIGNAL
);
if
(
ret
<
0
||
ret
!=
(
ssize_t
)
rsp
->
datalen
)
{
if
(
ret
<
0
||
ret
!=
(
ssize_t
)
rsp
->
datalen
)
SYSWARN
(
"Failed to send command response data %zd"
,
ret
);
return
log_warn_errno
(
-
1
,
errno
,
"Failed to send command response data %zd"
,
ret
);
return
-
1
;
}
return
0
;
return
0
;
}
}
...
@@ -277,13 +273,11 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
...
@@ -277,13 +273,11 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
client_fd
=
lxc_cmd_send
(
name
,
cmd
,
lxcpath
,
hashed_sock_name
);
client_fd
=
lxc_cmd_send
(
name
,
cmd
,
lxcpath
,
hashed_sock_name
);
if
(
client_fd
<
0
)
{
if
(
client_fd
<
0
)
{
SYSTRACE
(
"Command
\"
%s
\"
failed to connect command socket"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
if
(
errno
==
ECONNREFUSED
||
errno
==
EPIPE
)
if
(
errno
==
ECONNREFUSED
||
errno
==
EPIPE
)
*
stopped
=
1
;
*
stopped
=
1
;
return
-
1
;
return
log_trace_errno
(
-
1
,
errno
,
"Command
\"
%s
\"
failed to connect command socket"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
}
}
ret
=
lxc_cmd_rsp_recv
(
client_fd
,
cmd
);
ret
=
lxc_cmd_rsp_recv
(
client_fd
,
cmd
);
...
@@ -335,13 +329,13 @@ int lxc_try_cmd(const char *name, const char *lxcpath)
...
@@ -335,13 +329,13 @@ int lxc_try_cmd(const char *name, const char *lxcpath)
pid_t
lxc_cmd_get_init_pid
(
const
char
*
name
,
const
char
*
lxcpath
)
pid_t
lxc_cmd_get_init_pid
(
const
char
*
name
,
const
char
*
lxcpath
)
{
{
int
ret
,
stopped
;
int
ret
,
stopped
;
intmax_t
pid
;
intmax_t
pid
=
-
1
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_INIT_PID
.
cmd
=
LXC_CMD_GET_INIT_PID
},
},
.
rsp
=
{
.
rsp
=
{
.
data
=
INTMAX_TO_PTR
(
(
intmax_t
){
-
1
}
)
.
data
=
INTMAX_TO_PTR
(
pid
)
}
}
};
};
...
@@ -384,7 +378,9 @@ int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
...
@@ -384,7 +378,9 @@ int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
{
{
int
ret
,
stopped
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_CLONE_FLAGS
},
.
req
=
{
.
cmd
=
LXC_CMD_GET_CLONE_FLAGS
,
},
};
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
...
@@ -398,7 +394,9 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
...
@@ -398,7 +394,9 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
struct
lxc_handler
*
handler
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
struct
lxc_cmd_rsp
rsp
=
{
.
data
=
INT_TO_PTR
(
handler
->
ns_clone_flags
)
};
struct
lxc_cmd_rsp
rsp
=
{
.
data
=
INT_TO_PTR
(
handler
->
ns_clone_flags
),
};
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
}
}
...
@@ -544,7 +542,9 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath)
...
@@ -544,7 +542,9 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath)
{
{
int
ret
,
stopped
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_STATE
}
.
req
=
{
.
cmd
=
LXC_CMD_GET_STATE
,
},
};
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
...
@@ -554,22 +554,21 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath)
...
@@ -554,22 +554,21 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath)
if
(
ret
<
0
)
if
(
ret
<
0
)
return
-
1
;
return
-
1
;
if
(
!
ret
)
{
if
(
!
ret
)
WARN
(
"Container
\"
%s
\"
has stopped before sending its state"
,
name
);
return
log_warn
(
-
1
,
"Container
\"
%s
\"
has stopped before sending its state"
,
name
);
return
-
1
;
}
DEBUG
(
"Container
\"
%s
\"
is in
\"
%s
\"
state"
,
name
,
lxc_state2str
(
PTR_TO_INT
(
cmd
.
rsp
.
data
)));
return
PTR_TO_INT
(
cmd
.
rsp
.
data
);
return
log_debug
(
PTR_TO_INT
(
cmd
.
rsp
.
data
),
"Container
\"
%s
\"
is in
\"
%s
\"
state"
,
name
,
lxc_state2str
(
PTR_TO_INT
(
cmd
.
rsp
.
data
)));
}
}
static
int
lxc_cmd_get_state_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
static
int
lxc_cmd_get_state_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
struct
lxc_cmd_rsp
rsp
=
{
.
data
=
INT_TO_PTR
(
handler
->
state
)
};
struct
lxc_cmd_rsp
rsp
=
{
.
data
=
INT_TO_PTR
(
handler
->
state
),
};
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
}
}
...
@@ -587,15 +586,15 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
...
@@ -587,15 +586,15 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
{
{
int
ret
,
stopped
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_STOP
},
.
req
=
{
.
cmd
=
LXC_CMD_STOP
,
},
};
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
if
(
stopped
)
{
if
(
stopped
)
INFO
(
"Container
\"
%s
\"
is already stopped"
,
name
);
return
log_info
(
0
,
"Container
\"
%s
\"
is already stopped"
,
name
);
return
0
;
}
return
-
1
;
return
-
1
;
}
}
...
@@ -603,14 +602,10 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
...
@@ -603,14 +602,10 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
/* We do not expect any answer, because we wait for the connection to be
/* We do not expect any answer, because we wait for the connection to be
* closed.
* closed.
*/
*/
if
(
ret
>
0
)
{
if
(
ret
>
0
)
errno
=
-
cmd
.
rsp
.
ret
;
return
log_error_errno
(
-
1
,
-
cmd
.
rsp
.
ret
,
"Failed to stop container
\"
%s
\"
"
,
name
);
SYSERROR
(
"Failed to stop container
\"
%s
\"
"
,
name
);
return
-
1
;
}
INFO
(
"Container
\"
%s
\"
has stopped"
,
name
);
return
log_info
(
0
,
"Container
\"
%s
\"
has stopped"
,
name
);
return
0
;
}
}
static
int
lxc_cmd_stop_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
static
int
lxc_cmd_stop_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
...
@@ -657,7 +652,7 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
...
@@ -657,7 +652,7 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
/* should never be called */
/* should never be called */
return
-
1
;
return
log_error_errno
(
-
1
,
ENOSYS
,
"Called lxc_cmd_terminal_winch_callback()"
)
;
}
}
/*
/*
...
@@ -676,7 +671,10 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
...
@@ -676,7 +671,10 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
__do_free
struct
lxc_cmd_console_rsp_data
*
rspdata
=
NULL
;
__do_free
struct
lxc_cmd_console_rsp_data
*
rspdata
=
NULL
;
int
ret
,
stopped
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_CONSOLE
,
.
data
=
INT_TO_PTR
(
*
ttynum
)
},
.
req
=
{
.
cmd
=
LXC_CMD_CONSOLE
,
.
data
=
INT_TO_PTR
(
*
ttynum
),
},
};
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
...
@@ -684,28 +682,20 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
...
@@ -684,28 +682,20 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
return
ret
;
return
ret
;
rspdata
=
cmd
.
rsp
.
data
;
rspdata
=
cmd
.
rsp
.
data
;
if
(
cmd
.
rsp
.
ret
<
0
)
{
if
(
cmd
.
rsp
.
ret
<
0
)
errno
=
-
cmd
.
rsp
.
ret
;
return
log_error_errno
(
-
1
,
-
cmd
.
rsp
.
ret
,
"Denied access to tty"
);
SYSERROR
(
"Denied access to tty"
);
return
-
1
;
}
if
(
ret
==
0
)
{
if
(
ret
==
0
)
ERROR
(
"tty number %d invalid, busy or all ttys busy"
,
*
ttynum
);
return
log_error
(
-
1
,
"tty number %d invalid, busy or all ttys busy"
,
*
ttynum
);
return
-
1
;
}
if
(
rspdata
->
masterfd
<
0
)
{
if
(
rspdata
->
masterfd
<
0
)
ERROR
(
"Unable to allocate fd for tty %d"
,
rspdata
->
ttynum
);
return
log_error
(
-
1
,
"Unable to allocate fd for tty %d"
,
rspdata
->
ttynum
);
return
-
1
;
}
ret
=
cmd
.
rsp
.
ret
;
/* socket fd */
ret
=
cmd
.
rsp
.
ret
;
/* socket fd */
*
fd
=
rspdata
->
masterfd
;
*
fd
=
rspdata
->
masterfd
;
*
ttynum
=
rspdata
->
ttynum
;
*
ttynum
=
rspdata
->
ttynum
;
INFO
(
"Alloced fd %d for tty %d via socket %d"
,
*
fd
,
rspdata
->
ttynum
,
ret
);
return
ret
;
return
log_info
(
ret
,
"Alloced fd %d for tty %d via socket %d"
,
*
fd
,
rspdata
->
ttynum
,
ret
)
;
}
}
static
int
lxc_cmd_console_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
static
int
lxc_cmd_console_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
...
@@ -749,7 +739,9 @@ char *lxc_cmd_get_name(const char *hashed_sock_name)
...
@@ -749,7 +739,9 @@ char *lxc_cmd_get_name(const char *hashed_sock_name)
{
{
int
ret
,
stopped
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_NAME
},
.
req
=
{
.
cmd
=
LXC_CMD_GET_NAME
,
},
};
};
ret
=
lxc_cmd
(
NULL
,
&
cmd
,
&
stopped
,
NULL
,
hashed_sock_name
);
ret
=
lxc_cmd
(
NULL
,
&
cmd
,
&
stopped
,
NULL
,
hashed_sock_name
);
...
@@ -788,7 +780,9 @@ char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
...
@@ -788,7 +780,9 @@ char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
{
{
int
ret
,
stopped
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_LXCPATH
},
.
req
=
{
.
cmd
=
LXC_CMD_GET_LXCPATH
,
},
};
};
ret
=
lxc_cmd
(
NULL
,
&
cmd
,
&
stopped
,
NULL
,
hashed_sock_name
);
ret
=
lxc_cmd
(
NULL
,
&
cmd
,
&
stopped
,
NULL
,
hashed_sock_name
);
...
@@ -805,13 +799,11 @@ static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
...
@@ -805,13 +799,11 @@ static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
struct
lxc_handler
*
handler
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
struct
lxc_cmd_rsp
rsp
;
struct
lxc_cmd_rsp
rsp
=
{
.
ret
=
0
,
memset
(
&
rsp
,
0
,
sizeof
(
rsp
));
.
data
=
(
char
*
)
handler
->
lxcpath
,
.
datalen
=
strlen
(
handler
->
lxcpath
)
+
1
,
rsp
.
ret
=
0
;
};
rsp
.
data
=
(
char
*
)
handler
->
lxcpath
;
rsp
.
datalen
=
strlen
(
handler
->
lxcpath
)
+
1
;
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
return
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
}
}
...
@@ -824,11 +816,11 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
...
@@ -824,11 +816,11 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
int
state
,
stopped
;
int
state
,
stopped
;
ssize_t
ret
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
req
=
{
.
cmd
=
LXC_CMD_ADD_STATE_CLIENT
,
.
cmd
=
LXC_CMD_ADD_STATE_CLIENT
,
.
data
=
states
,
.
data
=
states
,
.
datalen
=
(
sizeof
(
lxc_state_t
)
*
MAX_STATE
)
.
datalen
=
(
sizeof
(
lxc_state_t
)
*
MAX_STATE
)
},
},
};
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
...
@@ -846,21 +838,15 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
...
@@ -846,21 +838,15 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
* function.
* function.
*/
*/
clientfd
=
cmd
.
rsp
.
ret
;
clientfd
=
cmd
.
rsp
.
ret
;
if
(
clientfd
<
0
)
{
if
(
clientfd
<
0
)
errno
=
-
clientfd
;
return
log_error_errno
(
-
1
,
-
clientfd
,
"Failed to receive socket fd"
);
SYSERROR
(
"Failed to receive socket fd"
);
return
-
1
;
}
state
=
PTR_TO_INT
(
cmd
.
rsp
.
data
);
state
=
PTR_TO_INT
(
cmd
.
rsp
.
data
);
if
(
state
<
MAX_STATE
)
{
if
(
state
<
MAX_STATE
)
TRACE
(
"Container is already in requested state %s"
,
lxc_state2str
(
state
));
return
log_trace
(
state
,
"Container is already in requested state %s"
,
lxc_state2str
(
state
));
return
state
;
}
*
state_client_fd
=
move_fd
(
clientfd
);
*
state_client_fd
=
move_fd
(
clientfd
);
TRACE
(
"Added state client %d to state client list"
,
*
state_client_fd
);
return
log_trace
(
MAX_STATE
,
"Added state client %d to state client list"
,
*
state_client_fd
);
return
MAX_STATE
;
}
}
static
int
lxc_cmd_add_state_client_callback
(
__owns
int
fd
,
struct
lxc_cmd_req
*
req
,
static
int
lxc_cmd_add_state_client_callback
(
__owns
int
fd
,
struct
lxc_cmd_req
*
req
,
...
@@ -908,11 +894,11 @@ int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
...
@@ -908,11 +894,11 @@ int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
int
stopped
=
0
;
int
stopped
=
0
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
req
=
{
.
cmd
=
LXC_CMD_ADD_BPF_DEVICE_CGROUP
,
.
cmd
=
LXC_CMD_ADD_BPF_DEVICE_CGROUP
,
.
data
=
device
,
.
data
=
device
,
.
datalen
=
sizeof
(
struct
device_item
),
.
datalen
=
sizeof
(
struct
device_item
),
},
},
};
};
int
ret
;
int
ret
;
...
@@ -1094,17 +1080,15 @@ int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
...
@@ -1094,17 +1080,15 @@ int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
int
stopped
;
int
stopped
;
ssize_t
ret
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
req
=
{
.
cmd
=
LXC_CMD_SERVE_STATE_CLIENTS
,
.
cmd
=
LXC_CMD_SERVE_STATE_CLIENTS
,
.
data
=
INT_TO_PTR
(
state
)
.
data
=
INT_TO_PTR
(
state
)
},
},
};
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to execute command"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to serve state clients"
);
return
-
1
;
}
return
0
;
return
0
;
}
}
...
@@ -1128,8 +1112,9 @@ static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
...
@@ -1128,8 +1112,9 @@ static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
return
0
;
return
0
;
reap_client_fd:
reap_client_fd:
/* Special indicator to lxc_cmd_handler() to close the fd and do related
/*
* cleanup.
* Special indicator to lxc_cmd_handler() to close the fd and do
* related cleanup.
*/
*/
return
1
;
return
1
;
}
}
...
@@ -1150,10 +1135,8 @@ int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
...
@@ -1150,10 +1135,8 @@ int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
};
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to execute command"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to add seccomp listener"
);
return
-
1
;
}
return
cmd
.
rsp
.
ret
;
return
cmd
.
rsp
.
ret
;
#else
#else
...
@@ -1224,7 +1207,7 @@ static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req,
...
@@ -1224,7 +1207,7 @@ static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req,
{
{
int
timeout
=
PTR_TO_INT
(
req
->
data
);
int
timeout
=
PTR_TO_INT
(
req
->
data
);
struct
lxc_cmd_rsp
rsp
=
{
struct
lxc_cmd_rsp
rsp
=
{
.
ret
=
-
ENOENT
,
.
ret
=
-
ENOENT
,
};
};
struct
cgroup_ops
*
ops
=
handler
->
cgroup_ops
;
struct
cgroup_ops
*
ops
=
handler
->
cgroup_ops
;
...
@@ -1257,7 +1240,7 @@ static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
...
@@ -1257,7 +1240,7 @@ static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
{
{
int
timeout
=
PTR_TO_INT
(
req
->
data
);
int
timeout
=
PTR_TO_INT
(
req
->
data
);
struct
lxc_cmd_rsp
rsp
=
{
struct
lxc_cmd_rsp
rsp
=
{
.
ret
=
-
ENOENT
,
.
ret
=
-
ENOENT
,
};
};
struct
cgroup_ops
*
ops
=
handler
->
cgroup_ops
;
struct
cgroup_ops
*
ops
=
handler
->
cgroup_ops
;
...
@@ -1451,28 +1434,20 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
...
@@ -1451,28 +1434,20 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
int
opt
=
1
,
ret
=
-
1
;
int
opt
=
1
,
ret
=
-
1
;
connection
=
accept
(
fd
,
NULL
,
0
);
connection
=
accept
(
fd
,
NULL
,
0
);
if
(
connection
<
0
)
{
if
(
connection
<
0
)
SYSERROR
(
"Failed to accept connection to run command"
);
return
log_error_errno
(
LXC_MAINLOOP_ERROR
,
errno
,
"Failed to accept connection to run command"
);
return
LXC_MAINLOOP_ERROR
;
}
ret
=
fcntl
(
connection
,
F_SETFD
,
FD_CLOEXEC
);
ret
=
fcntl
(
connection
,
F_SETFD
,
FD_CLOEXEC
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set close-on-exec on incoming command connection"
);
return
log_error_errno
(
ret
,
errno
,
"Failed to set close-on-exec on incoming command connection"
);
return
ret
;
}
ret
=
setsockopt
(
connection
,
SOL_SOCKET
,
SO_PASSCRED
,
&
opt
,
sizeof
(
opt
));
ret
=
setsockopt
(
connection
,
SOL_SOCKET
,
SO_PASSCRED
,
&
opt
,
sizeof
(
opt
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to enable necessary credentials on command socket"
);
return
log_error_errno
(
ret
,
errno
,
"Failed to enable necessary credentials on command socket"
);
return
ret
;
}
ret
=
lxc_mainloop_add_handler
(
descr
,
connection
,
lxc_cmd_handler
,
data
);
ret
=
lxc_mainloop_add_handler
(
descr
,
connection
,
lxc_cmd_handler
,
data
);
if
(
ret
)
{
if
(
ret
)
ERROR
(
"Failed to add command handler"
);
return
log_error
(
ret
,
"Failed to add command handler"
);
return
ret
;
}
move_fd
(
connection
);
move_fd
(
connection
);
return
ret
;
return
ret
;
...
@@ -1490,21 +1465,17 @@ int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
...
@@ -1490,21 +1465,17 @@ int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
fd
=
lxc_abstract_unix_open
(
path
,
SOCK_STREAM
,
0
);
fd
=
lxc_abstract_unix_open
(
path
,
SOCK_STREAM
,
0
);
if
(
fd
<
0
)
{
if
(
fd
<
0
)
{
SYSERROR
(
"Failed to create command socket %s"
,
&
path
[
1
]);
if
(
errno
==
EADDRINUSE
)
if
(
errno
==
EADDRINUSE
)
ERROR
(
"Container
\"
%s
\"
appears to be already running"
,
name
);
ERROR
(
"Container
\"
%s
\"
appears to be already running"
,
name
);
return
-
1
;
return
log_error_errno
(
-
1
,
errno
,
"Failed to create command socket %s"
,
&
path
[
1
])
;
}
}
ret
=
fcntl
(
fd
,
F_SETFD
,
FD_CLOEXEC
);
ret
=
fcntl
(
fd
,
F_SETFD
,
FD_CLOEXEC
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set FD_CLOEXEC on command socket file descriptor"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to set FD_CLOEXEC on command socket file descriptor"
);
return
-
1
;
}
TRACE
(
"Created abstract unix socket
\"
%s
\"
"
,
&
path
[
1
]);
return
log_trace
(
move_fd
(
fd
),
"Created abstract unix socket
\"
%s
\"
"
,
&
path
[
1
]);
return
move_fd
(
fd
);
}
}
int
lxc_cmd_mainloop_add
(
const
char
*
name
,
struct
lxc_epoll_descr
*
descr
,
int
lxc_cmd_mainloop_add
(
const
char
*
name
,
struct
lxc_epoll_descr
*
descr
,
...
@@ -1514,10 +1485,8 @@ int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
...
@@ -1514,10 +1485,8 @@ int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
int
ret
;
int
ret
;
ret
=
lxc_mainloop_add_handler
(
descr
,
fd
,
lxc_cmd_accept
,
handler
);
ret
=
lxc_mainloop_add_handler
(
descr
,
fd
,
lxc_cmd_accept
,
handler
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to add handler for command socket"
);
return
log_error
(
ret
,
"Failed to add handler for command socket"
);
return
ret
;
}
move_fd
(
fd
);
move_fd
(
fd
);
return
ret
;
return
ret
;
...
...
src/lxc/commands_utils.c
View file @
208b3ee0
...
@@ -39,26 +39,18 @@ int lxc_cmd_sock_rcv_state(int state_client_fd, int timeout)
...
@@ -39,26 +39,18 @@ int lxc_cmd_sock_rcv_state(int state_client_fd, int timeout)
out
.
tv_sec
=
timeout
;
out
.
tv_sec
=
timeout
;
ret
=
setsockopt
(
state_client_fd
,
SOL_SOCKET
,
SO_RCVTIMEO
,
ret
=
setsockopt
(
state_client_fd
,
SOL_SOCKET
,
SO_RCVTIMEO
,
(
const
void
*
)
&
out
,
sizeof
(
out
));
(
const
void
*
)
&
out
,
sizeof
(
out
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set %ds timeout on container "
return
log_error_errno
(
-
1
,
errno
,
"Failed to set %ds timeout on container state socket"
,
timeout
);
"state socket"
,
timeout
);
return
-
1
;
}
}
}
memset
(
&
msg
,
0
,
sizeof
(
msg
));
memset
(
&
msg
,
0
,
sizeof
(
msg
));
ret
=
lxc_recv_nointr
(
state_client_fd
,
&
msg
,
sizeof
(
msg
),
0
);
ret
=
lxc_recv_nointr
(
state_client_fd
,
&
msg
,
sizeof
(
msg
),
0
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to receive message"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to receive message"
);
return
-
1
;
}
TRACE
(
"Received state %s from state client %d"
,
lxc_state2str
(
msg
.
value
),
state_client_fd
);
return
msg
.
value
;
return
log_trace
(
msg
.
value
,
"Received state %s from state client %d"
,
lxc_state2str
(
msg
.
value
),
state_client_fd
);
}
}
/* Register a new state client and retrieve state from command socket. */
/* Register a new state client and retrieve state from command socket. */
...
@@ -110,26 +102,20 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen,
...
@@ -110,26 +102,20 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen,
if
(
hashed_sock_name
!=
NULL
)
{
if
(
hashed_sock_name
!=
NULL
)
{
ret
=
snprintf
(
offset
,
len
,
"lxc/%s/%s"
,
hashed_sock_name
,
suffix
);
ret
=
snprintf
(
offset
,
len
,
"lxc/%s/%s"
,
hashed_sock_name
,
suffix
);
if
(
ret
<
0
||
ret
>=
len
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
ERROR
(
"Failed to create abstract socket name"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create abstract socket name"
);
return
-
1
;
}
return
0
;
return
0
;
}
}
if
(
!
lxcpath
)
{
if
(
!
lxcpath
)
{
lxcpath
=
lxc_global_config_value
(
"lxc.lxcpath"
);
lxcpath
=
lxc_global_config_value
(
"lxc.lxcpath"
);
if
(
!
lxcpath
)
{
if
(
!
lxcpath
)
ERROR
(
"Failed to allocate memory"
);
return
log_error
(
-
1
,
"Failed to allocate memory"
);
return
-
1
;
}
}
}
ret
=
snprintf
(
offset
,
len
,
"%s/%s/%s"
,
lxcpath
,
name
,
suffix
);
ret
=
snprintf
(
offset
,
len
,
"%s/%s/%s"
,
lxcpath
,
name
,
suffix
);
if
(
ret
<
0
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
ERROR
(
"Failed to create abstract socket name"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create abstract socket name"
);
return
-
1
;
}
if
(
ret
<
len
)
if
(
ret
<
len
)
return
0
;
return
0
;
...
@@ -137,17 +123,13 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen,
...
@@ -137,17 +123,13 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen,
tmplen
=
strlen
(
name
)
+
strlen
(
lxcpath
)
+
2
;
tmplen
=
strlen
(
name
)
+
strlen
(
lxcpath
)
+
2
;
tmppath
=
must_realloc
(
NULL
,
tmplen
);
tmppath
=
must_realloc
(
NULL
,
tmplen
);
ret
=
snprintf
(
tmppath
,
tmplen
,
"%s/%s"
,
lxcpath
,
name
);
ret
=
snprintf
(
tmppath
,
tmplen
,
"%s/%s"
,
lxcpath
,
name
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
tmplen
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
tmplen
)
ERROR
(
"Failed to create abstract socket name"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create abstract socket name"
);
return
-
1
;
}
hash
=
fnv_64a_buf
(
tmppath
,
ret
,
FNV1A_64_INIT
);
hash
=
fnv_64a_buf
(
tmppath
,
ret
,
FNV1A_64_INIT
);
ret
=
snprintf
(
offset
,
len
,
"lxc/%016"
PRIx64
"/%s"
,
hash
,
suffix
);
ret
=
snprintf
(
offset
,
len
,
"lxc/%016"
PRIx64
"/%s"
,
hash
,
suffix
);
if
(
ret
<
0
||
ret
>=
len
)
{
if
(
ret
<
0
||
ret
>=
len
)
ERROR
(
"Failed to create abstract socket name"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create abstract socket name"
);
return
-
1
;
}
return
0
;
return
0
;
}
}
...
@@ -198,8 +180,7 @@ int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler,
...
@@ -198,8 +180,7 @@ int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler,
return
state
;
return
state
;
}
}
TRACE
(
"Added state client %d to state client list"
,
state_client_fd
);
move_ptr
(
newclient
);
move_ptr
(
newclient
);
move_ptr
(
tmplist
);
move_ptr
(
tmplist
);
return
MAX_STATE
;
return
log_trace
(
MAX_STATE
,
"Added state client %d to state client list"
,
state_client_fd
)
;
}
}
src/lxc/conf.c
View file @
208b3ee0
...
@@ -288,28 +288,20 @@ static struct limit_opt limit_opt[] = {
...
@@ -288,28 +288,20 @@ static struct limit_opt limit_opt[] = {
static
int
run_buffer
(
char
*
buffer
)
static
int
run_buffer
(
char
*
buffer
)
{
{
__do_free
char
*
output
=
NULL
;
__do_free
char
*
output
=
NULL
;
__do_lxc_pclose
struct
lxc_popen_FILE
*
f
=
NULL
;
int
fd
,
ret
;
int
fd
,
ret
;
struct
lxc_popen_FILE
*
f
;
f
=
lxc_popen
(
buffer
);
f
=
lxc_popen
(
buffer
);
if
(
!
f
)
{
if
(
!
f
)
SYSERROR
(
"Failed to popen() %s"
,
buffer
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to popen() %s"
,
buffer
);
return
-
1
;
}
output
=
malloc
(
LXC_LOG_BUFFER_SIZE
);
output
=
malloc
(
LXC_LOG_BUFFER_SIZE
);
if
(
!
output
)
{
if
(
!
output
)
ERROR
(
"Failed to allocate memory for %s"
,
buffer
);
return
log_error_errno
(
-
1
,
ENOMEM
,
"Failed to allocate memory for %s"
,
buffer
);
lxc_pclose
(
f
);
return
-
1
;
}
fd
=
fileno
(
f
->
f
);
fd
=
fileno
(
f
->
f
);
if
(
fd
<
0
)
{
if
(
fd
<
0
)
SYSERROR
(
"Failed to retrieve underlying file descriptor"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to retrieve underlying file descriptor"
);
lxc_pclose
(
f
);
return
-
1
;
}
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
ssize_t
bytes_read
;
ssize_t
bytes_read
;
...
@@ -324,17 +316,13 @@ static int run_buffer(char *buffer)
...
@@ -324,17 +316,13 @@ static int run_buffer(char *buffer)
break
;
break
;
}
}
ret
=
lxc_pclose
(
f
);
ret
=
lxc_pclose
(
move_ptr
(
f
));
if
(
ret
==
-
1
)
{
if
(
ret
==
-
1
)
SYSERROR
(
"Script exited with error"
);
return
log_error_errno
(
-
1
,
errno
,
"Script exited with error"
);
return
-
1
;
else
if
(
WIFEXITED
(
ret
)
&&
WEXITSTATUS
(
ret
)
!=
0
)
}
else
if
(
WIFEXITED
(
ret
)
&&
WEXITSTATUS
(
ret
)
!=
0
)
{
return
log_error
(
-
1
,
"Script exited with status %d"
,
WEXITSTATUS
(
ret
));
ERROR
(
"Script exited with status %d"
,
WEXITSTATUS
(
ret
));
else
if
(
WIFSIGNALED
(
ret
))
return
-
1
;
return
log_error
(
-
1
,
"Script terminated by signal %d"
,
WTERMSIG
(
ret
));
}
else
if
(
WIFSIGNALED
(
ret
))
{
ERROR
(
"Script terminated by signal %d"
,
WTERMSIG
(
ret
));
return
-
1
;
}
return
0
;
return
0
;
}
}
...
@@ -348,8 +336,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
...
@@ -348,8 +336,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
size_t
size
=
0
;
size_t
size
=
0
;
if
(
hook_version
==
0
)
if
(
hook_version
==
0
)
INFO
(
"Executing script
\"
%s
\"
for container
\"
%s
\"
, config
"
INFO
(
"Executing script
\"
%s
\"
for container
\"
%s
\"
, config
section
\"
%s
\"
"
,
"section
\"
%s
\"
"
,
script
,
name
,
section
);
script
,
name
,
section
);
else
else
INFO
(
"Executing script
\"
%s
\"
for container
\"
%s
\"
"
,
script
,
name
);
INFO
(
"Executing script
\"
%s
\"
for container
\"
%s
\"
"
,
script
,
name
);
...
@@ -386,26 +374,19 @@ int run_script_argv(const char *name, unsigned int hook_version,
...
@@ -386,26 +374,19 @@ int run_script_argv(const char *name, unsigned int hook_version,
buf_pos
=
snprintf
(
buffer
,
size
,
"exec %s %s %s %s"
,
script
,
name
,
section
,
hookname
);
buf_pos
=
snprintf
(
buffer
,
size
,
"exec %s %s %s %s"
,
script
,
name
,
section
,
hookname
);
else
else
buf_pos
=
snprintf
(
buffer
,
size
,
"exec %s"
,
script
);
buf_pos
=
snprintf
(
buffer
,
size
,
"exec %s"
,
script
);
if
(
buf_pos
<
0
||
(
size_t
)
buf_pos
>=
size
)
{
if
(
buf_pos
<
0
||
(
size_t
)
buf_pos
>=
size
)
ERROR
(
"Failed to create command line for script
\"
%s
\"
"
,
script
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create command line for script
\"
%s
\"
"
,
script
);
return
-
1
;
}
if
(
hook_version
==
1
)
{
if
(
hook_version
==
1
)
{
ret
=
setenv
(
"LXC_HOOK_TYPE"
,
hookname
,
1
);
ret
=
setenv
(
"LXC_HOOK_TYPE"
,
hookname
,
1
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to set environment variable: "
return
log_error_errno
(
-
1
,
errno
,
"Failed to set environment variable: LXC_HOOK_TYPE=%s"
,
hookname
);
"LXC_HOOK_TYPE=%s"
,
hookname
);
return
-
1
;
}
}
TRACE
(
"Set environment variable: LXC_HOOK_TYPE=%s"
,
hookname
);
TRACE
(
"Set environment variable: LXC_HOOK_TYPE=%s"
,
hookname
);
ret
=
setenv
(
"LXC_HOOK_SECTION"
,
section
,
1
);
ret
=
setenv
(
"LXC_HOOK_SECTION"
,
section
,
1
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set environment variable: "
return
log_error_errno
(
-
1
,
errno
,
"Failed to set environment variable: LXC_HOOK_SECTION=%s"
,
section
);
"LXC_HOOK_SECTION=%s"
,
section
);
return
-
1
;
}
TRACE
(
"Set environment variable: LXC_HOOK_SECTION=%s"
,
section
);
TRACE
(
"Set environment variable: LXC_HOOK_SECTION=%s"
,
section
);
if
(
strcmp
(
section
,
"net"
)
==
0
)
{
if
(
strcmp
(
section
,
"net"
)
==
0
)
{
...
@@ -415,48 +396,33 @@ int run_script_argv(const char *name, unsigned int hook_version,
...
@@ -415,48 +396,33 @@ int run_script_argv(const char *name, unsigned int hook_version,
return
-
1
;
return
-
1
;
ret
=
setenv
(
"LXC_NET_TYPE"
,
argv
[
0
],
1
);
ret
=
setenv
(
"LXC_NET_TYPE"
,
argv
[
0
],
1
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set environment variable: "
return
log_error_errno
(
-
1
,
errno
,
"Failed to set environment variable: LXC_NET_TYPE=%s"
,
argv
[
0
]);
"LXC_NET_TYPE=%s"
,
argv
[
0
]);
return
-
1
;
}
TRACE
(
"Set environment variable: LXC_NET_TYPE=%s"
,
argv
[
0
]);
TRACE
(
"Set environment variable: LXC_NET_TYPE=%s"
,
argv
[
0
]);
parent
=
argv
[
1
]
?
argv
[
1
]
:
""
;
parent
=
argv
[
1
]
?
argv
[
1
]
:
""
;
if
(
strcmp
(
argv
[
0
],
"macvlan"
)
==
0
)
{
if
(
strcmp
(
argv
[
0
],
"macvlan"
)
==
0
)
{
ret
=
setenv
(
"LXC_NET_PARENT"
,
parent
,
1
);
ret
=
setenv
(
"LXC_NET_PARENT"
,
parent
,
1
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set environment "
return
log_error_errno
(
-
1
,
errno
,
"Failed to set environment variable: LXC_NET_PARENT=%s"
,
parent
);
"variable: LXC_NET_PARENT=%s"
,
parent
);
return
-
1
;
}
TRACE
(
"Set environment variable: LXC_NET_PARENT=%s"
,
parent
);
TRACE
(
"Set environment variable: LXC_NET_PARENT=%s"
,
parent
);
}
else
if
(
strcmp
(
argv
[
0
],
"phys"
)
==
0
)
{
}
else
if
(
strcmp
(
argv
[
0
],
"phys"
)
==
0
)
{
ret
=
setenv
(
"LXC_NET_PARENT"
,
parent
,
1
);
ret
=
setenv
(
"LXC_NET_PARENT"
,
parent
,
1
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set environment "
return
log_error_errno
(
-
1
,
errno
,
"Failed to set environment variable: LXC_NET_PARENT=%s"
,
parent
);
"variable: LXC_NET_PARENT=%s"
,
parent
);
return
-
1
;
}
TRACE
(
"Set environment variable: LXC_NET_PARENT=%s"
,
parent
);
TRACE
(
"Set environment variable: LXC_NET_PARENT=%s"
,
parent
);
}
else
if
(
strcmp
(
argv
[
0
],
"veth"
)
==
0
)
{
}
else
if
(
strcmp
(
argv
[
0
],
"veth"
)
==
0
)
{
char
*
peer
=
argv
[
2
]
?
argv
[
2
]
:
""
;
char
*
peer
=
argv
[
2
]
?
argv
[
2
]
:
""
;
ret
=
setenv
(
"LXC_NET_PEER"
,
peer
,
1
);
ret
=
setenv
(
"LXC_NET_PEER"
,
peer
,
1
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set environment "
return
log_error_errno
(
-
1
,
errno
,
"Failed to set environment variable: LXC_NET_PEER=%s"
,
peer
);
"variable: LXC_NET_PEER=%s"
,
peer
);
return
-
1
;
}
TRACE
(
"Set environment variable: LXC_NET_PEER=%s"
,
peer
);
TRACE
(
"Set environment variable: LXC_NET_PEER=%s"
,
peer
);
ret
=
setenv
(
"LXC_NET_PARENT"
,
parent
,
1
);
ret
=
setenv
(
"LXC_NET_PARENT"
,
parent
,
1
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set environment "
return
log_error_errno
(
-
1
,
errno
,
"Failed to set environment variable: LXC_NET_PARENT=%s"
,
parent
);
"variable: LXC_NET_PARENT=%s"
,
parent
);
return
-
1
;
}
TRACE
(
"Set environment variable: LXC_NET_PARENT=%s"
,
parent
);
TRACE
(
"Set environment variable: LXC_NET_PARENT=%s"
,
parent
);
}
}
}
}
...
@@ -466,10 +432,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
...
@@ -466,10 +432,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
size_t
len
=
size
-
buf_pos
;
size_t
len
=
size
-
buf_pos
;
ret
=
snprintf
(
buffer
+
buf_pos
,
len
,
" %s"
,
argv
[
i
]);
ret
=
snprintf
(
buffer
+
buf_pos
,
len
,
" %s"
,
argv
[
i
]);
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
ERROR
(
"Failed to create command line for script
\"
%s
\"
"
,
script
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create command line for script
\"
%s
\"
"
,
script
);
return
-
1
;
}
buf_pos
+=
ret
;
buf_pos
+=
ret
;
}
}
...
@@ -554,11 +518,11 @@ int pin_rootfs(const char *rootfs)
...
@@ -554,11 +518,11 @@ int pin_rootfs(const char *rootfs)
if
(
!
S_ISDIR
(
s
.
st_mode
))
if
(
!
S_ISDIR
(
s
.
st_mode
))
return
-
2
;
return
-
2
;
ret
=
snprintf
(
absrootfspin
,
PATH_MAX
,
"%s/.lxc-keep"
,
absrootfs
);
ret
=
snprintf
(
absrootfspin
,
sizeof
(
absrootfspin
)
,
"%s/.lxc-keep"
,
absrootfs
);
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
absrootfspin
)
)
return
-
1
;
return
-
1
;
fd
=
open
(
absrootfspin
,
O_CREAT
|
O_RDWR
,
S_IWUSR
|
S_IRUSR
);
fd
=
open
(
absrootfspin
,
O_CREAT
|
O_RDWR
,
S_IWUSR
|
S_IRUSR
|
O_CLOEXEC
);
if
(
fd
<
0
)
if
(
fd
<
0
)
return
fd
;
return
fd
;
...
@@ -566,10 +530,8 @@ int pin_rootfs(const char *rootfs)
...
@@ -566,10 +530,8 @@ int pin_rootfs(const char *rootfs)
if
(
ret
<
0
)
if
(
ret
<
0
)
return
fd
;
return
fd
;
if
(
sfs
.
f_type
==
NFS_SUPER_MAGIC
)
{
if
(
sfs
.
f_type
==
NFS_SUPER_MAGIC
)
DEBUG
(
"Rootfs on NFS, not unlinking pin file
\"
%s
\"
"
,
absrootfspin
);
return
log_debug
(
fd
,
"Rootfs on NFS, not unlinking pin file
\"
%s
\"
"
,
absrootfspin
);
return
fd
;
}
(
void
)
unlink
(
absrootfspin
);
(
void
)
unlink
(
absrootfspin
);
...
@@ -700,16 +662,13 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
...
@@ -700,16 +662,13 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
return
-
1
;
return
-
1
;
}
}
if
(
!
default_mounts
[
i
].
destination
)
{
if
(
!
default_mounts
[
i
].
destination
)
ERROR
(
"BUG: auto mounts destination %d was NULL"
,
i
);
return
log_error
(
-
1
,
"BUG: auto mounts destination %d was NULL"
,
i
);
return
-
1
;
}
/* will act like strdup if %r is not present */
/* will act like strdup if %r is not present */
destination
=
lxc_string_replace
(
"%r"
,
conf
->
rootfs
.
path
?
conf
->
rootfs
.
mount
:
""
,
default_mounts
[
i
].
destination
);
destination
=
lxc_string_replace
(
"%r"
,
conf
->
rootfs
.
path
?
conf
->
rootfs
.
mount
:
""
,
default_mounts
[
i
].
destination
);
if
(
!
destination
)
{
if
(
!
destination
)
return
-
1
;
return
-
1
;
}
mflags
=
add_required_remount_flags
(
source
,
destination
,
mflags
=
add_required_remount_flags
(
source
,
destination
,
default_mounts
[
i
].
flags
);
default_mounts
[
i
].
flags
);
...
@@ -718,8 +677,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
...
@@ -718,8 +677,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
conf
->
rootfs
.
path
?
conf
->
rootfs
.
mount
:
NULL
);
conf
->
rootfs
.
path
?
conf
->
rootfs
.
mount
:
NULL
);
saved_errno
=
errno
;
saved_errno
=
errno
;
if
(
r
<
0
&&
errno
==
ENOENT
)
{
if
(
r
<
0
&&
errno
==
ENOENT
)
{
INFO
(
"Mount source or target for
\"
%s
\"
on
\"
%s
\"
does "
INFO
(
"Mount source or target for
\"
%s
\"
on
\"
%s
\"
does not exist. Skipping"
,
source
,
destination
);
"not exist. Skipping"
,
source
,
destination
);
r
=
0
;
r
=
0
;
}
else
if
(
r
<
0
)
{
}
else
if
(
r
<
0
)
{
SYSERROR
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
with flags %lu"
,
source
,
destination
,
mflags
);
SYSERROR
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
with flags %lu"
,
source
,
destination
,
mflags
);
...
@@ -765,18 +723,14 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
...
@@ -765,18 +723,14 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
if
(
!
handler
->
cgroup_ops
->
mount
(
handler
->
cgroup_ops
,
if
(
!
handler
->
cgroup_ops
->
mount
(
handler
->
cgroup_ops
,
handler
,
handler
,
conf
->
rootfs
.
path
?
conf
->
rootfs
.
mount
:
""
,
conf
->
rootfs
.
path
?
conf
->
rootfs
.
mount
:
""
,
cg_flags
))
{
cg_flags
))
SYSERROR
(
"Failed to mount
\"
/sys/fs/cgroup
\"
"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to mount
\"
/sys/fs/cgroup
\"
"
);
return
-
1
;
}
}
}
if
(
flags
&
LXC_AUTO_SHMOUNTS_MASK
)
{
if
(
flags
&
LXC_AUTO_SHMOUNTS_MASK
)
{
int
ret
=
add_shmount_to_list
(
conf
);
int
ret
=
add_shmount_to_list
(
conf
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to add shmount entry to container config"
);
return
log_error
(
-
1
,
"Failed to add shmount entry to container config"
);
return
-
1
;
}
}
}
return
0
;
return
0
;
...
@@ -790,10 +744,9 @@ static int setup_utsname(struct utsname *utsname)
...
@@ -790,10 +744,9 @@ static int setup_utsname(struct utsname *utsname)
return
0
;
return
0
;
ret
=
sethostname
(
utsname
->
nodename
,
strlen
(
utsname
->
nodename
));
ret
=
sethostname
(
utsname
->
nodename
,
strlen
(
utsname
->
nodename
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set the hostname to
\"
%s
\"
"
,
utsname
->
nodename
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to set the hostname to
\"
%s
\"
"
,
return
-
1
;
utsname
->
nodename
);
}
INFO
(
"Set hostname to
\"
%s
\"
"
,
utsname
->
nodename
);
INFO
(
"Set hostname to
\"
%s
\"
"
,
utsname
->
nodename
);
...
@@ -823,7 +776,7 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
...
@@ -823,7 +776,7 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
ret
=
snprintf
(
path
,
sizeof
(
path
),
"%s/dev/%s"
,
ret
=
snprintf
(
path
,
sizeof
(
path
),
"%s/dev/%s"
,
rootfs
->
path
?
rootfs
->
mount
:
""
,
d
->
name
);
rootfs
->
path
?
rootfs
->
mount
:
""
,
d
->
name
);
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
path
)
)
return
-
1
;
return
-
1
;
/* Stat the path first. If we don't get an error accept it as
/* Stat the path first. If we don't get an error accept it as
...
@@ -835,12 +788,10 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
...
@@ -835,12 +788,10 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
ret
=
symlink
(
d
->
oldpath
,
path
);
ret
=
symlink
(
d
->
oldpath
,
path
);
if
(
ret
&&
errno
!=
EEXIST
)
{
if
(
ret
&&
errno
!=
EEXIST
)
{
if
(
errno
==
EROFS
)
{
if
(
errno
==
EROFS
)
WARN
(
"Failed to create
\"
%s
\"
. Read-only filesystem"
,
path
);
WARN
(
"Failed to create
\"
%s
\"
. Read-only filesystem"
,
path
);
}
else
{
else
SYSERROR
(
"Failed to create
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create
\"
%s
\"
"
,
path
);
return
-
1
;
}
}
}
}
}
...
@@ -912,12 +863,10 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
...
@@ -912,12 +863,10 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
ret
=
mount
(
tty
->
name
,
lxcpath
,
"none"
,
MS_BIND
,
0
);
ret
=
mount
(
tty
->
name
,
lxcpath
,
"none"
,
MS_BIND
,
0
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSWARN
(
"Failed to bind mount
\"
%s
\"
onto
\"
%s
\"
"
,
SYSWARN
(
"Failed to bind mount
\"
%s
\"
onto
\"
%s
\"
"
,
tty
->
name
,
lxcpath
);
tty
->
name
,
lxcpath
);
continue
;
continue
;
}
}
DEBUG
(
"Bind mounted
\"
%s
\"
onto
\"
%s
\"
"
,
tty
->
name
,
DEBUG
(
"Bind mounted
\"
%s
\"
onto
\"
%s
\"
"
,
tty
->
name
,
lxcpath
);
lxcpath
);
ret
=
snprintf
(
lxcpath
,
sizeof
(
lxcpath
),
"%s/tty%d"
,
ret
=
snprintf
(
lxcpath
,
sizeof
(
lxcpath
),
"%s/tty%d"
,
ttydir
,
i
+
1
);
ttydir
,
i
+
1
);
...
@@ -925,11 +874,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
...
@@ -925,11 +874,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
return
-
1
;
return
-
1
;
ret
=
symlink
(
lxcpath
,
path
);
ret
=
symlink
(
lxcpath
,
path
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to create symlink
\"
%s
\"
->
\"
%s
\"
"
,
return
log_error_errno
(
-
1
,
errno
,
"Failed to create symlink
\"
%s
\"
->
\"
%s
\"
"
,
path
,
lxcpath
);
path
,
lxcpath
);
return
-
1
;
}
}
else
{
}
else
{
/* If we populated /dev, then we need to create
/* If we populated /dev, then we need to create
* /dev/ttyN
* /dev/ttyN
...
@@ -947,10 +893,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
...
@@ -947,10 +893,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
DEBUG
(
"Bind mounted
\"
%s
\"
onto
\"
%s
\"
"
,
tty
->
name
,
path
);
DEBUG
(
"Bind mounted
\"
%s
\"
onto
\"
%s
\"
"
,
tty
->
name
,
path
);
}
}
if
(
!
append_ttyname
(
&
conf
->
ttys
.
tty_names
,
tty
->
name
))
{
if
(
!
append_ttyname
(
&
conf
->
ttys
.
tty_names
,
tty
->
name
))
ERROR
(
"Error setting up container_ttys string"
);
return
log_error
(
-
1
,
"Error setting up container_ttys string"
);
return
-
1
;
}
}
}
INFO
(
"Finished setting up %zu /dev/tty<N> device(s)"
,
ttys
->
max
);
INFO
(
"Finished setting up %zu /dev/tty<N> device(s)"
,
ttys
->
max
);
...
@@ -959,7 +903,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
...
@@ -959,7 +903,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
int
lxc_allocate_ttys
(
struct
lxc_conf
*
conf
)
int
lxc_allocate_ttys
(
struct
lxc_conf
*
conf
)
{
{
size_t
i
;
__do_free
struct
lxc_terminal_info
*
tty_new
=
NULL
;
int
ret
;
int
ret
;
struct
lxc_tty_info
*
ttys
=
&
conf
->
ttys
;
struct
lxc_tty_info
*
ttys
=
&
conf
->
ttys
;
...
@@ -967,29 +911,28 @@ int lxc_allocate_ttys(struct lxc_conf *conf)
...
@@ -967,29 +911,28 @@ int lxc_allocate_ttys(struct lxc_conf *conf)
if
(
ttys
->
max
==
0
)
if
(
ttys
->
max
==
0
)
return
0
;
return
0
;
tty
s
->
tty
=
malloc
(
sizeof
(
*
ttys
->
tty
)
*
ttys
->
max
);
tty
_new
=
malloc
(
sizeof
(
struct
lxc_terminal_info
)
*
ttys
->
max
);
if
(
!
tty
s
->
tty
)
if
(
!
tty
_new
)
return
-
ENOMEM
;
return
-
ENOMEM
;
ttys
->
tty
=
tty_new
;
for
(
i
=
0
;
i
<
ttys
->
max
;
i
++
)
{
for
(
size_t
i
=
0
;
i
<
ttys
->
max
;
i
++
)
{
struct
lxc_terminal_info
*
tty
=
&
ttys
->
tty
[
i
];
struct
lxc_terminal_info
*
tty
=
&
ttys
->
tty
[
i
];
tty
->
master
=
-
EBADF
;
tty
->
master
=
-
EBADF
;
tty
->
slave
=
-
EBADF
;
tty
->
slave
=
-
EBADF
;
ret
=
openpty
(
&
tty
->
master
,
&
tty
->
slave
,
NULL
,
NULL
,
NULL
);
ret
=
openpty
(
&
tty
->
master
,
&
tty
->
slave
,
NULL
,
NULL
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create tty %zu"
,
i
);
ttys
->
max
=
i
;
ttys
->
max
=
i
;
lxc_delete_tty
(
ttys
);
lxc_delete_tty
(
ttys
);
return
-
ENOTTY
;
return
log_error_errno
(
-
ENOTTY
,
ENOTTY
,
"Failed to create tty %zu"
,
i
)
;
}
}
ret
=
ttyname_r
(
tty
->
slave
,
tty
->
name
,
sizeof
(
tty
->
name
));
ret
=
ttyname_r
(
tty
->
slave
,
tty
->
name
,
sizeof
(
tty
->
name
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to retrieve name of tty %zu slave"
,
i
);
ttys
->
max
=
i
;
ttys
->
max
=
i
;
lxc_delete_tty
(
ttys
);
lxc_delete_tty
(
ttys
);
return
-
ENOTTY
;
return
log_error_errno
(
-
ENOTTY
,
ENOTTY
,
"Failed to retrieve name of tty %zu slave"
,
i
)
;
}
}
DEBUG
(
"Created tty
\"
%s
\"
with master fd %d and slave fd %d"
,
DEBUG
(
"Created tty
\"
%s
\"
with master fd %d and slave fd %d"
,
...
@@ -1010,32 +953,22 @@ int lxc_allocate_ttys(struct lxc_conf *conf)
...
@@ -1010,32 +953,22 @@ int lxc_allocate_ttys(struct lxc_conf *conf)
}
}
INFO
(
"Finished creating %zu tty devices"
,
ttys
->
max
);
INFO
(
"Finished creating %zu tty devices"
,
ttys
->
max
);
ttys
->
tty
=
move_ptr
(
tty_new
);
return
0
;
return
0
;
}
}
void
lxc_delete_tty
(
struct
lxc_tty_info
*
ttys
)
void
lxc_delete_tty
(
struct
lxc_tty_info
*
ttys
)
{
{
int
i
;
if
(
!
ttys
->
tty
)
if
(
!
ttys
->
tty
)
return
;
return
;
for
(
i
=
0
;
i
<
ttys
->
max
;
i
++
)
{
for
(
i
nt
i
=
0
;
i
<
ttys
->
max
;
i
++
)
{
struct
lxc_terminal_info
*
tty
=
&
ttys
->
tty
[
i
];
struct
lxc_terminal_info
*
tty
=
&
ttys
->
tty
[
i
];
close_prot_errno_disarm
(
tty
->
master
);
if
(
tty
->
master
>=
0
)
{
close_prot_errno_disarm
(
tty
->
slave
);
close
(
tty
->
master
);
tty
->
master
=
-
EBADF
;
}
if
(
tty
->
slave
>=
0
)
{
close
(
tty
->
slave
);
tty
->
slave
=
-
EBADF
;
}
}
}
free
(
ttys
->
tty
);
free_disarm
(
ttys
->
tty
);
ttys
->
tty
=
NULL
;
}
}
static
int
lxc_send_ttys_to_parent
(
struct
lxc_handler
*
handler
)
static
int
lxc_send_ttys_to_parent
(
struct
lxc_handler
*
handler
)
...
@@ -1060,8 +993,8 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
...
@@ -1060,8 +993,8 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
if
(
ret
<
0
)
if
(
ret
<
0
)
break
;
break
;
TRACE
(
"Sent tty
\"
%s
\"
with master fd %d and slave fd %d to
"
TRACE
(
"Sent tty
\"
%s
\"
with master fd %d and slave fd %d to
parent"
,
"parent"
,
tty
->
name
,
tty
->
master
,
tty
->
slave
);
tty
->
name
,
tty
->
master
,
tty
->
slave
);
}
}
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -1233,10 +1166,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
...
@@ -1233,10 +1166,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
if
(
ret
==
0
||
(
ret
<
0
&&
errno
==
EEXIST
))
{
if
(
ret
==
0
||
(
ret
<
0
&&
errno
==
EEXIST
))
{
DEBUG
(
"Created device node
\"
%s
\"
"
,
path
);
DEBUG
(
"Created device node
\"
%s
\"
"
,
path
);
}
else
if
(
ret
<
0
)
{
}
else
if
(
ret
<
0
)
{
if
(
errno
!=
EPERM
)
{
if
(
errno
!=
EPERM
)
SYSERROR
(
"Failed to create device node
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create device node
\"
%s
\"
"
,
path
);
return
-
1
;
}
use_mknod
=
LXC_DEVNODE_BIND
;
use_mknod
=
LXC_DEVNODE_BIND
;
}
}
...
@@ -1270,10 +1201,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
...
@@ -1270,10 +1201,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
* device node so we can use it as a bind-mount target.
* device node so we can use it as a bind-mount target.
*/
*/
ret
=
mknod
(
path
,
S_IFREG
|
0000
,
0
);
ret
=
mknod
(
path
,
S_IFREG
|
0000
,
0
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create file
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create file
\"
%s
\"
"
,
path
);
return
-
1
;
}
}
}
/* Fallback to bind-mounting the device from the host. */
/* Fallback to bind-mounting the device from the host. */
...
@@ -1283,13 +1212,10 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
...
@@ -1283,13 +1212,10 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
ret
=
safe_mount
(
hostpath
,
path
,
0
,
MS_BIND
,
NULL
,
ret
=
safe_mount
(
hostpath
,
path
,
0
,
MS_BIND
,
NULL
,
rootfs
->
path
?
rootfs
->
mount
:
NULL
);
rootfs
->
path
?
rootfs
->
mount
:
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to bind mount host device node
\"
%s
\"
"
return
log_error_errno
(
-
1
,
errno
,
"Failed to bind mount host device node
\"
%s
\"
onto
\"
%s
\"
"
,
"onto
\"
%s
\"
"
,
hostpath
,
path
);
hostpath
,
path
);
return
-
1
;
DEBUG
(
"Bind mounted host device node
\"
%s
\"
onto
\"
%s
\"
"
,
hostpath
,
path
);
}
DEBUG
(
"Bind mounted host device node
\"
%s
\"
onto
\"
%s
\"
"
,
hostpath
,
path
);
}
}
(
void
)
umask
(
cmask
);
(
void
)
umask
(
cmask
);
...
@@ -1305,37 +1231,29 @@ static int lxc_mount_rootfs(struct lxc_conf *conf)
...
@@ -1305,37 +1231,29 @@ static int lxc_mount_rootfs(struct lxc_conf *conf)
if
(
!
rootfs
->
path
)
{
if
(
!
rootfs
->
path
)
{
ret
=
mount
(
""
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
0
);
ret
=
mount
(
""
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
0
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to remount
\"
/
\"
MS_REC | MS_SLAVE"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to remount
\"
/
\"
MS_REC | MS_SLAVE"
);
return
-
1
;
}
return
0
;
return
0
;
}
}
ret
=
access
(
rootfs
->
mount
,
F_OK
);
ret
=
access
(
rootfs
->
mount
,
F_OK
);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
SYSERROR
(
"Failed to access to
\"
%s
\"
. Check it is present"
,
return
log_error_errno
(
-
1
,
errno
,
"Failed to access to
\"
%s
\"
. Check it is present"
,
rootfs
->
mount
);
rootfs
->
mount
);
return
-
1
;
}
bdev
=
storage_init
(
conf
);
bdev
=
storage_init
(
conf
);
if
(
!
bdev
)
{
if
(
!
bdev
)
ERROR
(
"Failed to mount rootfs
\"
%s
\"
onto
\"
%s
\"
with options
\"
%s
\"
"
,
return
log_error
(
-
1
,
"Failed to mount rootfs
\"
%s
\"
onto
\"
%s
\"
with options
\"
%s
\"
"
,
rootfs
->
path
,
rootfs
->
mount
,
rootfs
->
path
,
rootfs
->
mount
,
rootfs
->
options
?
rootfs
->
options
:
"(null)"
);
rootfs
->
options
?
rootfs
->
options
:
"(null)"
);
return
-
1
;
}
ret
=
bdev
->
ops
->
mount
(
bdev
);
ret
=
bdev
->
ops
->
mount
(
bdev
);
storage_put
(
bdev
);
storage_put
(
bdev
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to mount rootfs
\"
%s
\"
onto
\"
%s
\"
with options
\"
%s
\"
"
,
return
log_error
(
-
1
,
"Failed to mount rootfs
\"
%s
\"
onto
\"
%s
\"
with options
\"
%s
\"
"
,
rootfs
->
path
,
rootfs
->
mount
,
rootfs
->
path
,
rootfs
->
mount
,
rootfs
->
options
?
rootfs
->
options
:
"(null)"
);
rootfs
->
options
?
rootfs
->
options
:
"(null)"
);
return
-
1
;
}
DEBUG
(
"Mounted rootfs
\"
%s
\"
onto
\"
%s
\"
with options
\"
%s
\"
"
,
DEBUG
(
"Mounted rootfs
\"
%s
\"
onto
\"
%s
\"
with options
\"
%s
\"
"
,
rootfs
->
path
,
rootfs
->
mount
,
rootfs
->
path
,
rootfs
->
mount
,
...
@@ -1351,10 +1269,8 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
...
@@ -1351,10 +1269,8 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
char
*
root
=
rootfs
->
mount
;
char
*
root
=
rootfs
->
mount
;
nroot
=
realpath
(
root
,
NULL
);
nroot
=
realpath
(
root
,
NULL
);
if
(
!
nroot
)
{
if
(
!
nroot
)
SYSERROR
(
"Failed to resolve
\"
%s
\"
"
,
root
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to resolve
\"
%s
\"
"
,
root
);
return
-
1
;
}
ret
=
chdir
(
"/"
);
ret
=
chdir
(
"/"
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -1364,16 +1280,12 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
...
@@ -1364,16 +1280,12 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
* can't be moved.
* can't be moved.
*/
*/
ret
=
mount
(
nroot
,
"/"
,
NULL
,
MS_REC
|
MS_BIND
,
NULL
);
ret
=
mount
(
nroot
,
"/"
,
NULL
,
MS_REC
|
MS_BIND
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to mount
\"
%s
\"
onto
\"
/
\"
as MS_REC | MS_BIND"
,
nroot
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to mount
\"
%s
\"
onto
\"
/
\"
as MS_REC | MS_BIND"
,
nroot
);
return
-
1
;
}
ret
=
mount
(
NULL
,
"/"
,
NULL
,
MS_REC
|
MS_PRIVATE
,
NULL
);
ret
=
mount
(
NULL
,
"/"
,
NULL
,
MS_REC
|
MS_PRIVATE
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to remount
\"
/
\"
"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to remount
\"
/
\"
"
);
return
-
1
;
}
/* The following code cleans up inherited mounts which are not required
/* The following code cleans up inherited mounts which are not required
* for CT.
* for CT.
...
@@ -1393,10 +1305,8 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
...
@@ -1393,10 +1305,8 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
size_t
len
=
0
;
size_t
len
=
0
;
f
=
fopen
(
"./proc/self/mountinfo"
,
"re"
);
f
=
fopen
(
"./proc/self/mountinfo"
,
"re"
);
if
(
!
f
)
{
if
(
!
f
)
SYSERROR
(
"Failed to open
\"
/proc/self/mountinfo
\"
"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to open
\"
/proc/self/mountinfo
\"
"
);
return
-
1
;
}
while
(
getline
(
&
line
,
&
len
,
f
)
>
0
)
{
while
(
getline
(
&
line
,
&
len
,
f
)
>
0
)
{
for
(
slider1
=
line
,
i
=
0
;
slider1
&&
i
<
4
;
i
++
)
for
(
slider1
=
line
,
i
=
0
;
slider1
&&
i
<
4
;
i
++
)
...
@@ -1432,16 +1342,12 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
...
@@ -1432,16 +1342,12 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
/* It is weird, but chdir("..") moves us in a new root */
/* It is weird, but chdir("..") moves us in a new root */
ret
=
chdir
(
".."
);
ret
=
chdir
(
".."
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to chdir(
\"
..
\"
)"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to chdir(
\"
..
\"
)"
);
return
-
1
;
}
ret
=
chroot
(
"."
);
ret
=
chroot
(
"."
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to chroot(
\"
.
\"
)"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to chroot(
\"
.
\"
)"
);
return
-
1
;
}
return
0
;
return
0
;
}
}
...
@@ -1478,61 +1384,45 @@ static int lxc_pivot_root(const char *rootfs)
...
@@ -1478,61 +1384,45 @@ static int lxc_pivot_root(const char *rootfs)
int
ret
;
int
ret
;
oldroot
=
open
(
"/"
,
O_DIRECTORY
|
O_RDONLY
|
O_CLOEXEC
);
oldroot
=
open
(
"/"
,
O_DIRECTORY
|
O_RDONLY
|
O_CLOEXEC
);
if
(
oldroot
<
0
)
{
if
(
oldroot
<
0
)
SYSERROR
(
"Failed to open old root directory"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to open old root directory"
);
return
-
1
;
}
newroot
=
open
(
rootfs
,
O_DIRECTORY
|
O_RDONLY
|
O_CLOEXEC
);
newroot
=
open
(
rootfs
,
O_DIRECTORY
|
O_RDONLY
|
O_CLOEXEC
);
if
(
newroot
<
0
)
{
if
(
newroot
<
0
)
SYSERROR
(
"Failed to open new root directory"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to open new root directory"
);
return
-
1
;
}
/* change into new root fs */
/* change into new root fs */
ret
=
fchdir
(
newroot
);
ret
=
fchdir
(
newroot
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to change to new rootfs
\"
%s
\"
"
,
rootfs
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to change to new rootfs
\"
%s
\"
"
,
rootfs
);
return
-
1
;
}
/* pivot_root into our new root fs */
/* pivot_root into our new root fs */
ret
=
pivot_root
(
"."
,
"."
);
ret
=
pivot_root
(
"."
,
"."
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to pivot_root()"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to pivot_root()"
);
return
-
1
;
}
/* At this point the old-root is mounted on top of our new-root. To
/* At this point the old-root is mounted on top of our new-root. To
* unmounted it we must not be chdir'd into it, so escape back to
* unmounted it we must not be chdir'd into it, so escape back to
* old-root.
* old-root.
*/
*/
ret
=
fchdir
(
oldroot
);
ret
=
fchdir
(
oldroot
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to enter old root directory"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to enter old root directory"
);
return
-
1
;
}
/* Make oldroot rslave to make sure our umounts don't propagate to the
/* Make oldroot rslave to make sure our umounts don't propagate to the
* host.
* host.
*/
*/
ret
=
mount
(
""
,
"."
,
""
,
MS_SLAVE
|
MS_REC
,
NULL
);
ret
=
mount
(
""
,
"."
,
""
,
MS_SLAVE
|
MS_REC
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to make oldroot rslave"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to make oldroot rslave"
);
return
-
1
;
}
ret
=
umount2
(
"."
,
MNT_DETACH
);
ret
=
umount2
(
"."
,
MNT_DETACH
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to detach old root directory"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to detach old root directory"
);
return
-
1
;
}
ret
=
fchdir
(
newroot
);
ret
=
fchdir
(
newroot
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to re-enter new root directory"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to re-enter new root directory"
);
return
-
1
;
}
TRACE
(
"pivot_root(
\"
%s
\"
) successful"
,
rootfs
);
TRACE
(
"pivot_root(
\"
%s
\"
) successful"
,
rootfs
);
...
@@ -1541,10 +1431,8 @@ static int lxc_pivot_root(const char *rootfs)
...
@@ -1541,10 +1431,8 @@ static int lxc_pivot_root(const char *rootfs)
static
int
lxc_setup_rootfs_switch_root
(
const
struct
lxc_rootfs
*
rootfs
)
static
int
lxc_setup_rootfs_switch_root
(
const
struct
lxc_rootfs
*
rootfs
)
{
{
if
(
!
rootfs
->
path
)
{
if
(
!
rootfs
->
path
)
DEBUG
(
"Container does not have a rootfs"
);
return
log_debug
(
0
,
"Container does not have a rootfs"
);
return
0
;
}
if
(
detect_ramfs_rootfs
())
if
(
detect_ramfs_rootfs
())
return
lxc_chroot
(
rootfs
);
return
lxc_chroot
(
rootfs
);
...
@@ -1591,11 +1479,8 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
...
@@ -1591,11 +1479,8 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
char
*
mntopt_sets
[
5
];
char
*
mntopt_sets
[
5
];
char
default_devpts_mntopts
[
256
]
=
"gid=5,newinstance,ptmxmode=0666,mode=0620"
;
char
default_devpts_mntopts
[
256
]
=
"gid=5,newinstance,ptmxmode=0666,mode=0620"
;
if
(
conf
->
pty_max
<=
0
)
{
if
(
conf
->
pty_max
<=
0
)
DEBUG
(
"No new devpts instance will be mounted since no pts "
return
log_debug
(
0
,
"No new devpts instance will be mounted since no pts devices are requested"
);
"devices are requested"
);
return
0
;
}
ret
=
snprintf
(
devpts_mntopts
,
sizeof
(
devpts_mntopts
),
"%s,max=%zu"
,
ret
=
snprintf
(
devpts_mntopts
,
sizeof
(
devpts_mntopts
),
"%s,max=%zu"
,
default_devpts_mntopts
,
conf
->
pty_max
);
default_devpts_mntopts
,
conf
->
pty_max
);
...
@@ -1606,10 +1491,8 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
...
@@ -1606,10 +1491,8 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
/* Create mountpoint for devpts instance. */
/* Create mountpoint for devpts instance. */
ret
=
mkdir
(
"/dev/pts"
,
0755
);
ret
=
mkdir
(
"/dev/pts"
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create
\"
/dev/pts
\"
directory"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create
\"
/dev/pts
\"
directory"
);
return
-
1
;
}
/* gid=5 && max= */
/* gid=5 && max= */
mntopt_sets
[
0
]
=
devpts_mntopts
;
mntopt_sets
[
0
]
=
devpts_mntopts
;
...
@@ -1633,54 +1516,42 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
...
@@ -1633,54 +1516,42 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
break
;
break
;
}
}
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to mount new devpts instance"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to mount new devpts instance"
);
return
-
1
;
}
DEBUG
(
"Mount new devpts instance with options
\"
%s
\"
"
,
*
opts
);
DEBUG
(
"Mount new devpts instance with options
\"
%s
\"
"
,
*
opts
);
/* Remove any pre-existing /dev/ptmx file. */
/* Remove any pre-existing /dev/ptmx file. */
ret
=
remove
(
"/dev/ptmx"
);
ret
=
remove
(
"/dev/ptmx"
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
if
(
errno
!=
ENOENT
)
{
if
(
errno
!=
ENOENT
)
SYSERROR
(
"Failed to remove existing
\"
/dev/ptmx
\"
file"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to remove existing
\"
/dev/ptmx
\"
file"
);
return
-
1
;
}
}
else
{
}
else
{
DEBUG
(
"Removed existing
\"
/dev/ptmx
\"
file"
);
DEBUG
(
"Removed existing
\"
/dev/ptmx
\"
file"
);
}
}
/* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */
/* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */
ret
=
mknod
(
"/dev/ptmx"
,
S_IFREG
|
0000
,
0
);
ret
=
mknod
(
"/dev/ptmx"
,
S_IFREG
|
0000
,
0
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create dummy
\"
/dev/ptmx
\"
file as bind mount target"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create dummy
\"
/dev/ptmx
\"
file as bind mount target"
);
return
-
1
;
}
DEBUG
(
"Created dummy
\"
/dev/ptmx
\"
file as bind mount target"
);
DEBUG
(
"Created dummy
\"
/dev/ptmx
\"
file as bind mount target"
);
/* Fallback option: create symlink /dev/ptmx -> /dev/pts/ptmx */
/* Fallback option: create symlink /dev/ptmx -> /dev/pts/ptmx */
ret
=
mount
(
"/dev/pts/ptmx"
,
"/dev/ptmx"
,
NULL
,
MS_BIND
,
NULL
);
ret
=
mount
(
"/dev/pts/ptmx"
,
"/dev/ptmx"
,
NULL
,
MS_BIND
,
NULL
);
if
(
!
ret
)
{
if
(
!
ret
)
DEBUG
(
"Bind mounted
\"
/dev/pts/ptmx
\"
to
\"
/dev/ptmx
\"
"
);
return
log_debug
(
0
,
"Bind mounted
\"
/dev/pts/ptmx
\"
to
\"
/dev/ptmx
\"
"
);
return
0
;
else
}
else
{
/* Fallthrough and try to create a symlink. */
/* Fallthrough and try to create a symlink. */
ERROR
(
"Failed to bind mount
\"
/dev/pts/ptmx
\"
to
\"
/dev/ptmx
\"
"
);
ERROR
(
"Failed to bind mount
\"
/dev/pts/ptmx
\"
to
\"
/dev/ptmx
\"
"
);
}
/* Remove the dummy /dev/ptmx file we created above. */
/* Remove the dummy /dev/ptmx file we created above. */
ret
=
remove
(
"/dev/ptmx"
);
ret
=
remove
(
"/dev/ptmx"
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to remove existing
\"
/dev/ptmx
\"
"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to remove existing
\"
/dev/ptmx
\"
"
);
return
-
1
;
}
/* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */
/* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */
ret
=
symlink
(
"/dev/pts/ptmx"
,
"/dev/ptmx"
);
ret
=
symlink
(
"/dev/pts/ptmx"
,
"/dev/ptmx"
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to create symlink from
\"
/dev/ptmx
\"
to
\"
/dev/pts/ptmx
\"
"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create symlink from
\"
/dev/ptmx
\"
to
\"
/dev/pts/ptmx
\"
"
);
return
-
1
;
}
DEBUG
(
"Created symlink from
\"
/dev/ptmx
\"
to
\"
/dev/pts/ptmx
\"
"
);
DEBUG
(
"Created symlink from
\"
/dev/ptmx
\"
to
\"
/dev/pts/ptmx
\"
"
);
return
0
;
return
0
;
...
@@ -1695,10 +1566,8 @@ static int setup_personality(int persona)
...
@@ -1695,10 +1566,8 @@ static int setup_personality(int persona)
return
0
;
return
0
;
ret
=
personality
(
persona
);
ret
=
personality
(
persona
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set personality to
\"
0x%x
\"
"
,
persona
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to set personality to
\"
0x%x
\"
"
,
persona
);
return
-
1
;
}
INFO
(
"Set personality to
\"
0x%x
\"
"
,
persona
);
INFO
(
"Set personality to
\"
0x%x
\"
"
,
persona
);
#endif
#endif
...
@@ -1725,35 +1594,26 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
...
@@ -1725,35 +1594,26 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
*/
*/
if
(
file_exists
(
path
))
{
if
(
file_exists
(
path
))
{
ret
=
lxc_unstack_mountpoint
(
path
,
false
);
ret
=
lxc_unstack_mountpoint
(
path
,
false
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to unmount
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
ret
,
errno
,
"Failed to unmount
\"
%s
\"
"
,
path
);
return
-
ret
;
else
}
else
{
DEBUG
(
"Cleared all (%d) mounts from
\"
%s
\"
"
,
ret
,
path
);
DEBUG
(
"Cleared all (%d) mounts from
\"
%s
\"
"
,
ret
,
path
);
}
}
}
/* For unprivileged containers autodev or automounts will already have
/* For unprivileged containers autodev or automounts will already have
* taken care of creating /dev/console.
* taken care of creating /dev/console.
*/
*/
ret
=
mknod
(
path
,
S_IFREG
|
0000
,
0
);
ret
=
mknod
(
path
,
S_IFREG
|
0000
,
0
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create console"
);
return
log_error_errno
(
-
errno
,
errno
,
"Failed to create console"
);
return
-
errno
;
}
ret
=
fchmod
(
console
->
slave
,
S_IXUSR
|
S_IXGRP
);
ret
=
fchmod
(
console
->
slave
,
S_IXUSR
|
S_IXGRP
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set mode
\"
0%o
\"
to
\"
%s
\"
"
,
return
log_error_errno
(
-
errno
,
errno
,
"Failed to set mode
\"
0%o
\"
to
\"
%s
\"
"
,
S_IXUSR
|
S_IXGRP
,
console
->
name
);
S_IXUSR
|
S_IXGRP
,
console
->
name
);
return
-
errno
;
}
ret
=
safe_mount
(
console
->
name
,
path
,
"none"
,
MS_BIND
,
0
,
rootfs_path
);
ret
=
safe_mount
(
console
->
name
,
path
,
"none"
,
MS_BIND
,
0
,
rootfs_path
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
console
->
name
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
console
->
name
,
path
);
return
-
1
;
}
DEBUG
(
"Mounted pts device
\"
%s
\"
onto
\"
%s
\"
"
,
console
->
name
,
path
);
DEBUG
(
"Mounted pts device
\"
%s
\"
onto
\"
%s
\"
"
,
console
->
name
,
path
);
return
0
;
return
0
;
...
@@ -1776,10 +1636,8 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
...
@@ -1776,10 +1636,8 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
return
-
1
;
return
-
1
;
ret
=
mkdir
(
path
,
0755
);
ret
=
mkdir
(
path
,
0755
);
if
(
ret
&&
errno
!=
EEXIST
)
{
if
(
ret
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
errno
,
errno
,
"Failed to create
\"
%s
\"
"
,
path
);
return
-
errno
;
}
DEBUG
(
"Created directory for console and tty devices at
\"
%s
\"
"
,
path
);
DEBUG
(
"Created directory for console and tty devices at
\"
%s
\"
"
,
path
);
ret
=
snprintf
(
lxcpath
,
sizeof
(
lxcpath
),
"%s/dev/%s/console"
,
rootfs_path
,
ttydir
);
ret
=
snprintf
(
lxcpath
,
sizeof
(
lxcpath
),
"%s/dev/%s/console"
,
rootfs_path
,
ttydir
);
...
@@ -1787,10 +1645,8 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
...
@@ -1787,10 +1645,8 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
return
-
1
;
return
-
1
;
ret
=
mknod
(
lxcpath
,
S_IFREG
|
0000
,
0
);
ret
=
mknod
(
lxcpath
,
S_IFREG
|
0000
,
0
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create
\"
%s
\"
"
,
lxcpath
);
return
log_error_errno
(
-
errno
,
errno
,
"Failed to create
\"
%s
\"
"
,
lxcpath
);
return
-
errno
;
}
ret
=
snprintf
(
path
,
sizeof
(
path
),
"%s/dev/console"
,
rootfs_path
);
ret
=
snprintf
(
path
,
sizeof
(
path
),
"%s/dev/console"
,
rootfs_path
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
path
))
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
path
))
...
@@ -1798,41 +1654,30 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
...
@@ -1798,41 +1654,30 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
if
(
file_exists
(
path
))
{
if
(
file_exists
(
path
))
{
ret
=
lxc_unstack_mountpoint
(
path
,
false
);
ret
=
lxc_unstack_mountpoint
(
path
,
false
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to unmount
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
ret
,
errno
,
"Failed to unmount
\"
%s
\"
"
,
path
);
return
-
ret
;
else
}
else
{
DEBUG
(
"Cleared all (%d) mounts from
\"
%s
\"
"
,
ret
,
path
);
DEBUG
(
"Cleared all (%d) mounts from
\"
%s
\"
"
,
ret
,
path
);
}
}
}
ret
=
mknod
(
path
,
S_IFREG
|
0000
,
0
);
ret
=
mknod
(
path
,
S_IFREG
|
0000
,
0
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create console"
);
return
log_error_errno
(
-
errno
,
errno
,
"Failed to create console"
);
return
-
errno
;
}
ret
=
fchmod
(
console
->
slave
,
S_IXUSR
|
S_IXGRP
);
ret
=
fchmod
(
console
->
slave
,
S_IXUSR
|
S_IXGRP
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to set mode
\"
0%o
\"
to
\"
%s
\"
"
,
return
log_error_errno
(
-
errno
,
errno
,
"Failed to set mode
\"
0%o
\"
to
\"
%s
\"
"
,
S_IXUSR
|
S_IXGRP
,
console
->
name
);
S_IXUSR
|
S_IXGRP
,
console
->
name
);
return
-
errno
;
}
/* bind mount console->name to '/dev/<ttydir>/console' */
/* bind mount console->name to '/dev/<ttydir>/console' */
ret
=
safe_mount
(
console
->
name
,
lxcpath
,
"none"
,
MS_BIND
,
0
,
rootfs_path
);
ret
=
safe_mount
(
console
->
name
,
lxcpath
,
"none"
,
MS_BIND
,
0
,
rootfs_path
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
console
->
name
,
lxcpath
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
console
->
name
,
lxcpath
);
return
-
1
;
}
DEBUG
(
"Mounted
\"
%s
\"
onto
\"
%s
\"
"
,
console
->
name
,
lxcpath
);
DEBUG
(
"Mounted
\"
%s
\"
onto
\"
%s
\"
"
,
console
->
name
,
lxcpath
);
/* bind mount '/dev/<ttydir>/console' to '/dev/console' */
/* bind mount '/dev/<ttydir>/console' to '/dev/console' */
ret
=
safe_mount
(
lxcpath
,
path
,
"none"
,
MS_BIND
,
0
,
rootfs_path
);
ret
=
safe_mount
(
lxcpath
,
path
,
"none"
,
MS_BIND
,
0
,
rootfs_path
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
console
->
name
,
lxcpath
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
console
->
name
,
lxcpath
);
return
-
1
;
}
DEBUG
(
"Mounted
\"
%s
\"
onto
\"
%s
\"
"
,
console
->
name
,
lxcpath
);
DEBUG
(
"Mounted
\"
%s
\"
onto
\"
%s
\"
"
,
console
->
name
,
lxcpath
);
DEBUG
(
"Console has been setup under
\"
%s
\"
and mounted to
\"
%s
\"
"
,
lxcpath
,
path
);
DEBUG
(
"Console has been setup under
\"
%s
\"
and mounted to
\"
%s
\"
"
,
lxcpath
,
path
);
...
@@ -1935,10 +1780,8 @@ int parse_propagationopts(const char *mntopts, unsigned long *pflags)
...
@@ -1935,10 +1780,8 @@ int parse_propagationopts(const char *mntopts, unsigned long *pflags)
return
0
;
return
0
;
s
=
strdup
(
mntopts
);
s
=
strdup
(
mntopts
);
if
(
!
s
)
{
if
(
!
s
)
SYSERROR
(
"Failed to allocate memory"
);
return
log_error_errno
(
-
ENOMEM
,
errno
,
"Failed to allocate memory"
);
return
-
ENOMEM
;
}
*
pflags
=
0L
;
*
pflags
=
0L
;
lxc_iterate_parts
(
p
,
s
,
","
)
lxc_iterate_parts
(
p
,
s
,
","
)
...
@@ -1986,33 +1829,28 @@ static int mount_entry(const char *fsname, const char *target,
...
@@ -1986,33 +1829,28 @@ static int mount_entry(const char *fsname, const char *target,
#endif
#endif
if
(
relative
)
{
if
(
relative
)
{
ret
=
snprintf
(
srcbuf
,
PATH_MAX
,
"%s/%s"
,
rootfs
?
rootfs
:
"/"
,
fsname
?
fsname
:
""
);
ret
=
snprintf
(
srcbuf
,
sizeof
(
srcbuf
),
"%s/%s"
,
rootfs
?
rootfs
:
"/"
,
fsname
?
fsname
:
""
);
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
{
if
(
ret
<
0
||
ret
>=
sizeof
(
srcbuf
))
ERROR
(
"source path is too long"
);
return
log_error_errno
(
-
1
,
errno
,
"source path is too long"
);
return
-
1
;
}
srcpath
=
srcbuf
;
srcpath
=
srcbuf
;
}
}
ret
=
safe_mount
(
srcpath
,
target
,
fstype
,
mountflags
&
~
MS_REMOUNT
,
data
,
ret
=
safe_mount
(
srcpath
,
target
,
fstype
,
mountflags
&
~
MS_REMOUNT
,
data
,
rootfs
);
rootfs
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
if
(
optional
)
{
if
(
optional
)
SYSINFO
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
(optional)"
,
return
log_info_errno
(
0
,
errno
,
"Failed to mount
\"
%s
\"
on
\"
%s
\"
(optional)"
,
srcpath
?
srcpath
:
"(null)"
,
target
);
srcpath
?
srcpath
:
"(null)"
,
target
);
return
0
;
}
SYSERROR
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
return
log_error_errno
(
-
1
,
errno
,
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
srcpath
?
srcpath
:
"(null)"
,
target
);
srcpath
?
srcpath
:
"(null)"
,
target
);
return
-
1
;
}
}
if
((
mountflags
&
MS_REMOUNT
)
||
(
mountflags
&
MS_BIND
))
{
if
((
mountflags
&
MS_REMOUNT
)
||
(
mountflags
&
MS_BIND
))
{
unsigned
long
rqd_flags
=
0
;
unsigned
long
rqd_flags
=
0
;
DEBUG
(
"Remounting
\"
%s
\"
on
\"
%s
\"
to respect bind or remount
"
DEBUG
(
"Remounting
\"
%s
\"
on
\"
%s
\"
to respect bind or remount
options"
,
"options"
,
srcpath
?
srcpath
:
"(none)"
,
target
?
target
:
"(none)"
);
srcpath
?
srcpath
:
"(none)"
,
target
?
target
:
"(none)"
);
if
(
mountflags
&
MS_RDONLY
)
if
(
mountflags
&
MS_RDONLY
)
rqd_flags
|=
MS_RDONLY
;
rqd_flags
|=
MS_RDONLY
;
...
@@ -2032,8 +1870,8 @@ static int mount_entry(const char *fsname, const char *target,
...
@@ -2032,8 +1870,8 @@ static int mount_entry(const char *fsname, const char *target,
if
(
sb
.
f_flag
&
MS_NOEXEC
)
if
(
sb
.
f_flag
&
MS_NOEXEC
)
required_flags
|=
MS_NOEXEC
;
required_flags
|=
MS_NOEXEC
;
DEBUG
(
"Flags for
\"
%s
\"
were %lu, required extra flags
"
DEBUG
(
"Flags for
\"
%s
\"
were %lu, required extra flags
are %lu"
,
"are %lu"
,
srcpath
,
sb
.
f_flag
,
required_flags
);
srcpath
,
sb
.
f_flag
,
required_flags
);
/* If this was a bind mount request, and required_flags
/* If this was a bind mount request, and required_flags
* does not have any flags which are not already in
* does not have any flags which are not already in
...
@@ -2042,8 +1880,7 @@ static int mount_entry(const char *fsname, const char *target,
...
@@ -2042,8 +1880,7 @@ static int mount_entry(const char *fsname, const char *target,
if
(
!
(
mountflags
&
MS_REMOUNT
))
{
if
(
!
(
mountflags
&
MS_REMOUNT
))
{
if
(
!
(
required_flags
&
~
mountflags
)
&&
if
(
!
(
required_flags
&
~
mountflags
)
&&
rqd_flags
==
0
)
{
rqd_flags
==
0
)
{
DEBUG
(
"Mountflags already were %lu, "
DEBUG
(
"Mountflags already were %lu, skipping remount"
,
mountflags
);
"skipping remount"
,
mountflags
);
goto
skipremount
;
goto
skipremount
;
}
}
}
}
...
@@ -2054,15 +1891,14 @@ static int mount_entry(const char *fsname, const char *target,
...
@@ -2054,15 +1891,14 @@ static int mount_entry(const char *fsname, const char *target,
ret
=
mount
(
srcpath
,
target
,
fstype
,
mountflags
|
MS_REMOUNT
,
data
);
ret
=
mount
(
srcpath
,
target
,
fstype
,
mountflags
|
MS_REMOUNT
,
data
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
if
(
optional
)
{
if
(
optional
)
SYSINFO
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
(optional)"
,
return
log_info_errno
(
0
,
errno
,
"Failed to mount
\"
%s
\"
on
\"
%s
\"
(optional)"
,
srcpath
?
srcpath
:
"(null)"
,
target
);
srcpath
?
srcpath
:
"(null)"
,
return
0
;
target
);
}
return
log_error_errno
(
-
1
,
errno
,
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
SYSERROR
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
srcpath
?
srcpath
:
"(null)"
,
srcpath
?
srcpath
:
"(null)"
,
target
);
target
);
return
-
1
;
}
}
}
}
...
@@ -2072,15 +1908,10 @@ skipremount:
...
@@ -2072,15 +1908,10 @@ skipremount:
if
(
pflags
)
{
if
(
pflags
)
{
ret
=
mount
(
NULL
,
target
,
NULL
,
pflags
,
NULL
);
ret
=
mount
(
NULL
,
target
,
NULL
,
pflags
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
if
(
optional
)
{
if
(
optional
)
SYSINFO
(
"Failed to change mount propagation "
return
log_info_errno
(
0
,
errno
,
"Failed to change mount propagation for
\"
%s
\"
(optional)"
,
target
);
"for
\"
%s
\"
(optional)"
,
target
);
else
return
0
;
return
log_error_errno
(
-
1
,
errno
,
"Failed to change mount propagation for
\"
%s
\"
(optional)"
,
target
);
}
else
{
SYSERROR
(
"Failed to change mount propagation "
"for
\"
%s
\"
(optional)"
,
target
);
return
-
1
;
}
}
}
DEBUG
(
"Changed mount propagation for
\"
%s
\"
"
,
target
);
DEBUG
(
"Changed mount propagation for
\"
%s
\"
"
,
target
);
}
}
...
@@ -2138,10 +1969,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
...
@@ -2138,10 +1969,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
if
(
hasmntopt
(
mntent
,
"create=dir"
))
{
if
(
hasmntopt
(
mntent
,
"create=dir"
))
{
ret
=
mkdir_p
(
path
,
0755
);
ret
=
mkdir_p
(
path
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create directory
\"
%s
\"
"
,
path
);
return
-
1
;
}
}
}
if
(
!
hasmntopt
(
mntent
,
"create=file"
))
if
(
!
hasmntopt
(
mntent
,
"create=file"
))
...
@@ -2158,10 +1987,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
...
@@ -2158,10 +1987,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
p2
=
dirname
(
p1
);
p2
=
dirname
(
p1
);
ret
=
mkdir_p
(
p2
,
0755
);
ret
=
mkdir_p
(
p2
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create directory
\"
%s
\"
"
,
path
);
return
-
1
;
}
ret
=
mknod
(
path
,
S_IFREG
|
0000
,
0
);
ret
=
mknod
(
path
,
S_IFREG
|
0000
,
0
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
if
(
ret
<
0
&&
errno
!=
EEXIST
)
...
@@ -2264,10 +2091,8 @@ static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
...
@@ -2264,10 +2091,8 @@ static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
skipvarlib:
skipvarlib:
aux
=
strstr
(
mntent
->
mnt_dir
,
rootfs
->
path
);
aux
=
strstr
(
mntent
->
mnt_dir
,
rootfs
->
path
);
if
(
!
aux
)
{
if
(
!
aux
)
WARN
(
"Ignoring mount point
\"
%s
\"
"
,
mntent
->
mnt_dir
);
return
log_warn
(
ret
,
"Ignoring mount point
\"
%s
\"
"
,
mntent
->
mnt_dir
);
return
ret
;
}
offset
=
strlen
(
rootfs
->
path
);
offset
=
strlen
(
rootfs
->
path
);
skipabs:
skipabs:
...
@@ -2316,35 +2141,38 @@ static int mount_file_entries(const struct lxc_conf *conf,
...
@@ -2316,35 +2141,38 @@ static int mount_file_entries(const struct lxc_conf *conf,
return
-
1
;
return
-
1
;
}
}
if
(
!
feof
(
file
)
||
ferror
(
file
))
{
if
(
!
feof
(
file
)
||
ferror
(
file
))
ERROR
(
"Failed to parse mount entries"
);
return
log_error
(
-
1
,
"Failed to parse mount entries"
);
return
-
1
;
}
return
0
;
return
0
;
}
}
static
inline
void
__auto_endmntent__
(
FILE
**
f
)
{
if
(
*
f
)
endmntent
(
*
f
);
}
#define __do_endmntent __attribute__((__cleanup__(__auto_endmntent__)))
static
int
setup_mount
(
const
struct
lxc_conf
*
conf
,
static
int
setup_mount
(
const
struct
lxc_conf
*
conf
,
const
struct
lxc_rootfs
*
rootfs
,
const
char
*
fstab
,
const
struct
lxc_rootfs
*
rootfs
,
const
char
*
fstab
,
const
char
*
lxc_name
,
const
char
*
lxc_path
)
const
char
*
lxc_name
,
const
char
*
lxc_path
)
{
{
FILE
*
f
;
__do_endmntent
FILE
*
f
=
NULL
;
int
ret
;
int
ret
;
if
(
!
fstab
)
if
(
!
fstab
)
return
0
;
return
0
;
f
=
setmntent
(
fstab
,
"r"
);
f
=
setmntent
(
fstab
,
"re"
);
if
(
!
f
)
{
if
(
!
f
)
SYSERROR
(
"Failed to open
\"
%s
\"
"
,
fstab
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to open
\"
%s
\"
"
,
fstab
);
return
-
1
;
}
ret
=
mount_file_entries
(
conf
,
rootfs
,
f
,
lxc_name
,
lxc_path
);
ret
=
mount_file_entries
(
conf
,
rootfs
,
f
,
lxc_name
,
lxc_path
);
if
(
ret
<
0
)
if
(
ret
<
0
)
ERROR
(
"Failed to set up mount entries"
);
ERROR
(
"Failed to set up mount entries"
);
endmntent
(
f
);
return
ret
;
return
ret
;
}
}
...
@@ -2379,10 +2207,8 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount,
...
@@ -2379,10 +2207,8 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount,
return
NULL
;
return
NULL
;
fd
=
lxc_make_tmpfile
(
template
,
true
);
fd
=
lxc_make_tmpfile
(
template
,
true
);
if
(
fd
<
0
)
{
if
(
fd
<
0
)
SYSERROR
(
"Could not create temporary mount file"
);
return
log_error_errno
(
NULL
,
errno
,
"Could not create temporary mount file"
);
return
NULL
;
}
TRACE
(
"Created temporary mount file"
);
TRACE
(
"Created temporary mount file"
);
}
}
...
@@ -2496,17 +2322,13 @@ static int setup_caps(struct lxc_list *caps)
...
@@ -2496,17 +2322,13 @@ static int setup_caps(struct lxc_list *caps)
drop_entry
=
iterator
->
elem
;
drop_entry
=
iterator
->
elem
;
capid
=
parse_cap
(
drop_entry
);
capid
=
parse_cap
(
drop_entry
);
if
(
capid
<
0
)
{
if
(
capid
<
0
)
ERROR
(
"unknown capability %s"
,
drop_entry
);
return
log_error
(
-
1
,
"unknown capability %s"
,
drop_entry
);
return
-
1
;
}
ret
=
prctl
(
PR_CAPBSET_DROP
,
prctl_arg
(
capid
),
prctl_arg
(
0
),
ret
=
prctl
(
PR_CAPBSET_DROP
,
prctl_arg
(
capid
),
prctl_arg
(
0
),
prctl_arg
(
0
),
prctl_arg
(
0
));
prctl_arg
(
0
),
prctl_arg
(
0
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to remove %s capability"
,
drop_entry
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to remove %s capability"
,
drop_entry
);
return
-
1
;
}
DEBUG
(
"Dropped %s (%d) capability"
,
drop_entry
,
capid
);
DEBUG
(
"Dropped %s (%d) capability"
,
drop_entry
,
capid
);
}
}
...
@@ -2537,10 +2359,8 @@ static int dropcaps_except(struct lxc_list *caps)
...
@@ -2537,10 +2359,8 @@ static int dropcaps_except(struct lxc_list *caps)
if
(
capid
==
-
2
)
if
(
capid
==
-
2
)
continue
;
continue
;
if
(
capid
<
0
)
{
if
(
capid
<
0
)
ERROR
(
"Unknown capability %s"
,
keep_entry
);
return
log_error
(
-
1
,
"Unknown capability %s"
,
keep_entry
);
return
-
1
;
}
DEBUG
(
"Keep capability %s (%d)"
,
keep_entry
,
capid
);
DEBUG
(
"Keep capability %s (%d)"
,
keep_entry
,
capid
);
caplist
[
capid
]
=
1
;
caplist
[
capid
]
=
1
;
...
@@ -2554,10 +2374,8 @@ static int dropcaps_except(struct lxc_list *caps)
...
@@ -2554,10 +2374,8 @@ static int dropcaps_except(struct lxc_list *caps)
ret
=
prctl
(
PR_CAPBSET_DROP
,
prctl_arg
(
i
),
prctl_arg
(
0
),
ret
=
prctl
(
PR_CAPBSET_DROP
,
prctl_arg
(
i
),
prctl_arg
(
0
),
prctl_arg
(
0
),
prctl_arg
(
0
));
prctl_arg
(
0
),
prctl_arg
(
0
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to remove capability %d"
,
i
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to remove capability %d"
,
i
);
return
-
1
;
}
}
}
DEBUG
(
"Capabilities have been setup"
);
DEBUG
(
"Capabilities have been setup"
);
...
@@ -2595,21 +2413,16 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid)
...
@@ -2595,21 +2413,16 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid)
lim
=
it
->
elem
;
lim
=
it
->
elem
;
resid
=
parse_resource
(
lim
->
resource
);
resid
=
parse_resource
(
lim
->
resource
);
if
(
resid
<
0
)
{
if
(
resid
<
0
)
ERROR
(
"Unknown resource %s"
,
lim
->
resource
);
return
log_error
(
-
1
,
"Unknown resource %s"
,
lim
->
resource
);
return
-
1
;
}
#if HAVE_PRLIMIT || HAVE_PRLIMIT64
#if HAVE_PRLIMIT || HAVE_PRLIMIT64
if
(
prlimit
(
pid
,
resid
,
&
lim
->
limit
,
NULL
)
!=
0
)
{
if
(
prlimit
(
pid
,
resid
,
&
lim
->
limit
,
NULL
)
!=
0
)
SYSERROR
(
"Failed to set limit %s"
,
lim
->
resource
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to set limit %s"
,
lim
->
resource
);
return
-
1
;
}
TRACE
(
"Setup
\"
%s
\"
limit"
,
lim
->
resource
);
TRACE
(
"Setup
\"
%s
\"
limit"
,
lim
->
resource
);
#else
#else
ERROR
(
"Cannot set limit
\"
%s
\"
as prlimit is missing"
,
lim
->
resource
);
return
log_error
(
-
1
,
"Cannot set limit
\"
%s
\"
as prlimit is missing"
,
lim
->
resource
);
return
-
1
;
#endif
#endif
}
}
...
@@ -2627,24 +2440,18 @@ int setup_sysctl_parameters(struct lxc_list *sysctls)
...
@@ -2627,24 +2440,18 @@ int setup_sysctl_parameters(struct lxc_list *sysctls)
lxc_list_for_each
(
it
,
sysctls
)
{
lxc_list_for_each
(
it
,
sysctls
)
{
elem
=
it
->
elem
;
elem
=
it
->
elem
;
tmp
=
lxc_string_replace
(
"."
,
"/"
,
elem
->
key
);
tmp
=
lxc_string_replace
(
"."
,
"/"
,
elem
->
key
);
if
(
!
tmp
)
{
if
(
!
tmp
)
ERROR
(
"Failed to replace key %s"
,
elem
->
key
);
return
log_error
(
-
1
,
"Failed to replace key %s"
,
elem
->
key
);
return
-
1
;
}
ret
=
snprintf
(
filename
,
sizeof
(
filename
),
"/proc/sys/%s"
,
tmp
);
ret
=
snprintf
(
filename
,
sizeof
(
filename
),
"/proc/sys/%s"
,
tmp
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
filename
))
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
filename
))
ERROR
(
"Error setting up sysctl parameters path"
);
return
log_error
(
-
1
,
"Error setting up sysctl parameters path"
);
return
-
1
;
}
ret
=
lxc_write_to_file
(
filename
,
elem
->
value
,
ret
=
lxc_write_to_file
(
filename
,
elem
->
value
,
strlen
(
elem
->
value
),
false
,
0666
);
strlen
(
elem
->
value
),
false
,
0666
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to setup sysctl parameters %s to %s"
,
return
log_error_errno
(
-
1
,
errno
,
"Failed to setup sysctl parameters %s to %s"
,
elem
->
key
,
elem
->
value
);
elem
->
key
,
elem
->
value
);
return
-
1
;
}
}
}
return
0
;
return
0
;
...
@@ -2661,24 +2468,17 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid)
...
@@ -2661,24 +2468,17 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid)
lxc_list_for_each
(
it
,
procs
)
{
lxc_list_for_each
(
it
,
procs
)
{
elem
=
it
->
elem
;
elem
=
it
->
elem
;
tmp
=
lxc_string_replace
(
"."
,
"/"
,
elem
->
filename
);
tmp
=
lxc_string_replace
(
"."
,
"/"
,
elem
->
filename
);
if
(
!
tmp
)
{
if
(
!
tmp
)
ERROR
(
"Failed to replace key %s"
,
elem
->
filename
);
return
log_error
(
-
1
,
"Failed to replace key %s"
,
elem
->
filename
);
return
-
1
;
}
ret
=
snprintf
(
filename
,
sizeof
(
filename
),
"/proc/%d/%s"
,
pid
,
tmp
);
ret
=
snprintf
(
filename
,
sizeof
(
filename
),
"/proc/%d/%s"
,
pid
,
tmp
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
filename
))
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
sizeof
(
filename
))
ERROR
(
"Error setting up proc filesystem path"
);
return
log_error
(
-
1
,
"Error setting up proc filesystem path"
);
return
-
1
;
}
ret
=
lxc_write_to_file
(
filename
,
elem
->
value
,
ret
=
lxc_write_to_file
(
filename
,
elem
->
value
,
strlen
(
elem
->
value
),
false
,
0666
);
strlen
(
elem
->
value
),
false
,
0666
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to setup proc filesystem %s to %s"
,
return
log_error_errno
(
-
1
,
errno
,
"Failed to setup proc filesystem %s to %s"
,
elem
->
filename
,
elem
->
value
);
elem
->
filename
,
elem
->
value
);
return
-
1
;
}
}
}
return
0
;
return
0
;
...
@@ -2779,18 +2579,14 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
...
@@ -2779,18 +2579,14 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
return
-
E2BIG
;
return
-
E2BIG
;
setgroups_fd
=
open
(
path
,
O_WRONLY
);
setgroups_fd
=
open
(
path
,
O_WRONLY
);
if
(
setgroups_fd
<
0
&&
errno
!=
ENOENT
)
{
if
(
setgroups_fd
<
0
&&
errno
!=
ENOENT
)
SYSERROR
(
"Failed to open
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to open
\"
%s
\"
"
,
path
);
return
-
1
;
}
if
(
setgroups_fd
>=
0
)
{
if
(
setgroups_fd
>=
0
)
{
ret
=
lxc_write_nointr
(
setgroups_fd
,
"deny
\n
"
,
ret
=
lxc_write_nointr
(
setgroups_fd
,
"deny
\n
"
,
STRLITERALLEN
(
"deny
\n
"
));
STRLITERALLEN
(
"deny
\n
"
));
if
(
ret
!=
STRLITERALLEN
(
"deny
\n
"
))
{
if
(
ret
!=
STRLITERALLEN
(
"deny
\n
"
))
SYSERROR
(
"Failed to write
\"
deny
\"
to
\"
/proc/%d/setgroups
\"
"
,
pid
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to write
\"
deny
\"
to
\"
/proc/%d/setgroups
\"
"
,
pid
);
return
-
1
;
}
TRACE
(
"Wrote
\"
deny
\"
to
\"
/proc/%d/setgroups
\"
"
,
pid
);
TRACE
(
"Wrote
\"
deny
\"
to
\"
/proc/%d/setgroups
\"
"
,
pid
);
}
}
}
}
...
@@ -2800,18 +2596,14 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
...
@@ -2800,18 +2596,14 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
return
-
E2BIG
;
return
-
E2BIG
;
fd
=
open
(
path
,
O_WRONLY
);
fd
=
open
(
path
,
O_WRONLY
|
O_CLOEXEC
);
if
(
fd
<
0
)
{
if
(
fd
<
0
)
SYSERROR
(
"Failed to open
\"
%s
\"
"
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to open
\"
%s
\"
"
,
path
);
return
-
1
;
}
ret
=
lxc_write_nointr
(
fd
,
buf
,
buf_size
);
ret
=
lxc_write_nointr
(
fd
,
buf
,
buf_size
);
if
(
ret
!=
buf_size
)
{
if
(
ret
!=
buf_size
)
SYSERROR
(
"Failed to write %cid mapping to
\"
%s
\"
"
,
return
log_error_errno
(
-
1
,
errno
,
"Failed to write %cid mapping to
\"
%s
\"
"
,
idtype
==
ID_TYPE_UID
?
'u'
:
'g'
,
path
);
idtype
==
ID_TYPE_UID
?
'u'
:
'g'
,
path
);
return
-
1
;
}
return
0
;
return
0
;
}
}
...
@@ -2843,36 +2635,27 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
...
@@ -2843,36 +2635,27 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
return
-
1
;
return
-
1
;
/* Check if the binary is setuid. */
/* Check if the binary is setuid. */
if
(
st
.
st_mode
&
S_ISUID
)
{
if
(
st
.
st_mode
&
S_ISUID
)
DEBUG
(
"The binary
\"
%s
\"
does have the setuid bit set"
,
path
);
return
log_debug
(
1
,
"The binary
\"
%s
\"
does have the setuid bit set"
,
path
);
return
1
;
}
#if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES
#if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES
/* Check if it has the CAP_SETUID capability. */
/* Check if it has the CAP_SETUID capability. */
if
((
cap
&
CAP_SETUID
)
&&
if
((
cap
&
CAP_SETUID
)
&&
lxc_file_cap_is_set
(
path
,
CAP_SETUID
,
CAP_EFFECTIVE
)
&&
lxc_file_cap_is_set
(
path
,
CAP_SETUID
,
CAP_EFFECTIVE
)
&&
lxc_file_cap_is_set
(
path
,
CAP_SETUID
,
CAP_PERMITTED
))
{
lxc_file_cap_is_set
(
path
,
CAP_SETUID
,
CAP_PERMITTED
))
DEBUG
(
"The binary
\"
%s
\"
has CAP_SETUID in its CAP_EFFECTIVE "
return
log_debug
(
1
,
"The binary
\"
%s
\"
has CAP_SETUID in its CAP_EFFECTIVE and CAP_PERMITTED sets"
,
path
);
"and CAP_PERMITTED sets"
,
path
);
return
1
;
}
/* Check if it has the CAP_SETGID capability. */
/* Check if it has the CAP_SETGID capability. */
if
((
cap
&
CAP_SETGID
)
&&
if
((
cap
&
CAP_SETGID
)
&&
lxc_file_cap_is_set
(
path
,
CAP_SETGID
,
CAP_EFFECTIVE
)
&&
lxc_file_cap_is_set
(
path
,
CAP_SETGID
,
CAP_EFFECTIVE
)
&&
lxc_file_cap_is_set
(
path
,
CAP_SETGID
,
CAP_PERMITTED
))
{
lxc_file_cap_is_set
(
path
,
CAP_SETGID
,
CAP_PERMITTED
))
DEBUG
(
"The binary
\"
%s
\"
has CAP_SETGID in its CAP_EFFECTIVE "
return
log_debug
(
1
,
"The binary
\"
%s
\"
has CAP_SETGID in its CAP_EFFECTIVE and CAP_PERMITTED sets"
,
path
);
"and CAP_PERMITTED sets"
,
path
);
return
1
;
}
#else
#else
/* If we cannot check for file capabilities we need to give the benefit
/* If we cannot check for file capabilities we need to give the benefit
* of the doubt. Otherwise we might fail even though all the necessary
* of the doubt. Otherwise we might fail even though all the necessary
* file capabilities are set.
* file capabilities are set.
*/
*/
DEBUG
(
"Cannot check for file capabilities as full capability support is "
DEBUG
(
"Cannot check for file capabilities as full capability support is missing. Manual intervention needed"
);
"missing. Manual intervention needed"
);
#endif
#endif
return
1
;
return
1
;
...
@@ -2979,13 +2762,12 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
...
@@ -2979,13 +2762,12 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
use_shadow
?
" "
:
""
,
map
->
nsid
,
use_shadow
?
" "
:
""
,
map
->
nsid
,
map
->
hostid
,
map
->
range
,
map
->
hostid
,
map
->
range
,
use_shadow
?
""
:
"
\n
"
);
use_shadow
?
""
:
"
\n
"
);
if
(
fill
<=
0
||
fill
>=
left
)
{
/*
/* The kernel only takes <= 4k for writes to
* The kernel only takes <= 4k for writes to
* /proc/<pid>/{g,u}id_map
* /proc/<pid>/{g,u}id_map
*/
*/
SYSERROR
(
"Too many %cid mappings defined"
,
u_or_g
);
if
(
fill
<=
0
||
fill
>=
left
)
return
-
1
;
return
log_error_errno
(
-
1
,
errno
,
"Too many %cid mappings defined"
,
u_or_g
);
}
pos
+=
fill
;
pos
+=
fill
;
}
}
...
@@ -2999,18 +2781,13 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
...
@@ -2999,18 +2781,13 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
lxc_map_ids_exec_wrapper
,
lxc_map_ids_exec_wrapper
,
(
void
*
)
mapbuf
);
(
void
*
)
mapbuf
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"new%cidmap failed to write mapping
\"
%s
\"
: %s"
,
return
log_error
(
-
1
,
"new%cidmap failed to write mapping
\"
%s
\"
: %s"
,
u_or_g
,
cmd_output
,
mapbuf
);
u_or_g
,
cmd_output
,
mapbuf
);
return
-
1
;
}
TRACE
(
"new%cidmap wrote mapping
\"
%s
\"
"
,
u_or_g
,
mapbuf
);
TRACE
(
"new%cidmap wrote mapping
\"
%s
\"
"
,
u_or_g
,
mapbuf
);
}
else
{
}
else
{
ret
=
write_id_mapping
(
type
,
pid
,
mapbuf
,
pos
-
mapbuf
);
ret
=
write_id_mapping
(
type
,
pid
,
mapbuf
,
pos
-
mapbuf
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to write mapping: %s"
,
mapbuf
);
return
log_error
(
-
1
,
"Failed to write mapping: %s"
,
mapbuf
);
return
-
1
;
}
TRACE
(
"Wrote mapping
\"
%s
\"
"
,
mapbuf
);
TRACE
(
"Wrote mapping
\"
%s
\"
"
,
mapbuf
);
}
}
...
@@ -3127,38 +2904,28 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf)
...
@@ -3127,38 +2904,28 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf)
hostuid
=
geteuid
();
hostuid
=
geteuid
();
hostgid
=
getegid
();
hostgid
=
getegid
();
if
(
!
get_mapped_rootid
(
conf
,
ID_TYPE_UID
,
&
val
))
{
if
(
!
get_mapped_rootid
(
conf
,
ID_TYPE_UID
,
&
val
))
ERROR
(
"No uid mapping for container root"
);
return
log_error
(
-
1
,
"No uid mapping for container root"
);
return
-
1
;
}
rootuid
=
(
uid_t
)
val
;
rootuid
=
(
uid_t
)
val
;
if
(
!
get_mapped_rootid
(
conf
,
ID_TYPE_GID
,
&
val
))
{
if
(
!
get_mapped_rootid
(
conf
,
ID_TYPE_GID
,
&
val
))
ERROR
(
"No gid mapping for container root"
);
return
log_error
(
-
1
,
"No gid mapping for container root"
);
return
-
1
;
}
rootgid
=
(
gid_t
)
val
;
rootgid
=
(
gid_t
)
val
;
if
(
hostuid
==
0
)
{
if
(
hostuid
==
0
)
{
if
(
chown
(
path
,
rootuid
,
rootgid
)
<
0
)
{
if
(
chown
(
path
,
rootuid
,
rootgid
)
<
0
)
ERROR
(
"Error chowning %s"
,
path
);
return
log_error
(
-
1
,
"Error chowning %s"
,
path
);
return
-
1
;
}
return
0
;
return
0
;
}
}
if
(
rootuid
==
hostuid
)
{
/* nothing to do */
/* nothing to do */
if
(
rootuid
==
hostuid
)
INFO
(
"Container root is our uid; no need to chown"
);
return
log_info
(
0
,
"Container root is our uid; no need to chown"
);
return
0
;
}
/* save the current gid of "path" */
/* save the current gid of "path" */
if
(
stat
(
path
,
&
sb
)
<
0
)
{
if
(
stat
(
path
,
&
sb
)
<
0
)
ERROR
(
"Error stat %s"
,
path
);
return
log_error
(
-
1
,
"Error stat %s"
,
path
);
return
-
1
;
}
/* Update the path argument in case this was overlayfs. */
/* Update the path argument in case this was overlayfs. */
args1
[
sizeof
(
args1
)
/
sizeof
(
args1
[
0
])
-
2
]
=
path
;
args1
[
sizeof
(
args1
)
/
sizeof
(
args1
[
0
])
-
2
]
=
path
;
...
@@ -3171,53 +2938,39 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf)
...
@@ -3171,53 +2938,39 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf)
DEBUG
(
"trying to chown
\"
%s
\"
to %d"
,
path
,
hostgid
);
DEBUG
(
"trying to chown
\"
%s
\"
to %d"
,
path
,
hostgid
);
if
(
sb
.
st_uid
==
hostuid
&&
if
(
sb
.
st_uid
==
hostuid
&&
mapped_hostid
(
sb
.
st_gid
,
conf
,
ID_TYPE_GID
)
<
0
&&
mapped_hostid
(
sb
.
st_gid
,
conf
,
ID_TYPE_GID
)
<
0
&&
chown
(
path
,
-
1
,
hostgid
)
<
0
)
{
chown
(
path
,
-
1
,
hostgid
)
<
0
)
ERROR
(
"Failed chgrping %s"
,
path
);
return
log_error
(
-
1
,
"Failed chgrping %s"
,
path
);
return
-
1
;
}
/* "u:0:rootuid:1" */
/* "u:0:rootuid:1" */
ret
=
snprintf
(
map1
,
100
,
"u:0:%d:1"
,
rootuid
);
ret
=
snprintf
(
map1
,
100
,
"u:0:%d:1"
,
rootuid
);
if
(
ret
<
0
||
ret
>=
100
)
{
if
(
ret
<
0
||
ret
>=
100
)
ERROR
(
"Error uid printing map string"
);
return
log_error
(
-
1
,
"Error uid printing map string"
);
return
-
1
;
}
/* "u:hostuid:hostuid:1" */
/* "u:hostuid:hostuid:1" */
ret
=
snprintf
(
map2
,
100
,
"u:%d:%d:1"
,
hostuid
,
hostuid
);
ret
=
snprintf
(
map2
,
100
,
"u:%d:%d:1"
,
hostuid
,
hostuid
);
if
(
ret
<
0
||
ret
>=
100
)
{
if
(
ret
<
0
||
ret
>=
100
)
ERROR
(
"Error uid printing map string"
);
return
log_error
(
-
1
,
"Error uid printing map string"
);
return
-
1
;
}
/* "g:0:rootgid:1" */
/* "g:0:rootgid:1" */
ret
=
snprintf
(
map3
,
100
,
"g:0:%d:1"
,
rootgid
);
ret
=
snprintf
(
map3
,
100
,
"g:0:%d:1"
,
rootgid
);
if
(
ret
<
0
||
ret
>=
100
)
{
if
(
ret
<
0
||
ret
>=
100
)
ERROR
(
"Error gid printing map string"
);
return
log_error
(
-
1
,
"Error gid printing map string"
);
return
-
1
;
}
/* "g:pathgid:rootgid+pathgid:1" */
/* "g:pathgid:rootgid+pathgid:1" */
ret
=
snprintf
(
map4
,
100
,
"g:%d:%d:1"
,
(
gid_t
)
sb
.
st_gid
,
ret
=
snprintf
(
map4
,
100
,
"g:%d:%d:1"
,
(
gid_t
)
sb
.
st_gid
,
rootgid
+
(
gid_t
)
sb
.
st_gid
);
rootgid
+
(
gid_t
)
sb
.
st_gid
);
if
(
ret
<
0
||
ret
>=
100
)
{
if
(
ret
<
0
||
ret
>=
100
)
ERROR
(
"Error gid printing map string"
);
return
log_error
(
-
1
,
"Error gid printing map string"
);
return
-
1
;
}
/* "g:hostgid:hostgid:1" */
/* "g:hostgid:hostgid:1" */
ret
=
snprintf
(
map5
,
100
,
"g:%d:%d:1"
,
hostgid
,
hostgid
);
ret
=
snprintf
(
map5
,
100
,
"g:%d:%d:1"
,
hostgid
,
hostgid
);
if
(
ret
<
0
||
ret
>=
100
)
{
if
(
ret
<
0
||
ret
>=
100
)
ERROR
(
"Error gid printing map string"
);
return
log_error
(
-
1
,
"Error gid printing map string"
);
return
-
1
;
}
/* "0:pathgid" (chown) */
/* "0:pathgid" (chown) */
ret
=
snprintf
(
ugid
,
100
,
"0:%d"
,
(
gid_t
)
sb
.
st_gid
);
ret
=
snprintf
(
ugid
,
100
,
"0:%d"
,
(
gid_t
)
sb
.
st_gid
);
if
(
ret
<
0
||
ret
>=
100
)
{
if
(
ret
<
0
||
ret
>=
100
)
ERROR
(
"Error owner printing format string for chown"
);
return
log_error
(
-
1
,
"Error owner printing format string for chown"
);
return
-
1
;
}
if
(
hostgid
==
sb
.
st_gid
)
if
(
hostgid
==
sb
.
st_gid
)
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
...
@@ -3371,10 +3124,8 @@ static int lxc_execute_bind_init(struct lxc_handler *handler)
...
@@ -3371,10 +3124,8 @@ static int lxc_execute_bind_init(struct lxc_handler *handler)
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
return
-
1
;
return
-
1
;
if
(
!
file_exists
(
path
))
{
if
(
!
file_exists
(
path
))
ERROR
(
"The file
\"
%s
\"
does not exist on host"
,
path
);
return
log_error_errno
(
-
1
,
errno
,
"The file
\"
%s
\"
does not exist on host"
,
path
);
return
-
1
;
}
ret
=
snprintf
(
destpath
,
PATH_MAX
,
"%s"
P_tmpdir
"%s"
,
conf
->
rootfs
.
mount
,
"/.lxc-init"
);
ret
=
snprintf
(
destpath
,
PATH_MAX
,
"%s"
P_tmpdir
"%s"
,
conf
->
rootfs
.
mount
,
"/.lxc-init"
);
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
...
@@ -3382,17 +3133,13 @@ static int lxc_execute_bind_init(struct lxc_handler *handler)
...
@@ -3382,17 +3133,13 @@ static int lxc_execute_bind_init(struct lxc_handler *handler)
if
(
!
file_exists
(
destpath
))
{
if
(
!
file_exists
(
destpath
))
{
ret
=
mknod
(
destpath
,
S_IFREG
|
0000
,
0
);
ret
=
mknod
(
destpath
,
S_IFREG
|
0000
,
0
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
SYSERROR
(
"Failed to create dummy
\"
%s
\"
file as bind mount target"
,
destpath
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to create dummy
\"
%s
\"
file as bind mount target"
,
destpath
);
return
-
1
;
}
}
}
ret
=
safe_mount
(
path
,
destpath
,
"none"
,
MS_BIND
,
NULL
,
conf
->
rootfs
.
mount
);
ret
=
safe_mount
(
path
,
destpath
,
"none"
,
MS_BIND
,
NULL
,
conf
->
rootfs
.
mount
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to bind mount lxc.init.static into container"
);
return
log_error_errno
(
-
1
,
errno
,
"Failed to bind mount lxc.init.static into container"
);
return
-
1
;
}
p
=
strdup
(
destpath
+
strlen
(
conf
->
rootfs
.
mount
));
p
=
strdup
(
destpath
+
strlen
(
conf
->
rootfs
.
mount
));
if
(
!
p
)
if
(
!
p
)
...
@@ -3420,28 +3167,21 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
...
@@ -3420,28 +3167,21 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
* give us a mount in our own ns so we can pivot_root to it
* give us a mount in our own ns so we can pivot_root to it
*/
*/
ret
=
mount
(
path
,
path
,
"rootfs"
,
MS_BIND
,
NULL
);
ret
=
mount
(
path
,
path
,
"rootfs"
,
MS_BIND
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to bind mount container / onto itself"
);
return
log_error
(
-
1
,
"Failed to bind mount container / onto itself"
);
return
-
1
;
}
TRACE
(
"Bind mounted container / onto itself"
);
return
log_trace
(
0
,
"Bind mounted container / onto itself"
);
return
0
;
}
}
remount_all_slave
();
remount_all_slave
();
ret
=
run_lxc_hooks
(
name
,
"pre-mount"
,
conf
,
NULL
);
ret
=
run_lxc_hooks
(
name
,
"pre-mount"
,
conf
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to run pre-mount hooks"
);
return
log_error
(
-
1
,
"Failed to run pre-mount hooks"
);
return
-
1
;
}
ret
=
lxc_mount_rootfs
(
conf
);
ret
=
lxc_mount_rootfs
(
conf
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup rootfs for"
);
return
log_error
(
-
1
,
"Failed to setup rootfs for"
);
return
-
1
;
}
conf
->
rootfs_setup
=
true
;
conf
->
rootfs_setup
=
true
;
return
0
;
return
0
;
...
@@ -3463,11 +3203,8 @@ static bool verify_start_hooks(struct lxc_conf *conf)
...
@@ -3463,11 +3203,8 @@ static bool verify_start_hooks(struct lxc_conf *conf)
return
false
;
return
false
;
ret
=
access
(
path
,
X_OK
);
ret
=
access
(
path
,
X_OK
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Start hook
\"
%s
\"
not found in container"
,
return
log_error_errno
(
false
,
errno
,
"Start hook
\"
%s
\"
not found in container"
,
hookname
);
hookname
);
return
false
;
}
return
true
;
return
true
;
}
}
...
@@ -3542,17 +3279,13 @@ int lxc_setup(struct lxc_handler *handler)
...
@@ -3542,17 +3279,13 @@ int lxc_setup(struct lxc_handler *handler)
char
*
keyring_context
=
NULL
;
char
*
keyring_context
=
NULL
;
ret
=
lxc_setup_rootfs_prepare_root
(
lxc_conf
,
name
,
lxcpath
);
ret
=
lxc_setup_rootfs_prepare_root
(
lxc_conf
,
name
,
lxcpath
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup rootfs"
);
return
log_error
(
-
1
,
"Failed to setup rootfs"
);
return
-
1
;
}
if
(
handler
->
nsfd
[
LXC_NS_UTS
]
==
-
EBADF
)
{
if
(
handler
->
nsfd
[
LXC_NS_UTS
]
==
-
EBADF
)
{
ret
=
setup_utsname
(
lxc_conf
->
utsname
);
ret
=
setup_utsname
(
lxc_conf
->
utsname
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup the utsname %s"
,
name
);
return
log_error
(
-
1
,
"Failed to setup the utsname %s"
,
name
);
return
-
1
;
}
}
}
if
(
!
lxc_conf
->
keyring_disable_session
)
{
if
(
!
lxc_conf
->
keyring_disable_session
)
{
...
@@ -3570,48 +3303,36 @@ int lxc_setup(struct lxc_handler *handler)
...
@@ -3570,48 +3303,36 @@ int lxc_setup(struct lxc_handler *handler)
if
(
handler
->
ns_clone_flags
&
CLONE_NEWNET
)
{
if
(
handler
->
ns_clone_flags
&
CLONE_NEWNET
)
{
ret
=
lxc_setup_network_in_child_namespaces
(
lxc_conf
,
ret
=
lxc_setup_network_in_child_namespaces
(
lxc_conf
,
&
lxc_conf
->
network
);
&
lxc_conf
->
network
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup network"
);
return
log_error
(
-
1
,
"Failed to setup network"
);
return
-
1
;
}
ret
=
lxc_network_send_name_and_ifindex_to_parent
(
handler
);
ret
=
lxc_network_send_name_and_ifindex_to_parent
(
handler
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to send network device names and ifindices to parent"
);
return
log_error
(
-
1
,
"Failed to send network device names and ifindices to parent"
);
return
-
1
;
}
}
}
if
(
lxc_conf
->
autodev
>
0
)
{
if
(
lxc_conf
->
autodev
>
0
)
{
ret
=
mount_autodev
(
name
,
&
lxc_conf
->
rootfs
,
lxc_conf
->
autodevtmpfssize
,
lxcpath
);
ret
=
mount_autodev
(
name
,
&
lxc_conf
->
rootfs
,
lxc_conf
->
autodevtmpfssize
,
lxcpath
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to mount
\"
/dev
\"
"
);
return
log_error
(
-
1
,
"Failed to mount
\"
/dev
\"
"
);
return
-
1
;
}
}
}
/* Do automatic mounts (mainly /proc and /sys), but exclude those that
/* Do automatic mounts (mainly /proc and /sys), but exclude those that
* need to wait until other stuff has finished.
* need to wait until other stuff has finished.
*/
*/
ret
=
lxc_mount_auto_mounts
(
lxc_conf
,
lxc_conf
->
auto_mounts
&
~
LXC_AUTO_CGROUP_MASK
,
handler
);
ret
=
lxc_mount_auto_mounts
(
lxc_conf
,
lxc_conf
->
auto_mounts
&
~
LXC_AUTO_CGROUP_MASK
,
handler
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup first automatic mounts"
);
return
log_error
(
-
1
,
"Failed to setup first automatic mounts"
);
return
-
1
;
}
ret
=
setup_mount
(
lxc_conf
,
&
lxc_conf
->
rootfs
,
lxc_conf
->
fstab
,
name
,
lxcpath
);
ret
=
setup_mount
(
lxc_conf
,
&
lxc_conf
->
rootfs
,
lxc_conf
->
fstab
,
name
,
lxcpath
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup mounts"
);
return
log_error
(
-
1
,
"Failed to setup mounts"
);
return
-
1
;
}
if
(
!
lxc_list_empty
(
&
lxc_conf
->
mount_list
))
{
if
(
!
lxc_list_empty
(
&
lxc_conf
->
mount_list
))
{
ret
=
setup_mount_entries
(
lxc_conf
,
&
lxc_conf
->
rootfs
,
ret
=
setup_mount_entries
(
lxc_conf
,
&
lxc_conf
->
rootfs
,
&
lxc_conf
->
mount_list
,
name
,
lxcpath
);
&
lxc_conf
->
mount_list
,
name
,
lxcpath
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup mount entries"
);
return
log_error
(
-
1
,
"Failed to setup mount entries"
);
return
-
1
;
}
}
}
if
(
lxc_conf
->
is_execute
)
{
if
(
lxc_conf
->
is_execute
)
{
...
@@ -3620,25 +3341,19 @@ int lxc_setup(struct lxc_handler *handler)
...
@@ -3620,25 +3341,19 @@ int lxc_setup(struct lxc_handler *handler)
char
path
[
PATH_MAX
];
char
path
[
PATH_MAX
];
ret
=
snprintf
(
path
,
PATH_MAX
,
SBINDIR
"/init.lxc.static"
);
ret
=
snprintf
(
path
,
PATH_MAX
,
SBINDIR
"/init.lxc.static"
);
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
{
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
ERROR
(
"Path to init.lxc.static too long"
);
return
log_error
(
-
1
,
"Path to init.lxc.static too long"
);
return
-
1
;
}
fd
=
open
(
path
,
O_PATH
|
O_CLOEXEC
);
fd
=
open
(
path
,
O_PATH
|
O_CLOEXEC
);
if
(
fd
<
0
)
{
if
(
fd
<
0
)
SYSERROR
(
"Unable to open lxc.init.static"
);
return
log_error_errno
(
-
1
,
errno
,
"Unable to open lxc.init.static"
);
return
-
1
;
}
((
struct
execute_args
*
)
handler
->
data
)
->
init_fd
=
fd
;
((
struct
execute_args
*
)
handler
->
data
)
->
init_fd
=
fd
;
((
struct
execute_args
*
)
handler
->
data
)
->
init_path
=
NULL
;
((
struct
execute_args
*
)
handler
->
data
)
->
init_path
=
NULL
;
}
else
{
}
else
{
ret
=
lxc_execute_bind_init
(
handler
);
ret
=
lxc_execute_bind_init
(
handler
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to bind-mount the lxc init system"
);
return
log_error
(
-
1
,
"Failed to bind-mount the lxc init system"
);
return
-
1
;
}
}
}
}
}
...
@@ -3647,81 +3362,59 @@ int lxc_setup(struct lxc_handler *handler)
...
@@ -3647,81 +3362,59 @@ int lxc_setup(struct lxc_handler *handler)
* automatically or via fstab entries.
* automatically or via fstab entries.
*/
*/
ret
=
lxc_mount_auto_mounts
(
lxc_conf
,
lxc_conf
->
auto_mounts
&
LXC_AUTO_CGROUP_MASK
,
handler
);
ret
=
lxc_mount_auto_mounts
(
lxc_conf
,
lxc_conf
->
auto_mounts
&
LXC_AUTO_CGROUP_MASK
,
handler
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup remaining automatic mounts"
);
return
log_error
(
-
1
,
"Failed to setup remaining automatic mounts"
);
return
-
1
;
}
ret
=
run_lxc_hooks
(
name
,
"mount"
,
lxc_conf
,
NULL
);
ret
=
run_lxc_hooks
(
name
,
"mount"
,
lxc_conf
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to run mount hooks"
);
return
log_error
(
-
1
,
"Failed to run mount hooks"
);
return
-
1
;
}
if
(
lxc_conf
->
autodev
>
0
)
{
if
(
lxc_conf
->
autodev
>
0
)
{
ret
=
run_lxc_hooks
(
name
,
"autodev"
,
lxc_conf
,
NULL
);
ret
=
run_lxc_hooks
(
name
,
"autodev"
,
lxc_conf
,
NULL
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to run autodev hooks"
);
return
log_error
(
-
1
,
"Failed to run autodev hooks"
);
return
-
1
;
}
ret
=
lxc_fill_autodev
(
&
lxc_conf
->
rootfs
);
ret
=
lxc_fill_autodev
(
&
lxc_conf
->
rootfs
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to populate
\"
/dev
\"
"
);
return
log_error
(
-
1
,
"Failed to populate
\"
/dev
\"
"
);
return
-
1
;
}
}
}
/* Make sure any start hooks are in the container */
/* Make sure any start hooks are in the container */
if
(
!
verify_start_hooks
(
lxc_conf
))
{
if
(
!
verify_start_hooks
(
lxc_conf
))
ERROR
(
"Failed to verify start hooks"
);
return
log_error
(
-
1
,
"Failed to verify start hooks"
);
return
-
1
;
}
ret
=
lxc_setup_console
(
&
lxc_conf
->
rootfs
,
&
lxc_conf
->
console
,
ret
=
lxc_setup_console
(
&
lxc_conf
->
rootfs
,
&
lxc_conf
->
console
,
lxc_conf
->
ttys
.
dir
);
lxc_conf
->
ttys
.
dir
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup console"
);
return
log_error
(
-
1
,
"Failed to setup console"
);
return
-
1
;
}
ret
=
lxc_setup_dev_symlinks
(
&
lxc_conf
->
rootfs
);
ret
=
lxc_setup_dev_symlinks
(
&
lxc_conf
->
rootfs
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup
\"
/dev
\"
symlinks"
);
return
log_error
(
-
1
,
"Failed to setup
\"
/dev
\"
symlinks"
);
return
-
1
;
}
ret
=
lxc_create_tmp_proc_mount
(
lxc_conf
);
ret
=
lxc_create_tmp_proc_mount
(
lxc_conf
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to
\"
/proc
\"
LSMs"
);
return
log_error
(
-
1
,
"Failed to
\"
/proc
\"
LSMs"
);
return
-
1
;
}
ret
=
lxc_setup_rootfs_switch_root
(
&
lxc_conf
->
rootfs
);
ret
=
lxc_setup_rootfs_switch_root
(
&
lxc_conf
->
rootfs
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to pivot root into rootfs"
);
return
log_error
(
-
1
,
"Failed to pivot root into rootfs"
);
return
-
1
;
}
/* Setting the boot-id is best-effort for now. */
/* Setting the boot-id is best-effort for now. */
if
(
lxc_conf
->
autodev
>
0
)
if
(
lxc_conf
->
autodev
>
0
)
(
void
)
lxc_setup_boot_id
();
(
void
)
lxc_setup_boot_id
();
ret
=
lxc_setup_devpts
(
lxc_conf
);
ret
=
lxc_setup_devpts
(
lxc_conf
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup new devpts instance"
);
return
log_error
(
-
1
,
"Failed to setup new devpts instance"
);
return
-
1
;
}
ret
=
lxc_create_ttys
(
handler
);
ret
=
lxc_create_ttys
(
handler
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
-
1
;
return
-
1
;
ret
=
setup_personality
(
lxc_conf
->
personality
);
ret
=
setup_personality
(
lxc_conf
->
personality
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to set personality"
);
return
log_error
(
-
1
,
"Failed to set personality"
);
return
-
1
;
}
/* Set sysctl value to a path under /proc/sys as determined from the
/* Set sysctl value to a path under /proc/sys as determined from the
* key. For e.g. net.ipv4.ip_forward translated to
* key. For e.g. net.ipv4.ip_forward translated to
...
@@ -3729,27 +3422,18 @@ int lxc_setup(struct lxc_handler *handler)
...
@@ -3729,27 +3422,18 @@ int lxc_setup(struct lxc_handler *handler)
*/
*/
if
(
!
lxc_list_empty
(
&
lxc_conf
->
sysctls
))
{
if
(
!
lxc_list_empty
(
&
lxc_conf
->
sysctls
))
{
ret
=
setup_sysctl_parameters
(
&
lxc_conf
->
sysctls
);
ret
=
setup_sysctl_parameters
(
&
lxc_conf
->
sysctls
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
ERROR
(
"Failed to setup sysctl parameters"
);
return
log_error
(
-
1
,
"Failed to setup sysctl parameters"
);
return
-
1
;
}
}
}
if
(
!
lxc_list_empty
(
&
lxc_conf
->
keepcaps
))
{
if
(
!
lxc_list_empty
(
&
lxc_conf
->
keepcaps
))
{
if
(
!
lxc_list_empty
(
&
lxc_conf
->
caps
))
{
if
(
!
lxc_list_empty
(
&
lxc_conf
->
caps
))
ERROR
(
"Container requests lxc.cap.drop and "
return
log_error
(
-
1
,
"Container requests lxc.cap.drop and lxc.cap.keep: either use lxc.cap.drop or lxc.cap.keep, not both"
);
"lxc.cap.keep: either use lxc.cap.drop or "
"lxc.cap.keep, not both"
);
return
-
1
;
}
if
(
dropcaps_except
(
&
lxc_conf
->
keepcaps
))
{
if
(
dropcaps_except
(
&
lxc_conf
->
keepcaps
))
ERROR
(
"Failed to keep capabilities"
);
return
log_error
(
-
1
,
"Failed to keep capabilities"
);
return
-
1
;
}
}
else
if
(
setup_caps
(
&
lxc_conf
->
caps
))
{
}
else
if
(
setup_caps
(
&
lxc_conf
->
caps
))
{
ERROR
(
"Failed to drop capabilities"
);
return
log_error
(
-
1
,
"Failed to drop capabilities"
);
return
-
1
;
}
}
NOTICE
(
"The container
\"
%s
\"
is set up"
,
name
);
NOTICE
(
"The container
\"
%s
\"
is set up"
,
name
);
...
@@ -4053,10 +3737,8 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key)
...
@@ -4053,10 +3737,8 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key)
}
}
}
}
if
(
!
done
)
{
if
(
!
done
)
ERROR
(
"Invalid hook key: %s"
,
key
);
return
log_error
(
-
1
,
"Invalid hook key: %s"
,
key
);
return
-
1
;
}
return
0
;
return
0
;
}
}
...
@@ -4229,8 +3911,9 @@ static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf,
...
@@ -4229,8 +3911,9 @@ static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf,
static
struct
id_map
*
mapped_hostid_add
(
struct
lxc_conf
*
conf
,
uid_t
id
,
static
struct
id_map
*
mapped_hostid_add
(
struct
lxc_conf
*
conf
,
uid_t
id
,
enum
idtype
type
)
enum
idtype
type
)
{
{
__do_free
struct
id_map
*
entry
=
NULL
;
int
hostid_mapped
;
int
hostid_mapped
;
struct
id_map
*
entry
=
NULL
,
*
tmp
=
NULL
;
struct
id_map
*
tmp
=
NULL
;
entry
=
malloc
(
sizeof
(
*
entry
));
entry
=
malloc
(
sizeof
(
*
entry
));
if
(
!
entry
)
if
(
!
entry
)
...
@@ -4243,18 +3926,15 @@ static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id,
...
@@ -4243,18 +3926,15 @@ static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id,
/* Find new mapping. */
/* Find new mapping. */
hostid_mapped
=
find_unmapped_nsid
(
conf
,
type
);
hostid_mapped
=
find_unmapped_nsid
(
conf
,
type
);
if
(
hostid_mapped
<
0
)
{
if
(
hostid_mapped
<
0
)
DEBUG
(
"Failed to find free mapping for id %d"
,
id
);
return
log_debug
(
NULL
,
"Failed to find free mapping for id %d"
,
id
);
free
(
entry
);
return
NULL
;
}
entry
->
idtype
=
type
;
entry
->
idtype
=
type
;
entry
->
nsid
=
hostid_mapped
;
entry
->
nsid
=
hostid_mapped
;
entry
->
hostid
=
(
unsigned
long
)
id
;
entry
->
hostid
=
(
unsigned
long
)
id
;
entry
->
range
=
1
;
entry
->
range
=
1
;
return
entry
;
return
move_ptr
(
entry
)
;
}
}
struct
lxc_list
*
get_minimal_idmap
(
struct
lxc_conf
*
conf
)
struct
lxc_list
*
get_minimal_idmap
(
struct
lxc_conf
*
conf
)
...
@@ -4270,20 +3950,16 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
...
@@ -4270,20 +3950,16 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
/* Find container root mappings. */
/* Find container root mappings. */
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 namespace uid %d"
,
0
);
return
log_debug
(
NULL
,
"Failed to find mapping for namespace uid %d"
,
0
);
return
NULL
;
}
euid
=
geteuid
();
euid
=
geteuid
();
if
(
euid
>=
container_root_uid
->
hostid
&&
if
(
euid
>=
container_root_uid
->
hostid
&&
euid
<
(
container_root_uid
->
hostid
+
container_root_uid
->
range
))
euid
<
(
container_root_uid
->
hostid
+
container_root_uid
->
range
))
host_uid_map
=
container_root_uid
;
host_uid_map
=
container_root_uid
;
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 namespace gid %d"
,
0
);
return
log_debug
(
NULL
,
"Failed to find mapping for namespace gid %d"
,
0
);
return
NULL
;
}
egid
=
getegid
();
egid
=
getegid
();
if
(
egid
>=
container_root_gid
->
hostid
&&
if
(
egid
>=
container_root_gid
->
hostid
&&
egid
<
(
container_root_gid
->
hostid
+
container_root_gid
->
range
))
egid
<
(
container_root_gid
->
hostid
+
container_root_gid
->
range
))
...
@@ -4292,17 +3968,13 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
...
@@ -4292,17 +3968,13 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
/* 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_uid_map
)
{
if
(
!
host_uid_map
)
DEBUG
(
"Failed to find mapping for uid %d"
,
euid
);
return
log_debug
(
NULL
,
"Failed to find mapping for uid %d"
,
euid
);
return
NULL
;
}
if
(
!
host_gid_map
)
if
(
!
host_gid_map
)
host_gid_map
=
mapped_hostid_add
(
conf
,
egid
,
ID_TYPE_GID
);
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
);
return
log_debug
(
NULL
,
"Failed to find mapping for gid %d"
,
egid
);
return
NULL
;
}
/* Allocate new {g,u}id map list. */
/* Allocate new {g,u}id map list. */
idmap
=
malloc
(
sizeof
(
*
idmap
));
idmap
=
malloc
(
sizeof
(
*
idmap
));
...
@@ -4656,8 +4328,7 @@ static char *getuname(void)
...
@@ -4656,8 +4328,7 @@ static char *getuname(void)
if
(
ret
==
0
)
if
(
ret
==
0
)
WARN
(
"Could not find matched password record."
);
WARN
(
"Could not find matched password record."
);
ERROR
(
"Failed to get password record - %u"
,
geteuid
());
return
log_error
(
NULL
,
"Failed to get password record - %u"
,
geteuid
());
return
NULL
;
}
}
return
strdup
(
pwent
.
pw_name
);
return
strdup
(
pwent
.
pw_name
);
...
@@ -4685,8 +4356,7 @@ static char *getgname(void)
...
@@ -4685,8 +4356,7 @@ static char *getgname(void)
if
(
ret
==
0
)
if
(
ret
==
0
)
WARN
(
"Could not find matched group record"
);
WARN
(
"Could not find matched group record"
);
ERROR
(
"Failed to get group record - %u"
,
getegid
());
return
log_error
(
NULL
,
"Failed to get group record - %u"
,
getegid
());
return
NULL
;
}
}
return
strdup
(
grent
.
gr_name
);
return
strdup
(
grent
.
gr_name
);
...
@@ -4802,9 +4472,9 @@ static void free_cgroup_settings(struct lxc_list *result)
...
@@ -4802,9 +4472,9 @@ static void free_cgroup_settings(struct lxc_list *result)
lxc_list_for_each_safe
(
iterator
,
result
,
next
)
{
lxc_list_for_each_safe
(
iterator
,
result
,
next
)
{
lxc_list_del
(
iterator
);
lxc_list_del
(
iterator
);
free
(
iterator
);
free
_disarm
(
iterator
);
}
}
free
(
result
);
free
_disarm
(
result
);
}
}
/* Return the list of cgroup_settings sorted according to the following rules
/* Return the list of cgroup_settings sorted according to the following rules
...
...
src/lxc/memory_utils.h
View file @
208b3ee0
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
#include <dirent.h>
#include <dirent.h>
#include <errno.h>
#include <errno.h>
#include <mntent.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/types.h>
...
@@ -12,11 +13,35 @@
...
@@ -12,11 +13,35 @@
#include "macro.h"
#include "macro.h"
#define define_cleanup_attribute(type, func) \
static inline void func##_ptr(type *ptr) \
{ \
if (*ptr) \
func(*ptr); \
}
#define free_disarm(ptr) \
({ \
free(ptr); \
move_ptr(ptr); \
})
static
inline
void
__auto_free__
(
void
*
p
)
static
inline
void
__auto_free__
(
void
*
p
)
{
{
free
(
*
(
void
**
)
p
);
free
(
*
(
void
**
)
p
);
}
}
static
inline
void
free_string_list
(
char
**
list
)
{
if
(
list
)
{
for
(
int
i
=
0
;
list
[
i
];
i
++
)
free
(
list
[
i
]);
free_disarm
(
list
);
}
}
define_cleanup_attribute
(
char
**
,
free_string_list
);
#define __do_free_string_list __attribute__((__cleanup__(free_string_list_ptr)))
static
inline
void
__auto_fclose__
(
FILE
**
f
)
static
inline
void
__auto_fclose__
(
FILE
**
f
)
{
{
if
(
*
f
)
if
(
*
f
)
...
@@ -37,12 +62,6 @@ static inline void __auto_closedir__(DIR **d)
...
@@ -37,12 +62,6 @@ static inline void __auto_closedir__(DIR **d)
fd = -EBADF; \
fd = -EBADF; \
}
}
#define free_disarm(ptr) \
({ \
free(ptr); \
move_ptr(ptr); \
})
static
inline
void
__auto_close__
(
int
*
fd
)
static
inline
void
__auto_close__
(
int
*
fd
)
{
{
close_prot_errno_disarm
(
*
fd
);
close_prot_errno_disarm
(
*
fd
);
...
...
src/lxc/pam/pam_cgfs.c
View file @
208b3ee0
...
@@ -77,7 +77,6 @@ static inline void clear_bit(unsigned bit, uint32_t *bitarr)
...
@@ -77,7 +77,6 @@ static inline void clear_bit(unsigned bit, uint32_t *bitarr)
bitarr
[
bit
/
NBITS
]
&=
~
(
1
<<
(
bit
%
NBITS
));
bitarr
[
bit
/
NBITS
]
&=
~
(
1
<<
(
bit
%
NBITS
));
}
}
static
char
*
copy_to_eol
(
char
*
s
);
static
char
*
copy_to_eol
(
char
*
s
);
static
void
free_string_list
(
char
**
list
);
static
char
*
get_mountpoint
(
char
*
line
);
static
char
*
get_mountpoint
(
char
*
line
);
static
bool
get_uid_gid
(
const
char
*
user
,
uid_t
*
uid
,
gid_t
*
gid
);
static
bool
get_uid_gid
(
const
char
*
user
,
uid_t
*
uid
,
gid_t
*
gid
);
static
int
handle_login
(
const
char
*
user
,
uid_t
uid
,
gid_t
gid
);
static
int
handle_login
(
const
char
*
user
,
uid_t
uid
,
gid_t
gid
);
...
@@ -454,16 +453,6 @@ static size_t string_list_length(char **list)
...
@@ -454,16 +453,6 @@ static size_t string_list_length(char **list)
return
len
;
return
len
;
}
}
/* Free null-terminated array of strings. */
static
void
free_string_list
(
char
**
list
)
{
char
**
it
;
for
(
it
=
list
;
it
&&
*
it
;
it
++
)
free
(
*
it
);
free
(
list
);
}
/* Write single integer to file. */
/* Write single integer to file. */
static
bool
write_int
(
char
*
path
,
int
v
)
static
bool
write_int
(
char
*
path
,
int
v
)
{
{
...
...
src/lxc/utils.h
View file @
208b3ee0
...
@@ -73,6 +73,13 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command);
...
@@ -73,6 +73,13 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command);
*/
*/
extern
int
lxc_pclose
(
struct
lxc_popen_FILE
*
fp
);
extern
int
lxc_pclose
(
struct
lxc_popen_FILE
*
fp
);
static
inline
void
__auto_lxc_pclose__
(
struct
lxc_popen_FILE
**
f
)
{
if
(
*
f
)
lxc_pclose
(
*
f
);
}
#define __do_lxc_pclose __attribute__((__cleanup__(__auto_lxc_pclose__)))
/*
/*
* wait on a child we forked
* wait on a child we forked
*/
*/
...
...
src/tests/share_ns.c
View file @
208b3ee0
...
@@ -35,8 +35,8 @@ struct thread_args {
...
@@ -35,8 +35,8 @@ struct thread_args {
int
thread_id
;
int
thread_id
;
bool
success
;
bool
success
;
pid_t
init_pid
;
pid_t
init_pid
;
char
*
inherited_ipc_ns
;
char
inherited_ipc_ns
[
4096
]
;
char
*
inherited_net_ns
;
char
inherited_net_ns
[
4096
]
;
};
};
void
*
ns_sharing_wrapper
(
void
*
data
)
void
*
ns_sharing_wrapper
(
void
*
data
)
...
@@ -45,8 +45,8 @@ void *ns_sharing_wrapper(void *data)
...
@@ -45,8 +45,8 @@ void *ns_sharing_wrapper(void *data)
ssize_t
ret
;
ssize_t
ret
;
char
name
[
100
];
char
name
[
100
];
char
owning_ns_init_pid
[
100
];
char
owning_ns_init_pid
[
100
];
char
proc_ns_path
[
409
6
];
char
proc_ns_path
[
25
6
];
char
ns_buf
[
409
6
];
char
ns_buf
[
25
6
];
struct
lxc_container
*
c
;
struct
lxc_container
*
c
;
struct
thread_args
*
args
=
data
;
struct
thread_args
*
args
=
data
;
...
@@ -162,15 +162,11 @@ void *ns_sharing_wrapper(void *data)
...
@@ -162,15 +162,11 @@ void *ns_sharing_wrapper(void *data)
args
->
success
=
true
;
args
->
success
=
true
;
out:
out:
if
(
c
->
is_running
(
c
)
&&
!
c
->
stop
(
c
))
{
if
(
c
->
is_running
(
c
)
&&
!
c
->
stop
(
c
))
lxc_error
(
"Failed to stop container
\"
%s
\"\n
"
,
name
);
lxc_error
(
"Failed to stop container
\"
%s
\"\n
"
,
name
);
goto
out
;
}
if
(
!
c
->
destroy
(
c
))
{
if
(
!
c
->
destroy
(
c
))
lxc_error
(
"Failed to destroy container
\"
%s
\"\n
"
,
name
);
lxc_error
(
"Failed to destroy container
\"
%s
\"\n
"
,
name
);
goto
out
;
}
pthread_exit
(
NULL
);
pthread_exit
(
NULL
);
return
NULL
;
return
NULL
;
...
@@ -178,16 +174,19 @@ out:
...
@@ -178,16 +174,19 @@ out:
int
main
(
int
argc
,
char
*
argv
[])
int
main
(
int
argc
,
char
*
argv
[])
{
{
struct
thread_args
*
args
=
NULL
;
size_t
nthreads
=
10
;
int
i
,
init_pid
,
j
;
int
i
,
init_pid
,
j
;
char
proc_ns_path
[
4096
];
char
proc_ns_path
[
4096
];
char
ipc_ns_buf
[
4096
];
char
ipc_ns_buf
[
4096
];
char
net_ns_buf
[
4096
];
char
net_ns_buf
[
4096
];
pthread_attr_t
attr
;
pthread_attr_t
attr
;
pthread_t
threads
[
10
];
pthread_t
threads
[
10
];
struct
thread_args
args
[
10
];
struct
lxc_container
*
c
;
struct
lxc_container
*
c
;
int
ret
=
EXIT_FAILURE
;
int
ret
=
EXIT_FAILURE
;
pthread_attr_init
(
&
attr
);
c
=
lxc_container_new
(
"owning-ns"
,
NULL
);
c
=
lxc_container_new
(
"owning-ns"
,
NULL
);
if
(
!
c
)
{
if
(
!
c
)
{
lxc_error
(
"%s"
,
"Failed to create container
\"
owning-ns
\"
"
);
lxc_error
(
"%s"
,
"Failed to create container
\"
owning-ns
\"
"
);
...
@@ -263,24 +262,28 @@ int main(int argc, char *argv[])
...
@@ -263,24 +262,28 @@ int main(int argc, char *argv[])
sleep
(
5
);
sleep
(
5
);
pthread_attr_init
(
&
attr
);
args
=
malloc
(
sizeof
(
struct
thread_args
)
*
nthreads
);
if
(
!
args
)
{
lxc_error
(
"%s
\n
"
,
"Failed to allocate memory"
);
goto
on_error_stop
;
}
for
(
j
=
0
;
j
<
10
;
j
++
)
{
for
(
j
=
0
;
j
<
10
;
j
++
)
{
lxc_debug
(
"Starting namespace sharing test iteration %d
\n
"
,
j
);
lxc_debug
(
"Starting namespace sharing test iteration %d
\n
"
,
j
);
for
(
i
=
0
;
i
<
10
;
i
++
)
{
for
(
i
=
0
;
i
<
nthreads
;
i
++
)
{
args
[
i
].
thread_id
=
i
;
args
[
i
].
thread_id
=
i
;
args
[
i
].
success
=
false
;
args
[
i
].
success
=
false
;
args
[
i
].
init_pid
=
init_pid
;
args
[
i
].
init_pid
=
init_pid
;
args
[
i
].
inherited_ipc_ns
=
ipc_ns_buf
;
memcpy
(
args
[
i
].
inherited_ipc_ns
,
ipc_ns_buf
,
sizeof
(
args
[
i
].
inherited_ipc_ns
))
;
args
[
i
].
inherited_net_ns
=
net_ns_buf
;
memcpy
(
args
[
i
].
inherited_net_ns
,
net_ns_buf
,
sizeof
(
args
[
i
].
inherited_net_ns
))
;
ret
=
pthread_create
(
&
threads
[
i
],
&
attr
,
ns_sharing_wrapper
,
(
void
*
)
&
args
[
i
]);
ret
=
pthread_create
(
&
threads
[
i
],
&
attr
,
ns_sharing_wrapper
,
(
void
*
)
&
args
[
i
]);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
goto
on_error_stop
;
goto
on_error_stop
;
}
}
for
(
i
=
0
;
i
<
10
;
i
++
)
{
for
(
i
=
0
;
i
<
nthreads
;
i
++
)
{
ret
=
pthread_join
(
threads
[
i
],
NULL
);
ret
=
pthread_join
(
threads
[
i
],
NULL
);
if
(
ret
!=
0
)
if
(
ret
!=
0
)
goto
on_error_stop
;
goto
on_error_stop
;
...
@@ -295,6 +298,9 @@ int main(int argc, char *argv[])
...
@@ -295,6 +298,9 @@ int main(int argc, char *argv[])
ret
=
EXIT_SUCCESS
;
ret
=
EXIT_SUCCESS
;
on_error_stop:
on_error_stop:
free
(
args
);
pthread_attr_destroy
(
&
attr
);
if
(
c
->
is_running
(
c
)
&&
!
c
->
stop
(
c
))
if
(
c
->
is_running
(
c
)
&&
!
c
->
stop
(
c
))
lxc_error
(
"%s
\n
"
,
"Failed to stop container
\"
owning-ns
\"
"
);
lxc_error
(
"%s
\n
"
,
"Failed to stop container
\"
owning-ns
\"
"
);
...
@@ -305,5 +311,6 @@ on_error_put:
...
@@ -305,5 +311,6 @@ on_error_put:
lxc_container_put
(
c
);
lxc_container_put
(
c
);
if
(
ret
==
EXIT_SUCCESS
)
if
(
ret
==
EXIT_SUCCESS
)
lxc_debug
(
"%s
\n
"
,
"All state namespace sharing tests passed"
);
lxc_debug
(
"%s
\n
"
,
"All state namespace sharing tests passed"
);
exit
(
ret
);
exit
(
ret
);
}
}
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