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
07f89a4f
Unverified
Commit
07f89a4f
authored
Feb 02, 2021
by
Stéphane Graber
Committed by
GitHub
Feb 02, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3647 from brauner/2021-02-02/fixes
cgroup2: only rely on command socket when getting cgroup values
parents
b22ae843
b7aeda96
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
443 additions
and
96 deletions
+443
-96
attach.c
src/lxc/attach.c
+2
-1
cgfsng.c
src/lxc/cgroups/cgfsng.c
+190
-48
cgroup.h
src/lxc/cgroups/cgroup.h
+7
-0
commands.c
src/lxc/commands.c
+23
-1
commands_utils.c
src/lxc/commands_utils.c
+7
-0
commands_utils.h
src/lxc/commands_utils.h
+3
-0
file_utils.c
src/lxc/file_utils.c
+26
-0
file_utils.h
src/lxc/file_utils.h
+2
-0
freezer.c
src/lxc/freezer.c
+8
-20
lxccontainer.c
src/lxc/lxccontainer.c
+35
-16
lxcseccomp.h
src/lxc/lxcseccomp.h
+12
-0
macro.h
src/lxc/macro.h
+2
-0
seccomp.c
src/lxc/seccomp.c
+0
-1
Makefile.am
src/tests/Makefile.am
+48
-1
cgpath.c
src/tests/cgpath.c
+40
-8
device_add_remove.c
src/tests/device_add_remove.c
+38
-0
No files found.
src/lxc/attach.c
View file @
07f89a4f
...
...
@@ -1208,6 +1208,7 @@ __noreturn static void do_attach(struct attach_payload *ap)
ret
=
lxc_seccomp_send_notifier_fd
(
&
conf
->
seccomp
,
ap
->
ipc_socket
);
if
(
ret
<
0
)
goto
on_error
;
lxc_seccomp_close_notifier_fd
(
&
conf
->
seccomp
);
}
if
(
!
lxc_switch_uid_gid
(
ctx
->
target_ns_uid
,
ctx
->
target_ns_gid
))
...
...
@@ -1522,7 +1523,7 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
* enough.
*/
ret
=
cgroup_attach
(
conf
,
name
,
lxcpath
,
pid
);
if
(
ret
)
{
if
(
ret
==
-
ENOCGROUP2
)
{
call_cleaner
(
cgroup_exit
)
struct
cgroup_ops
*
cgroup_ops
=
NULL
;
cgroup_ops
=
cgroup_init
(
conf
);
...
...
src/lxc/cgroups/cgfsng.c
View file @
07f89a4f
...
...
@@ -37,6 +37,7 @@
#include "cgroup2_devices.h"
#include "cgroup_utils.h"
#include "commands.h"
#include "commands_utils.h"
#include "conf.h"
#include "config.h"
#include "log.h"
...
...
@@ -2026,24 +2027,15 @@ static bool cg_legacy_freeze(struct cgroup_ops *ops)
static
int
freezer_cgroup_events_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
)
{
__do_close
int
duped_fd
=
-
EBADF
;
__do_free
char
*
line
=
NULL
;
__do_fclose
FILE
*
f
=
NULL
;
int
state
=
PTR_TO_INT
(
cbdata
);
size_t
len
;
const
char
*
state_string
;
duped_fd
=
dup
(
fd
);
if
(
duped_fd
<
0
)
return
LXC_MAINLOOP_ERROR
;
if
(
lseek
(
duped_fd
,
0
,
SEEK_SET
)
<
(
off_t
)
-
1
)
return
LXC_MAINLOOP_ERROR
;
f
=
fdopen
(
duped_fd
,
"re"
);
f
=
fdopen_at
(
fd
,
""
,
"re"
,
PROTECT_OPEN
,
PROTECT_LOOKUP_BENEATH
);
if
(
!
f
)
return
LXC_MAINLOOP_ERROR
;
move_fd
(
duped_fd
);
if
(
state
==
1
)
state_string
=
"frozen 1"
;
...
...
@@ -2054,6 +2046,8 @@ static int freezer_cgroup_events_cb(int fd, uint32_t events, void *cbdata,
if
(
strncmp
(
line
,
state_string
,
STRLITERALLEN
(
"frozen"
)
+
2
)
==
0
)
return
LXC_MAINLOOP_CLOSE
;
rewind
(
f
);
return
LXC_MAINLOOP_CONTINUE
;
}
...
...
@@ -2356,42 +2350,6 @@ static int cgroup_unified_attach_parent_wrapper(void *data)
args
->
pid
);
}
int
cgroup_attach
(
const
struct
lxc_conf
*
conf
,
const
char
*
name
,
const
char
*
lxcpath
,
pid_t
pid
)
{
__do_close
int
unified_fd
=
-
EBADF
;
int
ret
;
if
(
!
conf
||
!
name
||
!
lxcpath
||
pid
<=
0
)
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_cgroup2_fd
(
name
,
lxcpath
);
if
(
unified_fd
<
0
)
return
ret_errno
(
EBADF
);
if
(
!
lxc_list_empty
(
&
conf
->
id_map
))
{
struct
userns_exec_unified_attach_data
args
=
{
.
conf
=
conf
,
.
unified_fd
=
unified_fd
,
.
pid
=
pid
,
};
ret
=
socketpair
(
PF_LOCAL
,
SOCK_STREAM
|
SOCK_CLOEXEC
,
0
,
args
.
sk_pair
);
if
(
ret
<
0
)
return
-
errno
;
ret
=
userns_exec_minimal
(
conf
,
cgroup_unified_attach_parent_wrapper
,
&
args
,
cgroup_unified_attach_child_wrapper
,
&
args
);
}
else
{
ret
=
cgroup_attach_leaf
(
conf
,
unified_fd
,
pid
);
}
return
ret
;
}
/* Technically, we're always at a delegation boundary here (This is especially
* true when cgroup namespaces are available.). The reasoning is that in order
* for us to have been able to start a container in the first place the root
...
...
@@ -2664,8 +2622,9 @@ __cgfsng_ops static int cgfsng_set(struct cgroup_ops *ops,
struct
hierarchy
*
h
;
int
ret
=
-
1
;
if
(
!
ops
||
!
key
||
!
value
||
!
name
||
!
lxcpath
)
return
ret_errno
(
ENOENT
);
if
(
!
ops
||
is_empty_string
(
key
)
||
is_empty_string
(
value
)
||
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
return
ret_errno
(
EINVAL
);
controller
=
must_copy_string
(
key
);
p
=
strchr
(
controller
,
'.'
);
...
...
@@ -3500,3 +3459,186 @@ struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
return
move_ptr
(
cgfsng_ops
);
}
int
cgroup_attach
(
const
struct
lxc_conf
*
conf
,
const
char
*
name
,
const
char
*
lxcpath
,
pid_t
pid
)
{
__do_close
int
unified_fd
=
-
EBADF
;
int
ret
;
if
(
!
conf
||
is_empty_string
(
name
)
||
!
is_empty_string
(
lxcpath
)
||
pid
<=
0
)
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_cgroup2_fd
(
name
,
lxcpath
);
if
(
unified_fd
<
0
)
return
ret_errno
(
ENOCGROUP2
);
if
(
!
lxc_list_empty
(
&
conf
->
id_map
))
{
struct
userns_exec_unified_attach_data
args
=
{
.
conf
=
conf
,
.
unified_fd
=
unified_fd
,
.
pid
=
pid
,
};
ret
=
socketpair
(
PF_LOCAL
,
SOCK_STREAM
|
SOCK_CLOEXEC
,
0
,
args
.
sk_pair
);
if
(
ret
<
0
)
return
-
errno
;
ret
=
userns_exec_minimal
(
conf
,
cgroup_unified_attach_parent_wrapper
,
&
args
,
cgroup_unified_attach_child_wrapper
,
&
args
);
}
else
{
ret
=
cgroup_attach_leaf
(
conf
,
unified_fd
,
pid
);
}
return
ret
;
}
/* Connects to command socket therefore isn't callable from command handler. */
int
cgroup_get
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
filename
,
char
*
buf
,
size_t
len
)
{
__do_close
int
unified_fd
=
-
EBADF
;
ssize_t
ret
;
if
(
is_empty_string
(
filename
)
||
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
return
ret_errno
(
EINVAL
);
if
((
buf
&&
!
len
)
||
(
len
&&
!
buf
))
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_limiting_cgroup2_fd
(
name
,
lxcpath
);
if
(
unified_fd
<
0
)
return
ret_errno
(
ENOCGROUP2
);
ret
=
lxc_read_try_buf_at
(
unified_fd
,
filename
,
buf
,
len
);
if
(
ret
<
0
)
SYSERROR
(
"Failed to read cgroup value"
);
return
ret
;
}
/* Connects to command socket therefore isn't callable from command handler. */
int
cgroup_set
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
filename
,
const
char
*
value
)
{
__do_close
int
unified_fd
=
-
EBADF
;
ssize_t
ret
;
if
(
is_empty_string
(
filename
)
||
is_empty_string
(
value
)
||
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_limiting_cgroup2_fd
(
name
,
lxcpath
);
if
(
unified_fd
<
0
)
return
ret_errno
(
ENOCGROUP2
);
if
(
strncmp
(
filename
,
"devices."
,
STRLITERALLEN
(
"devices."
))
==
0
)
{
struct
device_item
device
=
{};
ret
=
device_cgroup_rule_parse
(
&
device
,
filename
,
value
);
if
(
ret
<
0
)
return
log_error_errno
(
-
1
,
EINVAL
,
"Failed to parse device string %s=%s"
,
filename
,
value
);
ret
=
lxc_cmd_add_bpf_device_cgroup
(
name
,
lxcpath
,
&
device
);
}
else
{
ret
=
lxc_writeat
(
unified_fd
,
filename
,
value
,
strlen
(
value
));
}
return
ret
;
}
static
int
do_cgroup_freeze
(
int
unified_fd
,
const
char
*
state_string
,
int
state_num
,
int
timeout
,
const
char
*
epoll_error
,
const
char
*
wait_error
)
{
__do_close
int
events_fd
=
-
EBADF
;
call_cleaner
(
lxc_mainloop_close
)
struct
lxc_epoll_descr
*
descr_ptr
=
NULL
;
int
ret
;
struct
lxc_epoll_descr
descr
=
{};
if
(
timeout
!=
0
)
{
ret
=
lxc_mainloop_open
(
&
descr
);
if
(
ret
)
return
log_error_errno
(
-
1
,
errno
,
"%s"
,
epoll_error
);
/* automatically cleaned up now */
descr_ptr
=
&
descr
;
events_fd
=
open_at
(
unified_fd
,
"cgroup.events"
,
PROTECT_OPEN
,
PROTECT_LOOKUP_BENEATH
,
0
);
if
(
events_fd
<
0
)
return
log_error_errno
(
-
errno
,
errno
,
"Failed to open cgroup.events file"
);
ret
=
lxc_mainloop_add_handler_events
(
&
descr
,
events_fd
,
EPOLLPRI
,
freezer_cgroup_events_cb
,
INT_TO_PTR
(
state_num
));
if
(
ret
<
0
)
return
log_error_errno
(
-
1
,
errno
,
"Failed to add cgroup.events fd handler to mainloop"
);
}
ret
=
lxc_writeat
(
unified_fd
,
"cgroup.freeze"
,
state_string
,
1
);
if
(
ret
<
0
)
return
log_error_errno
(
-
1
,
errno
,
"Failed to open cgroup.freeze file"
);
if
(
timeout
!=
0
)
{
ret
=
lxc_mainloop
(
&
descr
,
timeout
);
if
(
ret
)
return
log_error_errno
(
-
1
,
errno
,
"%s"
,
wait_error
);
}
return
log_trace
(
0
,
"Container now %s"
,
(
state_num
==
1
)
?
"frozen"
:
"unfrozen"
);
}
static
inline
int
__cgroup_freeze
(
int
unified_fd
,
int
timeout
)
{
return
do_cgroup_freeze
(
unified_fd
,
"1"
,
1
,
timeout
,
"Failed to create epoll instance to wait for container freeze"
,
"Failed to wait for container to be frozen"
);
}
int
cgroup_freeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
)
{
__do_close
int
unified_fd
=
-
EBADF
;
int
ret
;
if
(
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_limiting_cgroup2_fd
(
name
,
lxcpath
);
if
(
unified_fd
<
0
)
return
ret_errno
(
ENOCGROUP2
);
lxc_cmd_notify_state_listeners
(
name
,
lxcpath
,
FREEZING
);
ret
=
__cgroup_freeze
(
unified_fd
,
timeout
);
lxc_cmd_notify_state_listeners
(
name
,
lxcpath
,
!
ret
?
FROZEN
:
RUNNING
);
return
ret
;
}
int
__cgroup_unfreeze
(
int
unified_fd
,
int
timeout
)
{
return
do_cgroup_freeze
(
unified_fd
,
"0"
,
0
,
timeout
,
"Failed to create epoll instance to wait for container freeze"
,
"Failed to wait for container to be frozen"
);
}
int
cgroup_unfreeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
)
{
__do_close
int
unified_fd
=
-
EBADF
;
int
ret
;
if
(
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_limiting_cgroup2_fd
(
name
,
lxcpath
);
if
(
unified_fd
<
0
)
return
ret_errno
(
ENOCGROUP2
);
lxc_cmd_notify_state_listeners
(
name
,
lxcpath
,
THAWED
);
ret
=
__cgroup_unfreeze
(
unified_fd
,
timeout
);
lxc_cmd_notify_state_listeners
(
name
,
lxcpath
,
!
ret
?
RUNNING
:
FROZEN
);
return
ret
;
}
src/lxc/cgroups/cgroup.h
View file @
07f89a4f
...
...
@@ -191,6 +191,13 @@ __hidden extern void prune_init_scope(char *cg);
__hidden
extern
int
cgroup_attach
(
const
struct
lxc_conf
*
conf
,
const
char
*
name
,
const
char
*
lxcpath
,
pid_t
pid
);
__hidden
extern
int
cgroup_get
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
filename
,
char
*
buf
,
size_t
len
);
__hidden
extern
int
cgroup_set
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
filename
,
const
char
*
value
);
__hidden
extern
int
cgroup_freeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
);
__hidden
extern
int
cgroup_unfreeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
);
__hidden
extern
int
__cgroup_unfreeze
(
int
unified_fd
,
int
timeout
);
static
inline
bool
pure_unified_layout
(
const
struct
cgroup_ops
*
ops
)
{
...
...
src/lxc/commands.c
View file @
07f89a4f
...
...
@@ -897,7 +897,10 @@ static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
else
TRACE
(
"Sent signal %d to pidfd %d"
,
stopsignal
,
handler
->
pid
);
ret
=
cgroup_ops
->
unfreeze
(
cgroup_ops
,
-
1
);
if
(
pure_unified_layout
(
cgroup_ops
))
ret
=
__cgroup_unfreeze
(
cgroup_ops
->
unified
->
cgfd_limit
,
-
1
);
else
ret
=
cgroup_ops
->
unfreeze
(
cgroup_ops
,
-
1
);
if
(
ret
)
WARN
(
"Failed to unfreeze container
\"
%s
\"
"
,
handler
->
name
);
...
...
@@ -1531,6 +1534,25 @@ int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
return
PTR_TO_INT
(
cmd
.
rsp
.
data
);
}
int
lxc_cmd_get_limiting_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_LIMITING_CGROUP2_FD
,
},
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
return
-
1
;
if
(
cmd
.
rsp
.
ret
<
0
)
return
log_debug_errno
(
cmd
.
rsp
.
ret
,
-
cmd
.
rsp
.
ret
,
"Failed to receive cgroup2 fd"
);
return
PTR_TO_INT
(
cmd
.
rsp
.
data
);
}
static
int
lxc_cmd_get_cgroup2_fd_callback_do
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
,
...
...
src/lxc/commands_utils.c
View file @
07f89a4f
...
...
@@ -190,3 +190,10 @@ int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler,
TRACE
(
"Added state client fd %d to state client list"
,
state_client_fd
);
return
MAX_STATE
;
}
void
lxc_cmd_notify_state_listeners
(
const
char
*
name
,
const
char
*
lxcpath
,
lxc_state_t
state
)
{
(
void
)
lxc_cmd_serve_state_clients
(
name
,
lxcpath
,
state
);
(
void
)
lxc_monitor_send_state
(
name
,
state
,
lxcpath
);
}
src/lxc/commands_utils.h
View file @
07f89a4f
...
...
@@ -62,4 +62,7 @@ __hidden extern int lxc_add_state_client(int state_client_fd, struct lxc_handler
__hidden
extern
int
lxc_cmd_connect
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
,
const
char
*
suffix
);
__hidden
extern
void
lxc_cmd_notify_state_listeners
(
const
char
*
name
,
const
char
*
lxcpath
,
lxc_state_t
state
);
#endif
/* __LXC_COMMANDS_UTILS_H */
src/lxc/file_utils.c
View file @
07f89a4f
...
...
@@ -122,6 +122,32 @@ int lxc_read_from_file(const char *filename, void *buf, size_t count)
return
ret
;
}
ssize_t
lxc_read_try_buf_at
(
int
dfd
,
const
char
*
path
,
void
*
buf
,
size_t
count
)
{
__do_close
int
fd
=
-
EBADF
;
ssize_t
ret
;
fd
=
open_at
(
dfd
,
path
,
PROTECT_OPEN_W
,
PROTECT_LOOKUP_BENEATH
,
0
);
if
(
fd
<
0
)
return
-
errno
;
if
(
!
buf
||
!
count
)
{
char
buf2
[
100
];
size_t
count2
=
0
;
while
((
ret
=
lxc_read_nointr
(
fd
,
buf2
,
100
))
>
0
)
count2
+=
ret
;
if
(
ret
>=
0
)
ret
=
count2
;
}
else
{
memset
(
buf
,
0
,
count
);
ret
=
lxc_read_nointr
(
fd
,
buf
,
count
);
}
return
ret
;
}
ssize_t
lxc_write_nointr
(
int
fd
,
const
void
*
buf
,
size_t
count
)
{
ssize_t
ret
;
...
...
src/lxc/file_utils.h
View file @
07f89a4f
...
...
@@ -94,5 +94,7 @@ __hidden int fd_make_nonblocking(int fd);
__hidden
extern
char
*
read_file_at
(
int
dfd
,
const
char
*
fnam
,
unsigned
int
o_flags
,
unsigned
resolve_flags
);
__hidden
extern
ssize_t
lxc_read_try_buf_at
(
int
dfd
,
const
char
*
path
,
void
*
buf
,
size_t
count
);
#endif
/* __LXC_FILE_UTILS_H */
src/lxc/freezer.c
View file @
07f89a4f
...
...
@@ -15,6 +15,7 @@
#include "cgroups/cgroup.h"
#include "cgroups/cgroup_utils.h"
#include "commands.h"
#include "commands_utils.h"
#include "config.h"
#include "error.h"
#include "log.h"
...
...
@@ -25,13 +26,6 @@
lxc_log_define
(
freezer
,
lxc
);
static
void
notify_state_listeners
(
const
char
*
name
,
const
char
*
lxcpath
,
lxc_state_t
state
)
{
(
void
)
lxc_cmd_serve_state_clients
(
name
,
lxcpath
,
state
);
(
void
)
lxc_monitor_send_state
(
name
,
state
,
lxcpath
);
}
static
int
do_freeze_thaw
(
bool
freeze
,
struct
lxc_conf
*
conf
,
const
char
*
name
,
const
char
*
lxcpath
)
{
...
...
@@ -64,7 +58,7 @@ static int do_freeze_thaw(bool freeze, struct lxc_conf *conf, const char *name,
cur_state
[
lxc_char_right_gc
(
cur_state
,
strlen
(
cur_state
))]
=
'\0'
;
ret
=
strncmp
(
cur_state
,
state
,
state_len
);
if
(
ret
==
0
)
{
notify_state_listeners
(
name
,
lxcpath
,
new_state
);
lxc_cmd_
notify_state_listeners
(
name
,
lxcpath
,
new_state
);
return
0
;
}
...
...
@@ -78,12 +72,9 @@ int lxc_freeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
{
int
ret
;
notify_state_listeners
(
name
,
lxcpath
,
FREEZING
);
if
(
unified_cgroup_hierarchy
()
>
0
)
ret
=
lxc_cmd_freeze
(
name
,
lxcpath
,
-
1
);
else
ret
=
do_freeze_thaw
(
true
,
conf
,
name
,
lxcpath
);
notify_state_listeners
(
name
,
lxcpath
,
!
ret
?
FROZEN
:
RUNNING
);
lxc_cmd_notify_state_listeners
(
name
,
lxcpath
,
FREEZING
);
ret
=
do_freeze_thaw
(
true
,
conf
,
name
,
lxcpath
);
lxc_cmd_notify_state_listeners
(
name
,
lxcpath
,
!
ret
?
FROZEN
:
RUNNING
);
return
ret
;
}
...
...
@@ -91,11 +82,8 @@ int lxc_unfreeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
{
int
ret
;
notify_state_listeners
(
name
,
lxcpath
,
THAWED
);
if
(
unified_cgroup_hierarchy
()
>
0
)
ret
=
lxc_cmd_unfreeze
(
name
,
lxcpath
,
-
1
);
else
ret
=
do_freeze_thaw
(
false
,
conf
,
name
,
lxcpath
);
notify_state_listeners
(
name
,
lxcpath
,
!
ret
?
RUNNING
:
FROZEN
);
lxc_cmd_notify_state_listeners
(
name
,
lxcpath
,
THAWED
);
ret
=
do_freeze_thaw
(
false
,
conf
,
name
,
lxcpath
);
lxc_cmd_notify_state_listeners
(
name
,
lxcpath
,
!
ret
?
RUNNING
:
FROZEN
);
return
ret
;
}
src/lxc/lxccontainer.c
View file @
07f89a4f
...
...
@@ -507,32 +507,41 @@ WRAP_API(bool, lxcapi_is_running)
static
bool
do_lxcapi_freeze
(
struct
lxc_container
*
c
)
{
int
ret
=
0
;
lxc_state_t
s
;
if
(
!
c
||
!
c
->
lxc_conf
)
return
false
;
s
=
lxc_getstate
(
c
->
name
,
c
->
config_path
);
if
(
s
!=
FROZEN
)
return
lxc_freeze
(
c
->
lxc_conf
,
c
->
name
,
c
->
config_path
)
==
0
;
if
(
s
!=
FROZEN
)
{
ret
=
cgroup_freeze
(
c
->
name
,
c
->
config_path
,
-
1
);
if
(
ret
==
-
ENOCGROUP2
)
ret
=
lxc_freeze
(
c
->
lxc_conf
,
c
->
name
,
c
->
config_path
);
}
return
true
;
return
ret
==
0
;
}
WRAP_API
(
bool
,
lxcapi_freeze
)
static
bool
do_lxcapi_unfreeze
(
struct
lxc_container
*
c
)
{
int
ret
=
0
;
lxc_state_t
s
;
if
(
!
c
||
!
c
->
lxc_conf
)
return
false
;
s
=
lxc_getstate
(
c
->
name
,
c
->
config_path
);
if
(
s
==
FROZEN
)
return
lxc_unfreeze
(
c
->
lxc_conf
,
c
->
name
,
c
->
config_path
)
==
0
;
if
(
s
==
FROZEN
)
{
ret
=
cgroup_unfreeze
(
c
->
name
,
c
->
config_path
,
-
1
);
if
(
ret
==
-
ENOCGROUP2
)
ret
=
lxc_unfreeze
(
c
->
lxc_conf
,
c
->
name
,
c
->
config_path
);
}
return
true
;
return
ret
==
0
;
}
WRAP_API
(
bool
,
lxcapi_unfreeze
)
...
...
@@ -3277,6 +3286,7 @@ WRAP_API_1(bool, lxcapi_set_config_path, const char *)
static
bool
do_lxcapi_set_cgroup_item
(
struct
lxc_container
*
c
,
const
char
*
subsys
,
const
char
*
value
)
{
call_cleaner
(
cgroup_exit
)
struct
cgroup_ops
*
cgroup_ops
=
NULL
;
int
ret
;
if
(
!
c
)
return
false
;
...
...
@@ -3284,12 +3294,16 @@ static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsy
if
(
is_stopped
(
c
))
return
false
;
cgroup_ops
=
cgroup_init
(
c
->
lxc_conf
);
if
(
!
cgroup_ops
)
return
false
;
ret
=
cgroup_set
(
c
->
name
,
c
->
config_path
,
subsys
,
value
);
if
(
ret
==
-
ENOCGROUP2
)
{
cgroup_ops
=
cgroup_init
(
c
->
lxc_conf
);
if
(
!
cgroup_ops
)
return
false
;
ret
=
cgroup_ops
->
set
(
cgroup_ops
,
subsys
,
value
,
c
->
name
,
c
->
config_path
);
}
return
cgroup_ops
->
set
(
cgroup_ops
,
subsys
,
value
,
c
->
name
,
c
->
config_path
)
==
0
;
return
ret
==
0
;
}
WRAP_API_2
(
bool
,
lxcapi_set_cgroup_item
,
const
char
*
,
const
char
*
)
...
...
@@ -3297,6 +3311,7 @@ WRAP_API_2(bool, lxcapi_set_cgroup_item, const char *, const char *)
static
int
do_lxcapi_get_cgroup_item
(
struct
lxc_container
*
c
,
const
char
*
subsys
,
char
*
retv
,
int
inlen
)
{
call_cleaner
(
cgroup_exit
)
struct
cgroup_ops
*
cgroup_ops
=
NULL
;
int
ret
;
if
(
!
c
)
return
-
1
;
...
...
@@ -3304,12 +3319,16 @@ static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys
if
(
is_stopped
(
c
))
return
-
1
;
cgroup_ops
=
cgroup_init
(
c
->
lxc_conf
);
if
(
!
cgroup_ops
)
return
-
1
;
ret
=
cgroup_get
(
c
->
name
,
c
->
config_path
,
subsys
,
retv
,
inlen
);
if
(
ret
==
-
ENOCGROUP2
)
{
cgroup_ops
=
cgroup_init
(
c
->
lxc_conf
);
if
(
!
cgroup_ops
)
return
-
1
;
return
cgroup_ops
->
get
(
cgroup_ops
,
subsys
,
retv
,
inlen
,
c
->
name
,
c
->
config_path
);
return
cgroup_ops
->
get
(
cgroup_ops
,
subsys
,
retv
,
inlen
,
c
->
name
,
c
->
config_path
);
}
return
ret
;
}
WRAP_API_3
(
int
,
lxcapi_get_cgroup_item
,
const
char
*
,
char
*
,
int
)
...
...
src/lxc/lxcseccomp.h
View file @
07f89a4f
...
...
@@ -91,6 +91,14 @@ __hidden extern int lxc_seccomp_send_notifier_fd(struct lxc_seccomp *seccomp, in
__hidden
extern
int
lxc_seccomp_recv_notifier_fd
(
struct
lxc_seccomp
*
seccomp
,
int
socket_fd
);
__hidden
extern
int
lxc_seccomp_add_notifier
(
const
char
*
name
,
const
char
*
lxcpath
,
struct
lxc_seccomp
*
seccomp
);
static
inline
void
lxc_seccomp_close_notifier_fd
(
struct
lxc_seccomp
*
seccomp
)
{
#if HAVE_DECL_SECCOMP_NOTIFY_FD
if
(
seccomp
->
notifier
.
wants_supervision
)
close_prot_errno_disarm
(
seccomp
->
notifier
.
notify_fd
);
#endif
}
static
inline
int
lxc_seccomp_get_notify_fd
(
struct
lxc_seccomp
*
seccomp
)
{
#if HAVE_DECL_SECCOMP_NOTIFY_FD
...
...
@@ -162,5 +170,9 @@ static inline int lxc_seccomp_get_notify_fd(struct lxc_seccomp *seccomp)
return
-
EBADF
;
}
static
inline
void
lxc_seccomp_close_notifier_fd
(
struct
lxc_seccomp
*
seccomp
)
{
}
#endif
/* HAVE_SECCOMP */
#endif
/* __LXC_LXCSECCOMP_H */
src/lxc/macro.h
View file @
07f89a4f
...
...
@@ -670,4 +670,6 @@ enum {
#endif
#endif
#define ENOCGROUP2 ENOMEDIUM
#endif
/* __LXC_MACRO_H */
src/lxc/seccomp.c
View file @
07f89a4f
...
...
@@ -1638,7 +1638,6 @@ int lxc_seccomp_recv_notifier_fd(struct lxc_seccomp *seccomp, int socket_fd)
int
lxc_seccomp_add_notifier
(
const
char
*
name
,
const
char
*
lxcpath
,
struct
lxc_seccomp
*
seccomp
)
{
#if HAVE_DECL_SECCOMP_NOTIFY_FD
if
(
seccomp
->
notifier
.
wants_supervision
)
{
int
ret
;
...
...
src/tests/Makefile.am
View file @
07f89a4f
...
...
@@ -275,7 +275,54 @@ lxc_test_createtest_SOURCES = createtest.c
lxc_test_criu_check_feature_SOURCES
=
criu_check_feature.c lxctest.h
lxc_test_cve_2019_5736_SOURCES
=
cve-2019-5736.c lxctest.h
lxc_test_destroytest_SOURCES
=
destroytest.c
lxc_test_device_add_remove_SOURCES
=
device_add_remove.c
lxc_test_device_add_remove_SOURCES
=
device_add_remove.c
\
../lxc/af_unix.c ../lxc/af_unix.h
\
../lxc/caps.c ../lxc/caps.h
\
../lxc/cgroups/cgfsng.c
\
../lxc/cgroups/cgroup.c ../lxc/cgroups/cgroup.h
\
../lxc/cgroups/cgroup2_devices.c ../lxc/cgroups/cgroup2_devices.h
\
../lxc/cgroups/cgroup_utils.c ../lxc/cgroups/cgroup_utils.h
\
../lxc/commands.c ../lxc/commands.h
\
../lxc/commands_utils.c ../lxc/commands_utils.h
\
../lxc/conf.c ../lxc/conf.h
\
../lxc/confile.c ../lxc/confile.h
\
../lxc/confile_utils.c ../lxc/confile_utils.h
\
../lxc/error.c ../lxc/error.h
\
../lxc/file_utils.c ../lxc/file_utils.h
\
../include/netns_ifaddrs.c ../include/netns_ifaddrs.h
\
../lxc/initutils.c ../lxc/initutils.h
\
../lxc/log.c ../lxc/log.h
\
../lxc/lxclock.c ../lxc/lxclock.h
\
../lxc/mainloop.c ../lxc/mainloop.h
\
../lxc/monitor.c ../lxc/monitor.h
\
../lxc/namespace.c ../lxc/namespace.h
\
../lxc/network.c ../lxc/network.h
\
../lxc/nl.c ../lxc/nl.h
\
../lxc/parse.c ../lxc/parse.h
\
../lxc/process_utils.c ../lxc/process_utils.h
\
../lxc/ringbuf.c ../lxc/ringbuf.h
\
../lxc/start.c ../lxc/start.h
\
../lxc/state.c ../lxc/state.h
\
../lxc/storage/btrfs.c ../lxc/storage/btrfs.h
\
../lxc/storage/dir.c ../lxc/storage/dir.h
\
../lxc/storage/loop.c ../lxc/storage/loop.h
\
../lxc/storage/lvm.c ../lxc/storage/lvm.h
\
../lxc/storage/nbd.c ../lxc/storage/nbd.h
\
../lxc/storage/overlay.c ../lxc/storage/overlay.h
\
../lxc/storage/rbd.c ../lxc/storage/rbd.h
\
../lxc/storage/rsync.c ../lxc/storage/rsync.h
\
../lxc/storage/storage.c ../lxc/storage/storage.h
\
../lxc/storage/storage_utils.c ../lxc/storage/storage_utils.h
\
../lxc/storage/zfs.c ../lxc/storage/zfs.h
\
../lxc/sync.c ../lxc/sync.h
\
../lxc/string_utils.c ../lxc/string_utils.h
\
../lxc/terminal.c ../lxc/terminal.h
\
../lxc/utils.c ../lxc/utils.h
\
../lxc/uuid.c ../lxc/uuid.h
\
$(LSM_SOURCES)
if
ENABLE_SECCOMP
lxc_test_device_add_remove_SOURCES
+=
../lxc/seccomp.c ../lxc/lxcseccomp.h
endif
lxc_test_getkeys_SOURCES
=
getkeys.c
lxc_test_get_item_SOURCES
=
get_item.c
lxc_test_list_SOURCES
=
list.c
...
...
src/tests/cgpath.c
View file @
07f89a4f
...
...
@@ -30,8 +30,10 @@
#include <sys/stat.h>
#include "cgroup.h"
#include "lxc.h"
#include "commands.h"
#include "lxc.h"
#include "lxctest.h"
#include "utils.h"
#ifndef HAVE_STRLCPY
#include "include/strlcpy.h"
...
...
@@ -50,13 +52,32 @@
*/
static
int
test_running_container
(
const
char
*
lxcpath
,
const
char
*
name
)
{
__do_close
int
fd_log
=
-
EBADF
;
int
ret
=
-
1
;
struct
lxc_container
*
c
=
NULL
;
struct
lxc_log
log
=
{};
char
template
[
sizeof
(
P_tmpdir
"/attach_XXXXXX"
)];
char
*
cgrelpath
;
char
relpath
[
PATH_MAX
+
1
];
char
value
[
NAME_MAX
],
value_save
[
NAME_MAX
];
struct
cgroup_ops
*
cgroup_ops
;
(
void
)
strlcpy
(
template
,
P_tmpdir
"/attach_XXXXXX"
,
sizeof
(
template
));
fd_log
=
lxc_make_tmpfile
(
template
,
false
);
if
(
fd_log
<
0
)
{
lxc_error
(
"Failed to create temporary log file for container %s
\n
"
,
name
);
exit
(
EXIT_FAILURE
);
}
log
.
name
=
name
;
log
.
file
=
template
;
log
.
level
=
"TRACE"
;
log
.
prefix
=
"cgpath"
;
log
.
quiet
=
false
;
log
.
lxcpath
=
NULL
;
if
(
lxc_log_init
(
&
log
))
goto
err1
;
sprintf
(
relpath
,
DEFAULT_PAYLOAD_CGROUP_PREFIX
"%s"
,
name
);
if
((
c
=
lxc_container_new
(
name
,
lxcpath
))
==
NULL
)
{
...
...
@@ -83,33 +104,33 @@ static int test_running_container(const char *lxcpath, const char *name)
goto
err3
;
/* test get/set value using memory.soft_limit_in_bytes file */
ret
=
cgroup_ops
->
get
(
cgroup_ops
,
"
memory.soft_limit_in_bytes"
,
value
,
sizeof
(
value
),
c
->
name
,
c
->
config_path
);
if
(
ret
<
0
)
{
ret
=
cgroup_ops
->
get
(
cgroup_ops
,
"
pids.max"
,
value
,
sizeof
(
value
)
,
c
->
name
,
c
->
config_path
);
if
(
ret
<
0
)
{
TSTERR
(
"cgroup_get failed"
);
goto
err3
;
}
(
void
)
strlcpy
(
value_save
,
value
,
NAME_MAX
);
ret
=
cgroup_ops
->
set
(
cgroup_ops
,
"
memory.soft_limit_in_bytes"
,
"512M
"
,
ret
=
cgroup_ops
->
set
(
cgroup_ops
,
"
pids.max"
,
"10000
"
,
c
->
name
,
c
->
config_path
);
if
(
ret
<
0
)
{
TSTERR
(
"cgroup_set failed %d %d"
,
ret
,
errno
);
goto
err3
;
}
ret
=
cgroup_ops
->
get
(
cgroup_ops
,
"
memory.soft_limit_in_bytes
"
,
value
,
ret
=
cgroup_ops
->
get
(
cgroup_ops
,
"
pids.max
"
,
value
,
sizeof
(
value
),
c
->
name
,
c
->
config_path
);
if
(
ret
<
0
)
{
TSTERR
(
"cgroup_get failed"
);
goto
err3
;
}
if
(
strcmp
(
value
,
"
536870912
\n
"
))
{
if
(
strcmp
(
value
,
"
10000
\n
"
))
{
TSTERR
(
"cgroup_set_bypath failed to set value >%s<"
,
value
);
goto
err3
;
}
/* restore original value */
ret
=
cgroup_ops
->
set
(
cgroup_ops
,
"
memory.soft_limit_in_bytes
"
,
ret
=
cgroup_ops
->
set
(
cgroup_ops
,
"
pids.max
"
,
value_save
,
c
->
name
,
c
->
config_path
);
if
(
ret
<
0
)
{
TSTERR
(
"cgroup_set failed"
);
...
...
@@ -123,6 +144,17 @@ err3:
err2:
lxc_container_put
(
c
);
err1:
if
(
ret
!=
0
)
{
char
buf
[
4096
];
ssize_t
buflen
;
while
((
buflen
=
read
(
fd_log
,
buf
,
1024
))
>
0
)
{
buflen
=
write
(
STDERR_FILENO
,
buf
,
buflen
);
if
(
buflen
<=
0
)
break
;
}
}
(
void
)
unlink
(
template
);
return
ret
;
}
...
...
src/tests/device_add_remove.c
View file @
07f89a4f
...
...
@@ -20,14 +20,41 @@
#include <stdlib.h>
#include <lxc/lxccontainer.h>
#include "lxctest.h"
#include "memory_utils.h"
#include "utils.h"
#ifndef HAVE_STRLCPY
#include "include/strlcpy.h"
#endif
#define NAME "device_add_remove_test"
#define DEVICE "/dev/loop-control"
int
main
(
int
argc
,
char
*
argv
[])
{
__do_close
int
fd_log
=
-
EBADF
;
int
ret
=
1
;
struct
lxc_log
log
=
{};
char
template
[
sizeof
(
P_tmpdir
"/attach_XXXXXX"
)];
struct
lxc_container
*
c
;
(
void
)
strlcpy
(
template
,
P_tmpdir
"/attach_XXXXXX"
,
sizeof
(
template
));
fd_log
=
lxc_make_tmpfile
(
template
,
false
);
if
(
fd_log
<
0
)
{
lxc_error
(
"Failed to create temporary log file for container %s
\n
"
,
NAME
);
exit
(
EXIT_FAILURE
);
}
log
.
name
=
NAME
;
log
.
file
=
template
;
log
.
level
=
"TRACE"
;
log
.
prefix
=
"device_add_remove"
;
log
.
quiet
=
false
;
log
.
lxcpath
=
NULL
;
if
(
lxc_log_init
(
&
log
))
goto
out
;
c
=
lxc_container_new
(
NAME
,
NULL
);
if
(
!
c
)
{
fprintf
(
stderr
,
"Unable to instantiate container (%s)...
\n
"
,
NAME
);
...
...
@@ -69,6 +96,17 @@ int main(int argc, char *argv[])
ret
=
0
;
out:
if
(
ret
!=
0
)
{
char
buf
[
4096
];
ssize_t
buflen
;
while
((
buflen
=
read
(
fd_log
,
buf
,
1024
))
>
0
)
{
buflen
=
write
(
STDERR_FILENO
,
buf
,
buflen
);
if
(
buflen
<=
0
)
break
;
}
}
(
void
)
unlink
(
template
);
lxc_container_put
(
c
);
return
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