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
2ed90529
Unverified
Commit
2ed90529
authored
Feb 24, 2021
by
Stéphane Graber
Committed by
GitHub
Feb 24, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3694 from brauner/2021-02-24/fixes_2
commands: rework and add LXC_CMD_GET_CGROUP_FD and LXC_CMD_GET_LIMIT_CGROUP_FD
parents
5dc90afd
7e85a2c4
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
548 additions
and
186 deletions
+548
-186
Makefile.am
src/lxc/Makefile.am
+2
-0
attach.c
src/lxc/attach.c
+1
-1
cgfsng.c
src/lxc/cgroups/cgfsng.c
+122
-38
cgroup.h
src/lxc/cgroups/cgroup.h
+33
-6
commands.c
src/lxc/commands.c
+258
-85
commands.h
src/lxc/commands.h
+19
-8
criu.c
src/lxc/criu.c
+6
-6
error_utils.h
src/lxc/error_utils.h
+101
-0
file_utils.c
src/lxc/file_utils.c
+1
-1
lxccontainer.c
src/lxc/lxccontainer.c
+2
-2
macro.h
src/lxc/macro.h
+0
-37
memory_utils.h
src/lxc/memory_utils.h
+1
-0
terminal.c
src/lxc/terminal.c
+2
-2
No files found.
src/lxc/Makefile.am
View file @
2ed90529
...
@@ -18,6 +18,7 @@ noinst_HEADERS = api_extensions.h \
...
@@ -18,6 +18,7 @@ noinst_HEADERS = api_extensions.h \
confile_utils.h
\
confile_utils.h
\
criu.h
\
criu.h
\
error.h
\
error.h
\
error_utils.h
\
file_utils.h
\
file_utils.h
\
../include/netns_ifaddrs.h
\
../include/netns_ifaddrs.h
\
initutils.h
\
initutils.h
\
...
@@ -117,6 +118,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
...
@@ -117,6 +118,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
criu.c criu.h
\
criu.c criu.h
\
error.c error.h
\
error.c error.h
\
execute.c
\
execute.c
\
error_utils.h
\
freezer.c
\
freezer.c
\
file_utils.c file_utils.h
\
file_utils.c file_utils.h
\
../include/netns_ifaddrs.c ../include/netns_ifaddrs.h
\
../include/netns_ifaddrs.c ../include/netns_ifaddrs.h
\
...
...
src/lxc/attach.c
View file @
2ed90529
...
@@ -1641,7 +1641,7 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
...
@@ -1641,7 +1641,7 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
ret
=
cgroup_attach
(
conf
,
name
,
lxcpath
,
pid
);
ret
=
cgroup_attach
(
conf
,
name
,
lxcpath
,
pid
);
if
(
ret
)
{
if
(
ret
)
{
call_cleaner
(
cgroup_exit
)
struct
cgroup_ops
*
cgroup_ops
=
NULL
;
call_cleaner
(
cgroup_exit
)
struct
cgroup_ops
*
cgroup_ops
=
NULL
;
if
(
ret
!=
-
ENOCGROUP2
&&
ret
!=
-
ENOSYS
)
{
if
(
!
ERRNO_IS_NOT_SUPPORTED
(
ret
)
)
{
SYSERROR
(
"Failed to attach cgroup"
);
SYSERROR
(
"Failed to attach cgroup"
);
goto
on_error
;
goto
on_error
;
}
}
...
...
src/lxc/cgroups/cgfsng.c
View file @
2ed90529
...
@@ -40,6 +40,7 @@
...
@@ -40,6 +40,7 @@
#include "commands_utils.h"
#include "commands_utils.h"
#include "conf.h"
#include "conf.h"
#include "config.h"
#include "config.h"
#include "error_utils.h"
#include "log.h"
#include "log.h"
#include "macro.h"
#include "macro.h"
#include "mainloop.h"
#include "mainloop.h"
...
@@ -103,7 +104,7 @@ static bool string_in_list(char **list, const char *entry)
...
@@ -103,7 +104,7 @@ static bool string_in_list(char **list, const char *entry)
/* Given a handler's cgroup data, return the struct hierarchy for the controller
/* Given a handler's cgroup data, return the struct hierarchy for the controller
* @c, or NULL if there is none.
* @c, or NULL if there is none.
*/
*/
static
struct
hierarchy
*
get_hierarchy
(
struct
cgroup_ops
*
ops
,
const
char
*
controller
)
static
struct
hierarchy
*
get_hierarchy
(
const
struct
cgroup_ops
*
ops
,
const
char
*
controller
)
{
{
if
(
!
ops
->
hierarchies
)
if
(
!
ops
->
hierarchies
)
return
log_trace_errno
(
NULL
,
errno
,
"There are no useable cgroup controllers"
);
return
log_trace_errno
(
NULL
,
errno
,
"There are no useable cgroup controllers"
);
...
@@ -147,6 +148,38 @@ static struct hierarchy *get_hierarchy(struct cgroup_ops *ops, const char *contr
...
@@ -147,6 +148,38 @@ static struct hierarchy *get_hierarchy(struct cgroup_ops *ops, const char *contr
return
ret_set_errno
(
NULL
,
ENOENT
);
return
ret_set_errno
(
NULL
,
ENOENT
);
}
}
int
prepare_cgroup_fd
(
const
struct
cgroup_ops
*
ops
,
struct
cgroup_fd
*
fd
,
bool
limit
)
{
int
dfd
;
const
struct
hierarchy
*
h
;
h
=
get_hierarchy
(
ops
,
fd
->
controller
);
if
(
!
h
)
return
ret_errno
(
ENOENT
);
/*
* The client requested that the controller must be in a specific
* cgroup version.
*/
if
(
fd
->
type
!=
0
&&
fd
->
type
!=
h
->
fs_type
)
return
ret_errno
(
EINVAL
);
if
(
limit
)
dfd
=
h
->
dfd_con
;
else
dfd
=
h
->
dfd_lim
;
if
(
dfd
<
0
)
return
ret_errno
(
EBADF
);
fd
->
layout
=
ops
->
cgroup_layout
;
fd
->
type
=
h
->
fs_type
;
if
(
fd
->
type
==
UNIFIED_HIERARCHY
)
fd
->
utilities
=
h
->
utilities
;
fd
->
fd
=
dfd
;
return
0
;
}
/* Taken over modified from the kernel sources. */
/* Taken over modified from the kernel sources. */
#define NBITS 32
/* bits in uint32_t */
#define NBITS 32
/* bits in uint32_t */
#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
...
@@ -2057,7 +2090,7 @@ __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops,
...
@@ -2057,7 +2090,7 @@ __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops,
return
cgfsng_get_cgroup_do
(
ops
,
controller
,
false
);
return
cgfsng_get_cgroup_do
(
ops
,
controller
,
false
);
}
}
__cgfsng_ops
static
const
char
*
cgfsng_get_limit
ing
_cgroup
(
struct
cgroup_ops
*
ops
,
__cgfsng_ops
static
const
char
*
cgfsng_get_limit_cgroup
(
struct
cgroup_ops
*
ops
,
const
char
*
controller
)
const
char
*
controller
)
{
{
return
cgfsng_get_cgroup_do
(
ops
,
controller
,
true
);
return
cgfsng_get_cgroup_do
(
ops
,
controller
,
true
);
...
@@ -2369,7 +2402,7 @@ __cgfsng_ops static int cgfsng_get(struct cgroup_ops *ops, const char *filename,
...
@@ -2369,7 +2402,7 @@ __cgfsng_ops static int cgfsng_get(struct cgroup_ops *ops, const char *filename,
if
(
p
)
if
(
p
)
*
p
=
'\0'
;
*
p
=
'\0'
;
path
=
lxc_cmd_get_limit
ing
_cgroup_path
(
name
,
lxcpath
,
controller
);
path
=
lxc_cmd_get_limit_cgroup_path
(
name
,
lxcpath
,
controller
);
/* not running */
/* not running */
if
(
!
path
)
if
(
!
path
)
return
-
1
;
return
-
1
;
...
@@ -2531,7 +2564,7 @@ __cgfsng_ops static int cgfsng_set(struct cgroup_ops *ops,
...
@@ -2531,7 +2564,7 @@ __cgfsng_ops static int cgfsng_set(struct cgroup_ops *ops,
return
0
;
return
0
;
}
}
path
=
lxc_cmd_get_limit
ing
_cgroup_path
(
name
,
lxcpath
,
controller
);
path
=
lxc_cmd_get_limit_cgroup_path
(
name
,
lxcpath
,
controller
);
/* not running */
/* not running */
if
(
!
path
)
if
(
!
path
)
return
-
1
;
return
-
1
;
...
@@ -3336,7 +3369,7 @@ struct cgroup_ops *cgroup_ops_init(struct lxc_conf *conf)
...
@@ -3336,7 +3369,7 @@ struct cgroup_ops *cgroup_ops_init(struct lxc_conf *conf)
cgfsng_ops
->
chown
=
cgfsng_chown
;
cgfsng_ops
->
chown
=
cgfsng_chown
;
cgfsng_ops
->
mount
=
cgfsng_mount
;
cgfsng_ops
->
mount
=
cgfsng_mount
;
cgfsng_ops
->
devices_activate
=
cgfsng_devices_activate
;
cgfsng_ops
->
devices_activate
=
cgfsng_devices_activate
;
cgfsng_ops
->
get_limit
ing_cgroup
=
cgfsng_get_limiting
_cgroup
;
cgfsng_ops
->
get_limit
_cgroup
=
cgfsng_get_limit
_cgroup
;
cgfsng_ops
->
criu_escape
=
cgfsng_criu_escape
;
cgfsng_ops
->
criu_escape
=
cgfsng_criu_escape
;
cgfsng_ops
->
criu_num_hierarchies
=
cgfsng_criu_num_hierarchies
;
cgfsng_ops
->
criu_num_hierarchies
=
cgfsng_criu_num_hierarchies
;
...
@@ -3377,12 +3410,11 @@ static int __cgroup_attach_many(const struct lxc_conf *conf, const char *name,
...
@@ -3377,12 +3410,11 @@ static int __cgroup_attach_many(const struct lxc_conf *conf, const char *name,
{
{
call_cleaner
(
put_cgroup_ctx
)
struct
cgroup_ctx
*
ctx
=
&
(
struct
cgroup_ctx
){};
call_cleaner
(
put_cgroup_ctx
)
struct
cgroup_ctx
*
ctx
=
&
(
struct
cgroup_ctx
){};
int
ret
;
int
ret
;
char
pidstr
[
INTTYPE_TO_STRLEN
(
pid_t
)];
size_t
idx
;
size_t
idx
;
ssize_t
pidstr_len
;
ssize_t
pidstr_len
;
char
pidstr
[
INTTYPE_TO_STRLEN
(
pid_t
)];
ret
=
lxc_cmd_get_cgroup_ctx
(
name
,
lxcpath
,
NULL
,
true
,
ret
=
lxc_cmd_get_cgroup_ctx
(
name
,
lxcpath
,
sizeof
(
struct
cgroup_ctx
),
ctx
);
sizeof
(
struct
cgroup_ctx
),
ctx
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret_errno
(
ENOSYS
);
return
ret_errno
(
ENOSYS
);
...
@@ -3406,7 +3438,7 @@ static int __cgroup_attach_many(const struct lxc_conf *conf, const char *name,
...
@@ -3406,7 +3438,7 @@ static int __cgroup_attach_many(const struct lxc_conf *conf, const char *name,
if
(
idx
==
0
)
if
(
idx
==
0
)
return
syserrno_set
(
-
ENOENT
,
"Failed to attach to cgroups"
);
return
syserrno_set
(
-
ENOENT
,
"Failed to attach to cgroups"
);
TRACE
(
"Attached to %s cgroup layout"
,
cgroup_layout_name
(
ctx
->
cgroup_
layout
));
TRACE
(
"Attached to %s cgroup layout"
,
cgroup_layout_name
(
ctx
->
layout
));
return
0
;
return
0
;
}
}
...
@@ -3420,7 +3452,7 @@ static int __cgroup_attach_unified(const struct lxc_conf *conf, const char *name
...
@@ -3420,7 +3452,7 @@ static int __cgroup_attach_unified(const struct lxc_conf *conf, const char *name
dfd_unified
=
lxc_cmd_get_cgroup2_fd
(
name
,
lxcpath
);
dfd_unified
=
lxc_cmd_get_cgroup2_fd
(
name
,
lxcpath
);
if
(
dfd_unified
<
0
)
if
(
dfd_unified
<
0
)
return
ret_errno
(
ENO
CGROUP2
);
return
ret_errno
(
ENO
SYS
);
return
__unified_attach_fd
(
conf
,
dfd_unified
,
pid
);
return
__unified_attach_fd
(
conf
,
dfd_unified
,
pid
);
}
}
...
@@ -3432,65 +3464,117 @@ int cgroup_attach(const struct lxc_conf *conf, const char *name,
...
@@ -3432,65 +3464,117 @@ int cgroup_attach(const struct lxc_conf *conf, const char *name,
ret
=
__cgroup_attach_many
(
conf
,
name
,
lxcpath
,
pid
);
ret
=
__cgroup_attach_many
(
conf
,
name
,
lxcpath
,
pid
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
if
(
ret
!=
-
ENOSYS
)
if
(
!
ERRNO_IS_NOT_SUPPORTED
(
ret
)
)
return
ret
;
return
ret
;
ret
=
__cgroup_attach_unified
(
conf
,
name
,
lxcpath
,
pid
);
ret
=
__cgroup_attach_unified
(
conf
,
name
,
lxcpath
,
pid
);
if
(
ret
<
0
&&
ERRNO_IS_NOT_SUPPORTED
(
ret
))
return
ret_errno
(
ENOSYS
);
}
}
return
ret
;
return
ret
;
}
}
/* Connects to command socket therefore isn't callable from command handler. */
/* Connects to command socket therefore isn't callable from command handler. */
int
cgroup_get
(
const
char
*
name
,
const
char
*
lxcpath
,
int
cgroup_get
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
key
,
char
*
buf
,
size_t
len
)
const
char
*
filename
,
char
*
buf
,
size_t
len
)
{
{
__do_close
int
unified_fd
=
-
EBADF
;
__do_close
int
dfd
=
-
EBADF
;
ssize_t
ret
;
struct
cgroup_fd
fd
=
{
.
fd
=
-
EBADF
,
};
size_t
len_controller
;
int
ret
;
if
(
is_empty_string
(
filename
)
||
is_empty_string
(
name
)
||
if
(
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
)
||
is_empty_string
(
lxcpath
))
is_empty_string
(
key
))
return
ret_errno
(
EINVAL
);
return
ret_errno
(
EINVAL
);
if
((
buf
&&
!
len
)
||
(
len
&&
!
buf
))
if
((
buf
&&
!
len
)
||
(
len
&&
!
buf
))
return
ret_errno
(
EINVAL
);
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_limiting_cgroup2_fd
(
name
,
lxcpath
);
len_controller
=
strcspn
(
key
,
"."
);
if
(
unified_fd
<
0
)
len_controller
++
;
/* Don't forget the \0 byte. */
return
ret_errno
(
ENOCGROUP2
);
if
(
len_controller
>=
MAX_CGROUP_ROOT_NAMELEN
)
return
ret_errno
(
EINVAL
);
(
void
)
strlcpy
(
fd
.
controller
,
key
,
len_controller
);
ret
=
lxc_read_try_buf_at
(
unified_fd
,
filename
,
buf
,
len
);
ret
=
lxc_cmd_get_limit_cgroup_fd
(
name
,
lxcpath
,
sizeof
(
struct
cgroup_fd
),
&
fd
);
if
(
ret
<
0
)
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to read cgroup value"
);
if
(
!
ERRNO_IS_NOT_SUPPORTED
(
ret
))
return
ret
;
dfd
=
lxc_cmd_get_limit_cgroup2_fd
(
name
,
lxcpath
);
if
(
dfd
<
0
)
{
if
(
!
ERRNO_IS_NOT_SUPPORTED
(
ret
))
return
ret
;
return
ret_errno
(
ENOSYS
);
}
fd
.
type
=
UNIFIED_HIERARCHY
;
fd
.
fd
=
move_fd
(
dfd
);
}
dfd
=
move_fd
(
fd
.
fd
);
TRACE
(
"Reading %s from %s cgroup hierarchy"
,
key
,
cgroup_hierarchy_name
(
fd
.
type
));
if
(
fd
.
type
==
UNIFIED_HIERARCHY
&&
strequal
(
fd
.
controller
,
"devices"
))
return
ret_errno
(
EOPNOTSUPP
);
else
ret
=
lxc_read_try_buf_at
(
dfd
,
key
,
buf
,
len
);
return
ret
;
return
ret
;
}
}
/* Connects to command socket therefore isn't callable from command handler. */
/* Connects to command socket therefore isn't callable from command handler. */
int
cgroup_set
(
const
char
*
name
,
const
char
*
lxcpath
,
int
cgroup_set
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
key
,
const
char
*
value
)
const
char
*
filename
,
const
char
*
value
)
{
{
__do_close
int
unified_fd
=
-
EBADF
;
__do_close
int
dfd
=
-
EBADF
;
ssize_t
ret
;
struct
cgroup_fd
fd
=
{
.
fd
=
-
EBADF
,
};
size_t
len_controller
;
int
ret
;
if
(
is_empty_string
(
filename
)
||
is_empty_string
(
value
)
||
if
(
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
)
||
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
is_empty_string
(
key
)
||
is_empty_string
(
value
))
return
ret_errno
(
EINVAL
);
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_limiting_cgroup2_fd
(
name
,
lxcpath
);
len_controller
=
strcspn
(
key
,
"."
);
if
(
unified_fd
<
0
)
len_controller
++
;
/* Don't forget the \0 byte. */
return
ret_errno
(
ENOCGROUP2
);
if
(
len_controller
>=
MAX_CGROUP_ROOT_NAMELEN
)
return
ret_errno
(
EINVAL
);
(
void
)
strlcpy
(
fd
.
controller
,
key
,
len_controller
);
ret
=
lxc_cmd_get_limit_cgroup_fd
(
name
,
lxcpath
,
sizeof
(
struct
cgroup_fd
),
&
fd
);
if
(
ret
<
0
)
{
if
(
!
ERRNO_IS_NOT_SUPPORTED
(
ret
))
return
ret
;
dfd
=
lxc_cmd_get_limit_cgroup2_fd
(
name
,
lxcpath
);
if
(
dfd
<
0
)
{
if
(
!
ERRNO_IS_NOT_SUPPORTED
(
ret
))
return
ret
;
if
(
strnequal
(
filename
,
"devices."
,
STRLITERALLEN
(
"devices."
)))
{
return
ret_errno
(
ENOSYS
);
}
fd
.
type
=
UNIFIED_HIERARCHY
;
fd
.
fd
=
move_fd
(
dfd
);
}
dfd
=
move_fd
(
fd
.
fd
);
TRACE
(
"Setting %s to %s in %s cgroup hierarchy"
,
key
,
value
,
cgroup_hierarchy_name
(
fd
.
type
));
if
(
fd
.
type
==
UNIFIED_HIERARCHY
&&
strequal
(
fd
.
controller
,
"devices"
))
{
struct
device_item
device
=
{};
struct
device_item
device
=
{};
ret
=
device_cgroup_rule_parse
(
&
device
,
filename
,
value
);
ret
=
device_cgroup_rule_parse
(
&
device
,
key
,
value
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
log_error_errno
(
-
1
,
EINVAL
,
"Failed to parse device string %s=%s"
,
filename
,
value
);
return
log_error_errno
(
-
1
,
EINVAL
,
"Failed to parse device string %s=%s"
,
key
,
value
);
ret
=
lxc_cmd_add_bpf_device_cgroup
(
name
,
lxcpath
,
&
device
);
ret
=
lxc_cmd_add_bpf_device_cgroup
(
name
,
lxcpath
,
&
device
);
}
else
{
}
else
{
ret
=
lxc_writeat
(
unified_fd
,
filename
,
value
,
strlen
(
value
));
ret
=
lxc_writeat
(
dfd
,
key
,
value
,
strlen
(
value
));
}
}
return
ret
;
return
ret
;
...
@@ -3553,7 +3637,7 @@ int cgroup_freeze(const char *name, const char *lxcpath, int timeout)
...
@@ -3553,7 +3637,7 @@ int cgroup_freeze(const char *name, const char *lxcpath, int timeout)
if
(
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
if
(
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
return
ret_errno
(
EINVAL
);
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_limit
ing
_cgroup2_fd
(
name
,
lxcpath
);
unified_fd
=
lxc_cmd_get_limit_cgroup2_fd
(
name
,
lxcpath
);
if
(
unified_fd
<
0
)
if
(
unified_fd
<
0
)
return
ret_errno
(
ENOCGROUP2
);
return
ret_errno
(
ENOCGROUP2
);
...
@@ -3578,7 +3662,7 @@ int cgroup_unfreeze(const char *name, const char *lxcpath, int timeout)
...
@@ -3578,7 +3662,7 @@ int cgroup_unfreeze(const char *name, const char *lxcpath, int timeout)
if
(
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
if
(
is_empty_string
(
name
)
||
is_empty_string
(
lxcpath
))
return
ret_errno
(
EINVAL
);
return
ret_errno
(
EINVAL
);
unified_fd
=
lxc_cmd_get_limit
ing
_cgroup2_fd
(
name
,
lxcpath
);
unified_fd
=
lxc_cmd_get_limit_cgroup2_fd
(
name
,
lxcpath
);
if
(
unified_fd
<
0
)
if
(
unified_fd
<
0
)
return
ret_errno
(
ENOCGROUP2
);
return
ret_errno
(
ENOCGROUP2
);
...
...
src/lxc/cgroups/cgroup.h
View file @
2ed90529
...
@@ -56,15 +56,40 @@ typedef enum {
...
@@ -56,15 +56,40 @@ typedef enum {
UNIFIED_HIERARCHY
=
CGROUP2_SUPER_MAGIC
,
UNIFIED_HIERARCHY
=
CGROUP2_SUPER_MAGIC
,
}
cgroupfs_type_magic_t
;
}
cgroupfs_type_magic_t
;
static
inline
const
char
*
cgroup_hierarchy_name
(
cgroupfs_type_magic_t
type
)
{
switch
(
type
)
{
case
LEGACY_HIERARCHY
:
return
"legacy"
;
case
UNIFIED_HIERARCHY
:
return
"unified"
;
}
return
"unknown"
;
}
#define DEVICES_CONTROLLER (1U << 0)
#define DEVICES_CONTROLLER (1U << 0)
#define FREEZER_CONTROLLER (1U << 1)
#define FREEZER_CONTROLLER (1U << 1)
/*
* This is the maximum length of a cgroup controller in the kernel.
* This includes the \0 byte.
*/
#define MAX_CGROUP_ROOT_NAMELEN 64
/* That's plenty of hierarchies. */
/* That's plenty of hierarchies. */
#define CGROUP_CTX_MAX_FD 20
#define CGROUP_CTX_MAX_FD 20
// BUILD_BUG_ON(CGROUP_CTX_MAX_FD > KERNEL_SCM_MAX_FD);
struct
cgroup_fd
{
__s32
layout
;
__u32
utilities
;
__s32
type
;
__s32
fd
;
char
controller
[
MAX_CGROUP_ROOT_NAMELEN
];
}
__attribute__
((
aligned
(
8
)));
struct
cgroup_ctx
{
struct
cgroup_ctx
{
__s32
cgroup_
layout
;
__s32
layout
;
__u32
utilities
;
__u32
utilities
;
__u32
fd_len
;
__u32
fd_len
;
__s32
fd
[
CGROUP_CTX_MAX_FD
];
__s32
fd
[
CGROUP_CTX_MAX_FD
];
...
@@ -248,7 +273,7 @@ struct cgroup_ops {
...
@@ -248,7 +273,7 @@ struct cgroup_ops {
bool
(
*
monitor_delegate_controllers
)(
struct
cgroup_ops
*
ops
);
bool
(
*
monitor_delegate_controllers
)(
struct
cgroup_ops
*
ops
);
bool
(
*
payload_delegate_controllers
)(
struct
cgroup_ops
*
ops
);
bool
(
*
payload_delegate_controllers
)(
struct
cgroup_ops
*
ops
);
void
(
*
finalize
)(
struct
cgroup_ops
*
ops
);
void
(
*
finalize
)(
struct
cgroup_ops
*
ops
);
const
char
*
(
*
get_limit
ing
_cgroup
)(
struct
cgroup_ops
*
ops
,
const
char
*
controller
);
const
char
*
(
*
get_limit_cgroup
)(
struct
cgroup_ops
*
ops
,
const
char
*
controller
);
};
};
__hidden
extern
struct
cgroup_ops
*
cgroup_init
(
struct
lxc_conf
*
conf
);
__hidden
extern
struct
cgroup_ops
*
cgroup_init
(
struct
lxc_conf
*
conf
);
...
@@ -259,9 +284,9 @@ define_cleanup_function(struct cgroup_ops *, cgroup_exit);
...
@@ -259,9 +284,9 @@ define_cleanup_function(struct cgroup_ops *, cgroup_exit);
__hidden
extern
int
cgroup_attach
(
const
struct
lxc_conf
*
conf
,
const
char
*
name
,
__hidden
extern
int
cgroup_attach
(
const
struct
lxc_conf
*
conf
,
const
char
*
name
,
const
char
*
lxcpath
,
pid_t
pid
);
const
char
*
lxcpath
,
pid_t
pid
);
__hidden
extern
int
cgroup_get
(
const
char
*
name
,
const
char
*
lxcpath
,
__hidden
extern
int
cgroup_get
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
filename
,
char
*
buf
,
size_t
len
);
const
char
*
key
,
char
*
buf
,
size_t
len
);
__hidden
extern
int
cgroup_set
(
const
char
*
name
,
const
char
*
lxcpath
,
__hidden
extern
int
cgroup_set
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
filename
,
const
char
*
value
);
const
char
*
key
,
const
char
*
value
);
__hidden
extern
int
cgroup_freeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
);
__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
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
);
__hidden
extern
int
__cgroup_unfreeze
(
int
unified_fd
,
int
timeout
);
__hidden
extern
int
__cgroup_unfreeze
(
int
unified_fd
,
int
timeout
);
...
@@ -311,11 +336,13 @@ static inline int prepare_cgroup_ctx(struct cgroup_ops *ops,
...
@@ -311,11 +336,13 @@ static inline int prepare_cgroup_ctx(struct cgroup_ops *ops,
return
ret_errno
(
ENOENT
);
return
ret_errno
(
ENOENT
);
ctx
->
fd_len
=
idx
;
ctx
->
fd_len
=
idx
;
ctx
->
cgroup_
layout
=
ops
->
cgroup_layout
;
ctx
->
layout
=
ops
->
cgroup_layout
;
if
(
ops
->
unified
&&
ops
->
unified
->
dfd_con
>
0
)
if
(
ops
->
unified
&&
ops
->
unified
->
dfd_con
>
0
)
ctx
->
utilities
=
ops
->
unified
->
utilities
;
ctx
->
utilities
=
ops
->
unified
->
utilities
;
return
0
;
return
0
;
}
}
__hidden
extern
int
prepare_cgroup_fd
(
const
struct
cgroup_ops
*
ops
,
struct
cgroup_fd
*
fd
,
bool
limit
);
#endif
/* __LXC_CGROUP_H */
#endif
/* __LXC_CGROUP_H */
src/lxc/commands.c
View file @
2ed90529
...
@@ -65,7 +65,7 @@ lxc_log_define(commands, lxc);
...
@@ -65,7 +65,7 @@ lxc_log_define(commands, lxc);
static
const
char
*
lxc_cmd_str
(
lxc_cmd_t
cmd
)
static
const
char
*
lxc_cmd_str
(
lxc_cmd_t
cmd
)
{
{
static
const
char
*
const
cmdname
[
LXC_CMD_MAX
]
=
{
static
const
char
*
const
cmdname
[
LXC_CMD_MAX
]
=
{
[
LXC_CMD_
CONSOLE
]
=
"console
"
,
[
LXC_CMD_
GET_TTY_FD
]
=
"get_tty_fd
"
,
[
LXC_CMD_TERMINAL_WINCH
]
=
"terminal_winch"
,
[
LXC_CMD_TERMINAL_WINCH
]
=
"terminal_winch"
,
[
LXC_CMD_STOP
]
=
"stop"
,
[
LXC_CMD_STOP
]
=
"stop"
,
[
LXC_CMD_GET_STATE
]
=
"get_state"
,
[
LXC_CMD_GET_STATE
]
=
"get_state"
,
...
@@ -84,11 +84,13 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
...
@@ -84,11 +84,13 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
[
LXC_CMD_UNFREEZE
]
=
"unfreeze"
,
[
LXC_CMD_UNFREEZE
]
=
"unfreeze"
,
[
LXC_CMD_GET_CGROUP2_FD
]
=
"get_cgroup2_fd"
,
[
LXC_CMD_GET_CGROUP2_FD
]
=
"get_cgroup2_fd"
,
[
LXC_CMD_GET_INIT_PIDFD
]
=
"get_init_pidfd"
,
[
LXC_CMD_GET_INIT_PIDFD
]
=
"get_init_pidfd"
,
[
LXC_CMD_GET_LIMIT
ING_CGROUP
]
=
"get_limiting
_cgroup"
,
[
LXC_CMD_GET_LIMIT
_CGROUP
]
=
"get_limit
_cgroup"
,
[
LXC_CMD_GET_LIMIT
ING_CGROUP2_FD
]
=
"get_limiting
_cgroup2_fd"
,
[
LXC_CMD_GET_LIMIT
_CGROUP2_FD
]
=
"get_limit
_cgroup2_fd"
,
[
LXC_CMD_GET_DEVPTS_FD
]
=
"get_devpts_fd"
,
[
LXC_CMD_GET_DEVPTS_FD
]
=
"get_devpts_fd"
,
[
LXC_CMD_GET_SECCOMP_NOTIFY_FD
]
=
"get_seccomp_notify_fd"
,
[
LXC_CMD_GET_SECCOMP_NOTIFY_FD
]
=
"get_seccomp_notify_fd"
,
[
LXC_CMD_GET_CGROUP_CTX
]
=
"get_cgroup_ctx"
,
[
LXC_CMD_GET_CGROUP_CTX
]
=
"get_cgroup_ctx"
,
[
LXC_CMD_GET_CGROUP_FD
]
=
"get_cgroup_fd"
,
[
LXC_CMD_GET_LIMIT_CGROUP_FD
]
=
"get_limit_cgroup_fd"
,
};
};
if
(
cmd
>=
LXC_CMD_MAX
)
if
(
cmd
>=
LXC_CMD_MAX
)
...
@@ -110,6 +112,12 @@ static int __transfer_cgroup_ctx_fds(struct unix_fds *fds, struct cgroup_ctx *ct
...
@@ -110,6 +112,12 @@ static int __transfer_cgroup_ctx_fds(struct unix_fds *fds, struct cgroup_ctx *ct
return
0
;
return
0
;
}
}
static
int
__transfer_cgroup_fd
(
struct
unix_fds
*
fds
,
struct
cgroup_fd
*
fd
)
{
fd
->
fd
=
move_fd
(
fds
->
fd
[
0
]);
return
0
;
}
/*
/*
* lxc_cmd_rsp_recv: Receive a response to a command
* lxc_cmd_rsp_recv: Receive a response to a command
*
*
...
@@ -123,24 +131,32 @@ static int __transfer_cgroup_ctx_fds(struct unix_fds *fds, struct cgroup_ctx *ct
...
@@ -123,24 +131,32 @@ static int __transfer_cgroup_ctx_fds(struct unix_fds *fds, struct cgroup_ctx *ct
* the response data is <= a void * worth of data, it will be
* the response data is <= a void * worth of data, it will be
* stored directly in data and datalen will be 0.
* stored directly in data and datalen will be 0.
*
*
* As a special case, the response for LXC_CMD_CONSOLE is created
* As a special case, the response for LXC_CMD_GET_TTY_FD is created here as
* here as it contains an fd for the ptx pty passed through the
* it contains an fd for the ptx pty passed through the unix socket.
* unix socket.
*/
*/
static
int
lxc_cmd_rsp_recv
(
int
sock
,
struct
lxc_cmd_rr
*
cmd
)
static
int
lxc_cmd_rsp_recv
(
int
sock
,
struct
lxc_cmd_rr
*
cmd
)
{
{
__do_free
void
*
__private_ptr
=
NULL
;
struct
lxc_cmd_tty_rsp_data
*
data_console
=
NULL
;
call_cleaner
(
put_unix_fds
)
struct
unix_fds
*
fds
=
&
(
struct
unix_fds
){};
call_cleaner
(
put_unix_fds
)
struct
unix_fds
*
fds
=
&
(
struct
unix_fds
){};
struct
lxc_cmd_rsp
*
rsp
=
&
cmd
->
rsp
;
struct
lxc_cmd_rsp
*
rsp
=
&
cmd
->
rsp
;
int
cur_cmd
=
cmd
->
req
.
cmd
;
int
cur_cmd
=
cmd
->
req
.
cmd
,
fret
=
0
;
const
char
*
cur_cmdstr
;
const
char
*
cur_cmdstr
;
int
fret
=
0
;
int
ret
;
int
ret
;
/*
* Determine whether this command will receive file descriptors and how
* many at most.
*/
cur_cmdstr
=
lxc_cmd_str
(
cur_cmd
);
cur_cmdstr
=
lxc_cmd_str
(
cur_cmd
);
switch
(
cur_cmd
)
{
switch
(
cur_cmd
)
{
case
LXC_CMD_GET_CGROUP_FD
:
__fallthrough
;
case
LXC_CMD_GET_LIMIT_CGROUP_FD
:
__fallthrough
;
case
LXC_CMD_GET_CGROUP2_FD
:
case
LXC_CMD_GET_CGROUP2_FD
:
__fallthrough
;
__fallthrough
;
case
LXC_CMD_GET_LIMIT
ING
_CGROUP2_FD
:
case
LXC_CMD_GET_LIMIT_CGROUP2_FD
:
__fallthrough
;
__fallthrough
;
case
LXC_CMD_GET_INIT_PIDFD
:
case
LXC_CMD_GET_INIT_PIDFD
:
__fallthrough
;
__fallthrough
;
...
@@ -148,7 +164,7 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
...
@@ -148,7 +164,7 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
__fallthrough
;
__fallthrough
;
case
LXC_CMD_GET_DEVPTS_FD
:
case
LXC_CMD_GET_DEVPTS_FD
:
__fallthrough
;
__fallthrough
;
case
LXC_CMD_
CONSOLE
:
case
LXC_CMD_
GET_TTY_FD
:
fds
->
fd_count_max
=
1
;
fds
->
fd_count_max
=
1
;
break
;
break
;
case
LXC_CMD_GET_CGROUP_CTX
:
case
LXC_CMD_GET_CGROUP_CTX
:
...
@@ -158,83 +174,140 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
...
@@ -158,83 +174,140 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
fds
->
fd_count_max
=
0
;
fds
->
fd_count_max
=
0
;
break
;
break
;
}
}
/* Receive the first response including file descriptors if any. */
ret
=
lxc_abstract_unix_recv_fds
(
sock
,
fds
,
rsp
,
sizeof
(
*
rsp
));
ret
=
lxc_abstract_unix_recv_fds
(
sock
,
fds
,
rsp
,
sizeof
(
*
rsp
));
if
(
ret
<
0
)
if
(
ret
<
0
)
return
syserrno
(
ret
,
"Failed to receive response for command
\"
%s
\"
"
,
cur_cmdstr
);
return
syserrno
(
ret
,
"Failed to receive response for command
\"
%s
\"
"
,
cur_cmdstr
);
/*
* Verify that we actually received any file descriptors if the command
* expects to do so.
*/
if
(
fds
->
fd_count_max
==
0
)
{
if
(
fds
->
fd_count_max
==
0
)
{
TRACE
(
"Command
\"
%s
\"
received response with %u file descriptors"
,
cur_cmdstr
,
fds
->
fd_count_ret
);
WARN
(
"Command
\"
%s
\"
received response"
,
cur_cmdstr
);
}
else
if
(
fds
->
fd_count_ret
==
0
)
{
}
else
if
(
fds
->
fd_count_ret
==
0
)
{
WARN
(
"Command
\"
%s
\"
received response without expected file descriptors"
,
cur_cmdstr
);
TRACE
(
"Command
\"
%s
\"
received response without any of the expected %u file descriptors"
,
cur_cmdstr
,
fds
->
fd_count_max
);
fret
=
-
EBADF
;
fret
=
-
EBADF
;
}
else
{
TRACE
(
"Command
\"
%s
\"
received response with %u of %u expected file descriptors"
,
cur_cmdstr
,
fds
->
fd_count_ret
,
fds
->
fd_count_max
);
}
}
if
(
cur_cmd
==
LXC_CMD_CONSOLE
)
{
/*
struct
lxc_cmd_console_rsp_data
*
rspdata
;
* Ensure that no excessive data is sent unless someone retrieves the
* console ringbuffer.
/* recv() returns 0 bytes when a tty cannot be allocated,
* rsp->ret is < 0 when the peer permission check failed
*/
*/
if
(
ret
==
0
||
rsp
->
ret
<
0
)
if
((
rsp
->
datalen
>
LXC_CMD_DATA_MAX
)
&&
return
0
;
(
cur_cmd
!=
LXC_CMD_CONSOLE_LOG
))
return
syserrno_set
(
fret
?:
-
E2BIG
,
"Response data for command
\"
%s
\"
is too long: %d bytes > %d"
,
rspdata
=
malloc
(
sizeof
(
*
rspdata
));
cur_cmdstr
,
rsp
->
datalen
,
LXC_CMD_DATA_MAX
);
if
(
!
rspdata
)
return
syserrno_set
(
-
ENOMEM
,
"Failed to receive response for command
\"
%s
\"
"
,
cur_cmdstr
);
rspdata
->
ptxfd
=
move_fd
(
fds
->
fd
[
0
]);
rspdata
->
ttynum
=
PTR_TO_INT
(
rsp
->
data
);
rsp
->
data
=
rspdata
;
}
/*
* Prepare buffer for any command that expects to receive additional
* data. Note that some don't want any additional data.
*/
switch
(
cur_cmd
)
{
switch
(
cur_cmd
)
{
case
LXC_CMD_GET_CGROUP2_FD
:
case
LXC_CMD_GET_CGROUP2_FD
:
/* no data */
__fallthrough
;
__fallthrough
;
case
LXC_CMD_GET_LIMIT
ING_CGROUP2_FD
:
case
LXC_CMD_GET_LIMIT
_CGROUP2_FD
:
/* no data */
__fallthrough
;
__fallthrough
;
case
LXC_CMD_GET_INIT_PIDFD
:
case
LXC_CMD_GET_INIT_PIDFD
:
/* no data */
__fallthrough
;
__fallthrough
;
case
LXC_CMD_GET_DEVPTS_FD
:
case
LXC_CMD_GET_DEVPTS_FD
:
/* no data */
__fallthrough
;
__fallthrough
;
case
LXC_CMD_GET_SECCOMP_NOTIFY_FD
:
case
LXC_CMD_GET_SECCOMP_NOTIFY_FD
:
/* no data */
if
(
!
fret
)
rsp
->
data
=
INT_TO_PTR
(
move_fd
(
fds
->
fd
[
0
]));
rsp
->
data
=
INT_TO_PTR
(
move_fd
(
fds
->
fd
[
0
]));
return
log_debug
(
fret
?:
ret
,
"Finished processing
\"
%s
\"
"
,
cur_cmdstr
);
case
LXC_CMD_GET_CGROUP_CTX
:
/* Return for any command that doesn't expect additional data. */
if
((
rsp
->
datalen
==
0
)
||
(
rsp
->
datalen
>
sizeof
(
struct
cgroup_ctx
)))
return
log_debug
(
fret
?:
ret
,
"Finished processing
\"
%s
\"
with file descriptor %d"
,
cur_cmdstr
,
PTR_TO_INT
(
rsp
->
data
));
case
LXC_CMD_GET_CGROUP_FD
:
/* data */
__fallthrough
;
case
LXC_CMD_GET_LIMIT_CGROUP_FD
:
/* data */
if
(
rsp
->
datalen
>
sizeof
(
struct
cgroup_fd
))
return
syserrno_set
(
fret
?:
-
EINVAL
,
"Invalid response size from server for
\"
%s
\"
"
,
cur_cmdstr
);
return
syserrno_set
(
fret
?:
-
EINVAL
,
"Invalid response size from server for
\"
%s
\"
"
,
cur_cmdstr
);
/* Don't pointlessly allocate. */
/* Don't pointlessly allocate. */
rsp
->
data
=
(
void
*
)
cmd
->
req
.
data
;
rsp
->
data
=
(
void
*
)
cmd
->
req
.
data
;
break
;
break
;
default:
case
LXC_CMD_GET_CGROUP_CTX
:
/* data */
if
(
rsp
->
datalen
>
sizeof
(
struct
cgroup_ctx
))
return
syserrno_set
(
fret
?:
-
EINVAL
,
"Invalid response size from server for
\"
%s
\"
"
,
cur_cmdstr
);
/* Don't pointlessly allocate. */
rsp
->
data
=
(
void
*
)
cmd
->
req
.
data
;
break
;
break
;
}
case
LXC_CMD_GET_TTY_FD
:
/* data */
/*
* recv() returns 0 bytes when a tty cannot be allocated,
* rsp->ret is < 0 when the peer permission check failed
*/
if
(
ret
==
0
||
rsp
->
ret
<
0
)
return
0
;
if
(
rsp
->
datalen
==
0
)
__private_ptr
=
malloc
(
sizeof
(
struct
lxc_cmd_tty_rsp_data
));
return
log_debug
(
fret
?:
ret
,
"Response data length for command
\"
%s
\"
is 0"
,
cur_cmdstr
);
if
(
!
__private_ptr
)
return
syserrno_set
(
fret
?:
-
ENOMEM
,
"Failed to receive response for command
\"
%s
\"
"
,
cur_cmdstr
);
data_console
=
(
struct
lxc_cmd_tty_rsp_data
*
)
__private_ptr
;
data_console
->
ptxfd
=
move_fd
(
fds
->
fd
[
0
]);
data_console
->
ttynum
=
PTR_TO_INT
(
rsp
->
data
);
if
((
rsp
->
datalen
>
LXC_CMD_DATA_MAX
)
&&
rsp
->
datalen
=
0
;
(
cur_cmd
!=
LXC_CMD_CONSOLE_LOG
))
rsp
->
data
=
data_console
;
return
syserrno_set
(
-
E2BIG
,
"Response data for command
\"
%s
\"
is too long: %d bytes > %d"
,
break
;
cur_cmdstr
,
rsp
->
datalen
,
LXC_CMD_DATA_MAX
);
case
LXC_CMD_CONSOLE_LOG
:
/* data */
__private_ptr
=
zalloc
(
rsp
->
datalen
+
1
);
rsp
->
data
=
__private_ptr
;
break
;
default:
/* catch any additional command */
if
(
rsp
->
datalen
>
0
)
{
__private_ptr
=
zalloc
(
rsp
->
datalen
);
rsp
->
data
=
__private_ptr
;
}
break
;
}
if
(
rsp
->
datalen
==
0
)
{
DEBUG
(
"Command
\"
%s
\"
requested no additional data"
,
cur_cmdstr
);
/*
* Note that LXC_CMD_GET_TTY_FD historically allocates memory
* to return info to the caller. That's why we jump to no_data
* so we ensure that the allocated data is wiped if we return
* early here.
*/
goto
no_data
;
}
if
(
cur_cmd
==
LXC_CMD_CONSOLE_LOG
)
/*
rsp
->
data
=
zalloc
(
rsp
->
datalen
+
1
);
* All commands ending up here expect data so rsp->data must be valid.
else
if
(
cur_cmd
!=
LXC_CMD_GET_CGROUP_CTX
)
* Either static or allocated memory.
rsp
->
data
=
malloc
(
rsp
->
datalen
);
*/
if
(
!
rsp
->
data
)
if
(
!
rsp
->
data
)
return
syserrno_set
(
-
ENOMEM
,
"Failed to allocat
e response buffer for command
\"
%s
\"
"
,
cur_cmdstr
);
return
syserrno_set
(
fret
?:
-
ENOMEM
,
"Failed to prepar
e response buffer for command
\"
%s
\"
"
,
cur_cmdstr
);
ret
=
lxc_recv_nointr
(
sock
,
rsp
->
data
,
rsp
->
datalen
,
0
);
ret
=
lxc_recv_nointr
(
sock
,
rsp
->
data
,
rsp
->
datalen
,
0
);
if
(
ret
!=
rsp
->
datalen
)
if
(
ret
!=
rsp
->
datalen
)
return
syserrno
(
-
errno
,
"Failed to receive response data for command
\"
%s
\"
"
,
cur_cmdstr
);
return
syserrno
(
-
errno
,
"Failed to receive response data for command
\"
%s
\"
: %d != %d"
,
cur_cmdstr
,
ret
,
rsp
->
datalen
);
if
(
cur_cmd
==
LXC_CMD_GET_CGROUP_CTX
)
{
switch
(
cur_cmd
)
{
case
LXC_CMD_GET_CGROUP_CTX
:
if
(
!
fret
)
ret
=
__transfer_cgroup_ctx_fds
(
fds
,
rsp
->
data
);
ret
=
__transfer_cgroup_ctx_fds
(
fds
,
rsp
->
data
);
if
(
ret
<
0
)
/* Make sure any received fds are wiped by us. */
return
syserrno
(
ret
,
"Failed to transfer file descriptors for
\"
%s
\"
"
,
cur_cmdstr
);
break
;
case
LXC_CMD_GET_CGROUP_FD
:
__fallthrough
;
case
LXC_CMD_GET_LIMIT_CGROUP_FD
:
if
(
!
fret
)
ret
=
__transfer_cgroup_fd
(
fds
,
rsp
->
data
);
/* Make sure any received fds are wiped by us. */
break
;
}
}
no_data:
if
(
!
fret
&&
ret
>=
0
)
move_ptr
(
__private_ptr
);
return
fret
?:
ret
;
return
fret
?:
ret
;
}
}
...
@@ -288,12 +361,18 @@ static inline int lxc_cmd_rsp_send_keep(int fd, struct lxc_cmd_rsp *rsp)
...
@@ -288,12 +361,18 @@ static inline int lxc_cmd_rsp_send_keep(int fd, struct lxc_cmd_rsp *rsp)
static
inline
int
rsp_one_fd
(
int
fd
,
int
fd_send
,
struct
lxc_cmd_rsp
*
rsp
)
static
inline
int
rsp_one_fd
(
int
fd
,
int
fd_send
,
struct
lxc_cmd_rsp
*
rsp
)
{
{
in
t
ret
;
ssize_
t
ret
;
ret
=
lxc_abstract_unix_send_fds
(
fd
,
&
fd_send
,
1
,
rsp
,
sizeof
(
*
rsp
));
ret
=
lxc_abstract_unix_send_fds
(
fd
,
&
fd_send
,
1
,
rsp
,
sizeof
(
*
rsp
));
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
rsp
->
data
&&
rsp
->
datalen
>
0
)
{
ret
=
lxc_send_nointr
(
fd
,
rsp
->
data
,
rsp
->
datalen
,
MSG_NOSIGNAL
);
if
(
ret
<
0
||
ret
!=
(
ssize_t
)
rsp
->
datalen
)
return
syswarn
(
-
errno
,
"Failed to send command response %zd"
,
ret
);
}
return
LXC_CMD_REAP_CLIENT_FD
;
return
LXC_CMD_REAP_CLIENT_FD
;
}
}
...
@@ -369,13 +448,13 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
...
@@ -369,13 +448,13 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
*
*
* Returns the size of the response message on success, < 0 on failure
* Returns the size of the response message on success, < 0 on failure
*
*
* Note that there is a special case for LXC_CMD_
CONSOLE
. For this command
* Note that there is a special case for LXC_CMD_
GET_TTY_FD
. For this command
* the fd cannot be closed because it is used as a placeholder to indicate
* the fd cannot be closed because it is used as a placeholder to indicate
that
*
that a particular tty slot is in use. The fd is also used as a signal to
*
a particular tty slot is in use. The fd is also used as a signal to the
*
the container that when the caller dies or closes the fd, the container
*
container that when the caller dies or closes the fd, the container will
*
will notice the fd on its side of the socket in its mainloop select and
*
notice the fd on its side of the socket in its mainloop select and then free
* the
n free the slot with lxc_cmd_fd_cleanup(). The socket fd will b
e
* the
slot with lxc_cmd_fd_cleanup(). The socket fd will be returned in th
e
*
returned in the
cmd response structure.
* cmd response structure.
*/
*/
static
int
lxc_cmd
(
const
char
*
name
,
struct
lxc_cmd_rr
*
cmd
,
int
*
stopped
,
static
int
lxc_cmd
(
const
char
*
name
,
struct
lxc_cmd_rr
*
cmd
,
int
*
stopped
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
...
@@ -384,7 +463,7 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
...
@@ -384,7 +463,7 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
int
ret
=
-
1
;
int
ret
=
-
1
;
bool
stay_connected
=
false
;
bool
stay_connected
=
false
;
if
(
cmd
->
req
.
cmd
==
LXC_CMD_
CONSOLE
||
if
(
cmd
->
req
.
cmd
==
LXC_CMD_
GET_TTY_FD
||
cmd
->
req
.
cmd
==
LXC_CMD_ADD_STATE_CLIENT
)
cmd
->
req
.
cmd
==
LXC_CMD_ADD_STATE_CLIENT
)
stay_connected
=
true
;
stay_connected
=
true
;
...
@@ -629,7 +708,6 @@ static int lxc_cmd_get_seccomp_notify_fd_callback(int fd, struct lxc_cmd_req *re
...
@@ -629,7 +708,6 @@ static int lxc_cmd_get_seccomp_notify_fd_callback(int fd, struct lxc_cmd_req *re
}
}
int
lxc_cmd_get_cgroup_ctx
(
const
char
*
name
,
const
char
*
lxcpath
,
int
lxc_cmd_get_cgroup_ctx
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
controller
,
bool
batch
,
size_t
size_ret_ctx
,
struct
cgroup_ctx
*
ret_ctx
)
size_t
size_ret_ctx
,
struct
cgroup_ctx
*
ret_ctx
)
{
{
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
...
@@ -644,9 +722,6 @@ int lxc_cmd_get_cgroup_ctx(const char *name, const char *lxcpath,
...
@@ -644,9 +722,6 @@ int lxc_cmd_get_cgroup_ctx(const char *name, const char *lxcpath,
};
};
int
ret
,
stopped
;
int
ret
,
stopped
;
if
(
batch
&&
!
is_empty_string
(
controller
))
return
ret_errno
(
EINVAL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
log_debug_errno
(
-
1
,
errno
,
"Failed to process cgroup context command"
);
return
log_debug_errno
(
-
1
,
errno
,
"Failed to process cgroup context command"
);
...
@@ -679,6 +754,7 @@ static int lxc_cmd_get_cgroup_ctx_callback(int fd, struct lxc_cmd_req *req,
...
@@ -679,6 +754,7 @@ static int lxc_cmd_get_cgroup_ctx_callback(int fd, struct lxc_cmd_req *req,
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
}
}
rsp
.
ret
=
0
;
rsp
.
data
=
&
ctx_server
;
rsp
.
data
=
&
ctx_server
;
rsp
.
datalen
=
min
(
sizeof
(
struct
cgroup_ctx
),
(
size_t
)
req
->
datalen
);
rsp
.
datalen
=
min
(
sizeof
(
struct
cgroup_ctx
),
(
size_t
)
req
->
datalen
);
return
rsp_many_fds
(
fd
,
ctx_server
.
fd_len
,
ctx_server
.
fd
,
&
rsp
);
return
rsp_many_fds
(
fd
,
ctx_server
.
fd_len
,
ctx_server
.
fd
,
&
rsp
);
...
@@ -742,7 +818,7 @@ static char *lxc_cmd_get_cgroup_path_do(const char *name, const char *lxcpath,
...
@@ -742,7 +818,7 @@ static char *lxc_cmd_get_cgroup_path_do(const char *name, const char *lxcpath,
return
NULL
;
return
NULL
;
if
(
ret
==
0
)
{
if
(
ret
==
0
)
{
if
(
command
==
LXC_CMD_GET_LIMIT
ING
_CGROUP
)
{
if
(
command
==
LXC_CMD_GET_LIMIT_CGROUP
)
{
/*
/*
* This may indicate that the container was started
* This may indicate that the container was started
* under an ealier version before
* under an ealier version before
...
@@ -783,10 +859,10 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
...
@@ -783,10 +859,10 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
}
}
/*
/*
* lxc_cmd_get_limit
ing_cgroup_path: Calculate a container's limiting
cgroup
* lxc_cmd_get_limit
_cgroup_path: Calculate a container's limit
cgroup
* path for a particular subsystem. This is the cgroup path relative to the
* path for a particular subsystem. This is the cgroup path relative to the
* root of the cgroup filesystem. This may be the same as the path returned by
* root of the cgroup filesystem. This may be the same as the path returned by
* lxc_cmd_get_cgroup_path if the container doesn't have a limit
ing
path prefix
* lxc_cmd_get_cgroup_path if the container doesn't have a limit path prefix
* set.
* set.
*
*
* @name : name of container to connect to
* @name : name of container to connect to
...
@@ -796,11 +872,11 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
...
@@ -796,11 +872,11 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
* Returns the path on success, NULL on failure. The caller must free() the
* Returns the path on success, NULL on failure. The caller must free() the
* returned path.
* returned path.
*/
*/
char
*
lxc_cmd_get_limit
ing
_cgroup_path
(
const
char
*
name
,
const
char
*
lxcpath
,
char
*
lxc_cmd_get_limit_cgroup_path
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
subsystem
)
const
char
*
subsystem
)
{
{
return
lxc_cmd_get_cgroup_path_do
(
name
,
lxcpath
,
subsystem
,
return
lxc_cmd_get_cgroup_path_do
(
name
,
lxcpath
,
subsystem
,
LXC_CMD_GET_LIMIT
ING
_CGROUP
);
LXC_CMD_GET_LIMIT_CGROUP
);
}
}
static
int
lxc_cmd_get_cgroup_callback_do
(
int
fd
,
struct
lxc_cmd_req
*
req
,
static
int
lxc_cmd_get_cgroup_callback_do
(
int
fd
,
struct
lxc_cmd_req
*
req
,
...
@@ -824,7 +900,7 @@ static int lxc_cmd_get_cgroup_callback_do(int fd, struct lxc_cmd_req *req,
...
@@ -824,7 +900,7 @@ static int lxc_cmd_get_cgroup_callback_do(int fd, struct lxc_cmd_req *req,
reqdata
=
NULL
;
reqdata
=
NULL
;
}
}
get_fn
=
(
limiting_cgroup
?
cgroup_ops
->
get_limit
ing
_cgroup
get_fn
=
(
limiting_cgroup
?
cgroup_ops
->
get_limit_cgroup
:
cgroup_ops
->
get_cgroup
);
:
cgroup_ops
->
get_cgroup
);
path
=
get_fn
(
cgroup_ops
,
reqdata
);
path
=
get_fn
(
cgroup_ops
,
reqdata
);
...
@@ -846,7 +922,7 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
...
@@ -846,7 +922,7 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
return
lxc_cmd_get_cgroup_callback_do
(
fd
,
req
,
handler
,
descr
,
false
);
return
lxc_cmd_get_cgroup_callback_do
(
fd
,
req
,
handler
,
descr
,
false
);
}
}
static
int
lxc_cmd_get_limit
ing
_cgroup_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
static
int
lxc_cmd_get_limit_cgroup_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
)
{
{
...
@@ -1056,7 +1132,7 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
...
@@ -1056,7 +1132,7 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
}
}
/*
/*
* lxc_cmd_
console
: Open an fd to a tty in the container
* lxc_cmd_
get_tty_fd
: Open an fd to a tty in the container
*
*
* @name : name of container to connect to
* @name : name of container to connect to
* @ttynum : in: the tty to open or -1 for next available
* @ttynum : in: the tty to open or -1 for next available
...
@@ -1066,13 +1142,13 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
...
@@ -1066,13 +1142,13 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
*
*
* Returns fd holding tty allocated on success, < 0 on failure
* Returns fd holding tty allocated on success, < 0 on failure
*/
*/
int
lxc_cmd_
console
(
const
char
*
name
,
int
*
ttynum
,
int
*
fd
,
const
char
*
lxcpath
)
int
lxc_cmd_
get_tty_fd
(
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_
tty
_rsp_data
*
rspdata
=
NULL
;
int
ret
,
stopped
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
req
=
{
.
cmd
=
LXC_CMD_
CONSOLE
,
.
cmd
=
LXC_CMD_
GET_TTY_FD
,
.
data
=
INT_TO_PTR
(
*
ttynum
),
.
data
=
INT_TO_PTR
(
*
ttynum
),
},
},
};
};
...
@@ -1098,7 +1174,7 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
...
@@ -1098,7 +1174,7 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
return
log_info
(
ret
,
"Alloced fd %d for tty %d via socket %d"
,
*
fd
,
rspdata
->
ttynum
,
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_
get_tty_fd
_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
)
{
{
...
@@ -1569,6 +1645,102 @@ static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
...
@@ -1569,6 +1645,102 @@ static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
}
}
int
lxc_cmd_get_cgroup_fd
(
const
char
*
name
,
const
char
*
lxcpath
,
size_t
size_ret_fd
,
struct
cgroup_fd
*
ret_fd
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_CGROUP_FD
,
.
datalen
=
sizeof
(
struct
cgroup_fd
),
.
data
=
ret_fd
,
},
.
rsp
=
{
ret
=
-
ENOSYS
,
},
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
return
log_debug_errno
(
-
1
,
errno
,
"Failed to process cgroup fd command"
);
if
(
cmd
.
rsp
.
ret
<
0
)
return
log_debug_errno
(
-
EBADF
,
errno
,
"Failed to receive cgroup fd"
);
return
0
;
}
int
lxc_cmd_get_limit_cgroup_fd
(
const
char
*
name
,
const
char
*
lxcpath
,
size_t
size_ret_fd
,
struct
cgroup_fd
*
ret_fd
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_LIMIT_CGROUP_FD
,
.
datalen
=
sizeof
(
struct
cgroup_fd
),
.
data
=
ret_fd
,
},
.
rsp
=
{
ret
=
-
ENOSYS
,
},
};
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
return
log_debug_errno
(
-
1
,
errno
,
"Failed to process limit cgroup fd command"
);
if
(
cmd
.
rsp
.
ret
<
0
)
return
log_debug_errno
(
-
EBADF
,
errno
,
"Failed to receive limit cgroup fd"
);
return
0
;
}
static
int
__lxc_cmd_get_cgroup_fd_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
,
bool
limit
)
{
struct
lxc_cmd_rsp
rsp
=
{
.
ret
=
-
EINVAL
,
};
struct
cgroup_ops
*
ops
=
handler
->
cgroup_ops
;
struct
cgroup_fd
fd_server
=
{};
int
ret
;
ret
=
copy_struct_from_client
(
sizeof
(
struct
cgroup_fd
),
&
fd_server
,
req
->
datalen
,
req
->
data
);
if
(
ret
<
0
)
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
if
(
strnlen
(
fd_server
.
controller
,
MAX_CGROUP_ROOT_NAMELEN
)
==
0
)
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
ret
=
prepare_cgroup_fd
(
ops
,
&
fd_server
,
limit
);
if
(
ret
<
0
)
{
rsp
.
ret
=
ret
;
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
}
rsp
.
ret
=
0
;
rsp
.
data
=
&
fd_server
;
rsp
.
datalen
=
min
(
sizeof
(
struct
cgroup_fd
),
(
size_t
)
req
->
datalen
);
return
rsp_one_fd
(
fd
,
fd_server
.
fd
,
&
rsp
);
}
static
int
lxc_cmd_get_cgroup_fd_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
{
return
__lxc_cmd_get_cgroup_fd_callback
(
fd
,
req
,
handler
,
descr
,
false
);
}
static
int
lxc_cmd_get_limit_cgroup_fd_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
{
return
__lxc_cmd_get_cgroup_fd_callback
(
fd
,
req
,
handler
,
descr
,
true
);
}
int
lxc_cmd_get_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
int
lxc_cmd_get_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
{
int
ret
,
stopped
;
int
ret
,
stopped
;
...
@@ -1591,12 +1763,12 @@ int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
...
@@ -1591,12 +1763,12 @@ int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
return
PTR_TO_INT
(
cmd
.
rsp
.
data
);
return
PTR_TO_INT
(
cmd
.
rsp
.
data
);
}
}
int
lxc_cmd_get_limit
ing
_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
int
lxc_cmd_get_limit_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
{
int
ret
,
stopped
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_LIMIT
ING
_CGROUP2_FD
,
.
cmd
=
LXC_CMD_GET_LIMIT_CGROUP2_FD
,
},
},
.
rsp
=
{
.
rsp
=
{
.
ret
=
-
ENOSYS
,
.
ret
=
-
ENOSYS
,
...
@@ -1647,8 +1819,7 @@ static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
...
@@ -1647,8 +1819,7 @@ static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
false
);
false
);
}
}
static
int
lxc_cmd_get_limiting_cgroup2_fd_callback
(
int
fd
,
static
int
lxc_cmd_get_limit_cgroup2_fd_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
...
@@ -1674,7 +1845,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
...
@@ -1674,7 +1845,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
struct
lxc_epoll_descr
*
);
struct
lxc_epoll_descr
*
);
callback
cb
[
LXC_CMD_MAX
]
=
{
callback
cb
[
LXC_CMD_MAX
]
=
{
[
LXC_CMD_
CONSOLE
]
=
lxc_cmd_console
_callback
,
[
LXC_CMD_
GET_TTY_FD
]
=
lxc_cmd_get_tty_fd
_callback
,
[
LXC_CMD_TERMINAL_WINCH
]
=
lxc_cmd_terminal_winch_callback
,
[
LXC_CMD_TERMINAL_WINCH
]
=
lxc_cmd_terminal_winch_callback
,
[
LXC_CMD_STOP
]
=
lxc_cmd_stop_callback
,
[
LXC_CMD_STOP
]
=
lxc_cmd_stop_callback
,
[
LXC_CMD_GET_STATE
]
=
lxc_cmd_get_state_callback
,
[
LXC_CMD_GET_STATE
]
=
lxc_cmd_get_state_callback
,
...
@@ -1693,11 +1864,13 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
...
@@ -1693,11 +1864,13 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
[
LXC_CMD_UNFREEZE
]
=
lxc_cmd_unfreeze_callback
,
[
LXC_CMD_UNFREEZE
]
=
lxc_cmd_unfreeze_callback
,
[
LXC_CMD_GET_CGROUP2_FD
]
=
lxc_cmd_get_cgroup2_fd_callback
,
[
LXC_CMD_GET_CGROUP2_FD
]
=
lxc_cmd_get_cgroup2_fd_callback
,
[
LXC_CMD_GET_INIT_PIDFD
]
=
lxc_cmd_get_init_pidfd_callback
,
[
LXC_CMD_GET_INIT_PIDFD
]
=
lxc_cmd_get_init_pidfd_callback
,
[
LXC_CMD_GET_LIMIT
ING_CGROUP
]
=
lxc_cmd_get_limiting
_cgroup_callback
,
[
LXC_CMD_GET_LIMIT
_CGROUP
]
=
lxc_cmd_get_limit
_cgroup_callback
,
[
LXC_CMD_GET_LIMIT
ING_CGROUP2_FD
]
=
lxc_cmd_get_limiting
_cgroup2_fd_callback
,
[
LXC_CMD_GET_LIMIT
_CGROUP2_FD
]
=
lxc_cmd_get_limit
_cgroup2_fd_callback
,
[
LXC_CMD_GET_DEVPTS_FD
]
=
lxc_cmd_get_devpts_fd_callback
,
[
LXC_CMD_GET_DEVPTS_FD
]
=
lxc_cmd_get_devpts_fd_callback
,
[
LXC_CMD_GET_SECCOMP_NOTIFY_FD
]
=
lxc_cmd_get_seccomp_notify_fd_callback
,
[
LXC_CMD_GET_SECCOMP_NOTIFY_FD
]
=
lxc_cmd_get_seccomp_notify_fd_callback
,
[
LXC_CMD_GET_CGROUP_CTX
]
=
lxc_cmd_get_cgroup_ctx_callback
,
[
LXC_CMD_GET_CGROUP_CTX
]
=
lxc_cmd_get_cgroup_ctx_callback
,
[
LXC_CMD_GET_CGROUP_FD
]
=
lxc_cmd_get_cgroup_fd_callback
,
[
LXC_CMD_GET_LIMIT_CGROUP_FD
]
=
lxc_cmd_get_limit_cgroup_fd_callback
,
};
};
if
(
req
->
cmd
>=
LXC_CMD_MAX
)
if
(
req
->
cmd
>=
LXC_CMD_MAX
)
...
...
src/lxc/commands.h
View file @
2ed90529
...
@@ -21,7 +21,7 @@
...
@@ -21,7 +21,7 @@
#define LXC_CMD_REAP_CLIENT_FD 1
#define LXC_CMD_REAP_CLIENT_FD 1
typedef
enum
{
typedef
enum
{
LXC_CMD_
CONSOLE
=
0
,
LXC_CMD_
GET_TTY_FD
=
0
,
LXC_CMD_TERMINAL_WINCH
=
1
,
LXC_CMD_TERMINAL_WINCH
=
1
,
LXC_CMD_STOP
=
2
,
LXC_CMD_STOP
=
2
,
LXC_CMD_GET_STATE
=
3
,
LXC_CMD_GET_STATE
=
3
,
...
@@ -40,11 +40,13 @@ typedef enum {
...
@@ -40,11 +40,13 @@ typedef enum {
LXC_CMD_UNFREEZE
=
16
,
LXC_CMD_UNFREEZE
=
16
,
LXC_CMD_GET_CGROUP2_FD
=
17
,
LXC_CMD_GET_CGROUP2_FD
=
17
,
LXC_CMD_GET_INIT_PIDFD
=
18
,
LXC_CMD_GET_INIT_PIDFD
=
18
,
LXC_CMD_GET_LIMIT
ING
_CGROUP
=
19
,
LXC_CMD_GET_LIMIT_CGROUP
=
19
,
LXC_CMD_GET_LIMIT
ING
_CGROUP2_FD
=
20
,
LXC_CMD_GET_LIMIT_CGROUP2_FD
=
20
,
LXC_CMD_GET_DEVPTS_FD
=
21
,
LXC_CMD_GET_DEVPTS_FD
=
21
,
LXC_CMD_GET_SECCOMP_NOTIFY_FD
=
22
,
LXC_CMD_GET_SECCOMP_NOTIFY_FD
=
22
,
LXC_CMD_GET_CGROUP_CTX
=
23
,
LXC_CMD_GET_CGROUP_CTX
=
23
,
LXC_CMD_GET_CGROUP_FD
=
24
,
LXC_CMD_GET_LIMIT_CGROUP_FD
=
25
,
LXC_CMD_MAX
,
LXC_CMD_MAX
,
}
lxc_cmd_t
;
}
lxc_cmd_t
;
...
@@ -65,7 +67,7 @@ struct lxc_cmd_rr {
...
@@ -65,7 +67,7 @@ struct lxc_cmd_rr {
struct
lxc_cmd_rsp
rsp
;
struct
lxc_cmd_rsp
rsp
;
};
};
struct
lxc_cmd_
console
_rsp_data
{
struct
lxc_cmd_
tty
_rsp_data
{
int
ptxfd
;
int
ptxfd
;
int
ttynum
;
int
ttynum
;
};
};
...
@@ -79,7 +81,8 @@ struct lxc_cmd_console_log {
...
@@ -79,7 +81,8 @@ struct lxc_cmd_console_log {
};
};
__hidden
extern
int
lxc_cmd_terminal_winch
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_terminal_winch
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_console
(
const
char
*
name
,
int
*
ttynum
,
int
*
fd
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_get_tty_fd
(
const
char
*
name
,
int
*
ttynum
,
int
*
fd
,
const
char
*
lxcpath
);
/*
/*
* Get the 'real' cgroup path (as seen in /proc/self/cgroup) for a container
* Get the 'real' cgroup path (as seen in /proc/self/cgroup) for a container
* for a particular subsystem
* for a particular subsystem
...
@@ -125,7 +128,6 @@ __hidden extern int lxc_cmd_console_log(const char *name, const char *lxcpath,
...
@@ -125,7 +128,6 @@ __hidden extern int lxc_cmd_console_log(const char *name, const char *lxcpath,
struct
lxc_console_log
*
log
);
struct
lxc_console_log
*
log
);
__hidden
extern
int
lxc_cmd_get_seccomp_notify_fd
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_get_seccomp_notify_fd
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_get_cgroup_ctx
(
const
char
*
name
,
const
char
*
lxcpath
,
__hidden
extern
int
lxc_cmd_get_cgroup_ctx
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
controller
,
bool
batch
,
size_t
size_ret_ctx
,
size_t
size_ret_ctx
,
struct
cgroup_ctx
*
ret_ctx
);
struct
cgroup_ctx
*
ret_ctx
);
__hidden
extern
int
lxc_cmd_seccomp_notify_add_listener
(
const
char
*
name
,
const
char
*
lxcpath
,
int
fd
,
__hidden
extern
int
lxc_cmd_seccomp_notify_add_listener
(
const
char
*
name
,
const
char
*
lxcpath
,
int
fd
,
...
@@ -138,9 +140,18 @@ __hidden extern int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *
...
@@ -138,9 +140,18 @@ __hidden extern int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *
__hidden
extern
int
lxc_cmd_freeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
);
__hidden
extern
int
lxc_cmd_freeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
);
__hidden
extern
int
lxc_cmd_unfreeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
);
__hidden
extern
int
lxc_cmd_unfreeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
);
__hidden
extern
int
lxc_cmd_get_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_get_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
char
*
lxc_cmd_get_limiting_cgroup_path
(
const
char
*
name
,
const
char
*
lxcpath
,
__hidden
extern
int
lxc_cmd_get_cgroup_fd
(
const
char
*
name
,
const
char
*
lxcpath
,
size_t
size_ret_fd
,
struct
cgroup_fd
*
ret_fd
);
__hidden
extern
char
*
lxc_cmd_get_limit_cgroup_path
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
subsystem
);
const
char
*
subsystem
);
__hidden
extern
int
lxc_cmd_get_limiting_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_get_limit_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_get_limit_cgroup_fd
(
const
char
*
name
,
const
char
*
lxcpath
,
size_t
size_ret_fd
,
struct
cgroup_fd
*
ret_fd
);
__hidden
extern
int
lxc_cmd_get_devpts_fd
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
int
lxc_cmd_get_devpts_fd
(
const
char
*
name
,
const
char
*
lxcpath
);
#endif
/* __commands_h */
#endif
/* __commands_h */
src/lxc/criu.c
View file @
2ed90529
...
@@ -304,19 +304,19 @@ static int exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf,
...
@@ -304,19 +304,19 @@ static int exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf,
* the handler the restore task created.
* the handler the restore task created.
*/
*/
if
(
strequal
(
opts
->
action
,
"dump"
)
||
strequal
(
opts
->
action
,
"pre-dump"
))
{
if
(
strequal
(
opts
->
action
,
"dump"
)
||
strequal
(
opts
->
action
,
"pre-dump"
))
{
cgroup_base_path
=
lxc_cmd_get_limit
ing
_cgroup_path
(
opts
->
c
->
name
,
opts
->
c
->
config_path
,
controllers_list
[
0
]);
cgroup_base_path
=
lxc_cmd_get_limit_cgroup_path
(
opts
->
c
->
name
,
opts
->
c
->
config_path
,
controllers_list
[
0
]);
if
(
!
cgroup_base_path
)
if
(
!
cgroup_base_path
)
return
log_error_errno
(
-
ENOENT
,
ENOENT
,
"Failed to retrieve limit
ing
cgroup path for %s"
,
controllers_list
[
0
]
?:
"(null)"
);
return
log_error_errno
(
-
ENOENT
,
ENOENT
,
"Failed to retrieve limit cgroup path for %s"
,
controllers_list
[
0
]
?:
"(null)"
);
}
else
{
}
else
{
const
char
*
p
;
const
char
*
p
;
p
=
cgroup_ops
->
get_limit
ing
_cgroup
(
cgroup_ops
,
controllers_list
[
0
]);
p
=
cgroup_ops
->
get_limit_cgroup
(
cgroup_ops
,
controllers_list
[
0
]);
if
(
!
p
)
if
(
!
p
)
return
log_error_errno
(
-
ENOENT
,
ENOENT
,
"Failed to retrieve limit
ing
cgroup path for %s"
,
controllers_list
[
0
]
?:
"(null)"
);
return
log_error_errno
(
-
ENOENT
,
ENOENT
,
"Failed to retrieve limit cgroup path for %s"
,
controllers_list
[
0
]
?:
"(null)"
);
cgroup_base_path
=
strdup
(
p
);
cgroup_base_path
=
strdup
(
p
);
if
(
!
cgroup_base_path
)
if
(
!
cgroup_base_path
)
return
log_error_errno
(
-
ENOMEM
,
ENOMEM
,
"Failed to duplicate limit
ing
cgroup path"
);
return
log_error_errno
(
-
ENOMEM
,
ENOMEM
,
"Failed to duplicate limit cgroup path"
);
}
}
tmp
=
lxc_deslashify
(
cgroup_base_path
);
tmp
=
lxc_deslashify
(
cgroup_base_path
);
...
@@ -393,7 +393,7 @@ static int exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf,
...
@@ -393,7 +393,7 @@ static int exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf,
DECLARE_ARG
(
"-t"
);
DECLARE_ARG
(
"-t"
);
DECLARE_ARG
(
init_pid_str
);
DECLARE_ARG
(
init_pid_str
);
freezer_relative
=
lxc_cmd_get_limit
ing
_cgroup_path
(
opts
->
c
->
name
,
freezer_relative
=
lxc_cmd_get_limit_cgroup_path
(
opts
->
c
->
name
,
opts
->
c
->
config_path
,
opts
->
c
->
config_path
,
"freezer"
);
"freezer"
);
if
(
!
freezer_relative
)
if
(
!
freezer_relative
)
...
...
src/lxc/error_utils.h
0 → 100644
View file @
2ed90529
/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef __LXC_ERROR_UTILS_H
#define __LXC_ERROR_UTILS_H
#include <stdbool.h>
#define MAX_ERRNO 4095
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
static
inline
void
*
ERR_PTR
(
long
error
)
{
return
(
void
*
)
error
;
}
static
inline
long
PTR_ERR
(
const
void
*
ptr
)
{
return
(
long
)
ptr
;
}
static
inline
long
IS_ERR
(
const
void
*
ptr
)
{
return
IS_ERR_VALUE
((
unsigned
long
)
ptr
);
}
static
inline
long
IS_ERR_OR_NULL
(
const
void
*
ptr
)
{
return
!
ptr
||
IS_ERR_VALUE
((
unsigned
long
)
ptr
);
}
static
inline
void
*
ERR_CAST
(
const
void
*
ptr
)
{
return
(
void
*
)
ptr
;
}
static
inline
int
PTR_RET
(
const
void
*
ptr
)
{
if
(
IS_ERR
(
ptr
))
return
PTR_ERR
(
ptr
);
else
return
0
;
}
/* Taken from Lennart tyvm. */
#define CASE_F(X) case X:
#define CASE_F_1(CASE, X) CASE_F(X)
#define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__)
#define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__)
#define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__)
#define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__)
#define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__)
#define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__)
#define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__)
#define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__)
#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
#define FOR_EACH_MAKE_CASE(...) \
GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
(CASE_F,__VA_ARGS__)
#define XCONCATENATE(x, y) x ## y
#define CONCATENATE(x, y) XCONCATENATE(x, y)
#define assert_static(expr) \
struct CONCATENATE(_assert_struct_, __COUNTER__) { \
char x[(expr) ? 0 : -1]; \
}
#define IN_SET(x, ...) \
({ \
bool _found = false; \
static const long double __assert_in_set[] __lxc_unused = { \
__VA_ARGS__}; \
assert_static(ARRAY_SIZE(__assert_in_set) <= 20); \
switch (x) { \
FOR_EACH_MAKE_CASE(__VA_ARGS__) \
_found = true; \
break; \
default: \
break; \
} \
_found; \
})
static
inline
bool
ERRNO_IS_NOT_SUPPORTED
(
int
r
)
{
return
IN_SET
(
abs
(
r
),
EOPNOTSUPP
,
ENOSYS
);
}
#endif
/* __LXC_ERROR_UTILS_H */
src/lxc/file_utils.c
View file @
2ed90529
...
@@ -127,7 +127,7 @@ ssize_t lxc_read_try_buf_at(int dfd, const char *path, void *buf, size_t count)
...
@@ -127,7 +127,7 @@ ssize_t lxc_read_try_buf_at(int dfd, const char *path, void *buf, size_t count)
__do_close
int
fd
=
-
EBADF
;
__do_close
int
fd
=
-
EBADF
;
ssize_t
ret
;
ssize_t
ret
;
fd
=
open_at
(
dfd
,
path
,
PROTECT_OPEN
_W
,
PROTECT_LOOKUP_BENEATH
,
0
);
fd
=
open_at
(
dfd
,
path
,
PROTECT_OPEN
,
PROTECT_LOOKUP_BENEATH
,
0
);
if
(
fd
<
0
)
if
(
fd
<
0
)
return
-
errno
;
return
-
errno
;
...
...
src/lxc/lxccontainer.c
View file @
2ed90529
...
@@ -3290,7 +3290,7 @@ static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsy
...
@@ -3290,7 +3290,7 @@ static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsy
return
false
;
return
false
;
ret
=
cgroup_set
(
c
->
name
,
c
->
config_path
,
subsys
,
value
);
ret
=
cgroup_set
(
c
->
name
,
c
->
config_path
,
subsys
,
value
);
if
(
ret
==
-
ENOCGROUP2
)
{
if
(
ret
<
0
&&
ERRNO_IS_NOT_SUPPORTED
(
ret
)
)
{
cgroup_ops
=
cgroup_init
(
c
->
lxc_conf
);
cgroup_ops
=
cgroup_init
(
c
->
lxc_conf
);
if
(
!
cgroup_ops
)
if
(
!
cgroup_ops
)
return
false
;
return
false
;
...
@@ -3315,7 +3315,7 @@ static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys
...
@@ -3315,7 +3315,7 @@ static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys
return
-
1
;
return
-
1
;
ret
=
cgroup_get
(
c
->
name
,
c
->
config_path
,
subsys
,
retv
,
inlen
);
ret
=
cgroup_get
(
c
->
name
,
c
->
config_path
,
subsys
,
retv
,
inlen
);
if
(
ret
==
-
ENOCGROUP2
)
{
if
(
ret
<
0
&&
ERRNO_IS_NOT_SUPPORTED
(
ret
)
)
{
cgroup_ops
=
cgroup_init
(
c
->
lxc_conf
);
cgroup_ops
=
cgroup_init
(
c
->
lxc_conf
);
if
(
!
cgroup_ops
)
if
(
!
cgroup_ops
)
return
-
1
;
return
-
1
;
...
...
src/lxc/macro.h
View file @
2ed90529
...
@@ -700,43 +700,6 @@ enum {
...
@@ -700,43 +700,6 @@ enum {
(b) = __tmp; \
(b) = __tmp; \
} while (0)
} while (0)
#define MAX_ERRNO 4095
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
static
inline
void
*
ERR_PTR
(
long
error
)
{
return
(
void
*
)
error
;
}
static
inline
long
PTR_ERR
(
const
void
*
ptr
)
{
return
(
long
)
ptr
;
}
static
inline
long
IS_ERR
(
const
void
*
ptr
)
{
return
IS_ERR_VALUE
((
unsigned
long
)
ptr
);
}
static
inline
long
IS_ERR_OR_NULL
(
const
void
*
ptr
)
{
return
!
ptr
||
IS_ERR_VALUE
((
unsigned
long
)
ptr
);
}
static
inline
void
*
ERR_CAST
(
const
void
*
ptr
)
{
return
(
void
*
)
ptr
;
}
static
inline
int
PTR_RET
(
const
void
*
ptr
)
{
if
(
IS_ERR
(
ptr
))
return
PTR_ERR
(
ptr
);
else
return
0
;
}
#define min(x, y) \
#define min(x, y) \
({ \
({ \
typeof(x) _min1 = (x); \
typeof(x) _min1 = (x); \
...
...
src/lxc/memory_utils.h
View file @
2ed90529
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
#include <unistd.h>
#include <unistd.h>
#include "macro.h"
#include "macro.h"
#include "error_utils.h"
#define define_cleanup_function(type, cleaner) \
#define define_cleanup_function(type, cleaner) \
static inline void cleaner##_function(type *ptr) \
static inline void cleaner##_function(type *ptr) \
...
...
src/lxc/terminal.c
View file @
2ed90529
...
@@ -1078,7 +1078,7 @@ int lxc_terminal_ptx_cb(int fd, uint32_t events, void *cbdata,
...
@@ -1078,7 +1078,7 @@ int lxc_terminal_ptx_cb(int fd, uint32_t events, void *cbdata,
int
lxc_terminal_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
int
*
ptxfd
)
int
lxc_terminal_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
int
*
ptxfd
)
{
{
return
lxc_cmd_
console
(
c
->
name
,
ttynum
,
ptxfd
,
c
->
config_path
);
return
lxc_cmd_
get_tty_fd
(
c
->
name
,
ttynum
,
ptxfd
,
c
->
config_path
);
}
}
int
lxc_console
(
struct
lxc_container
*
c
,
int
ttynum
,
int
lxc_console
(
struct
lxc_container
*
c
,
int
ttynum
,
...
@@ -1094,7 +1094,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
...
@@ -1094,7 +1094,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
};
};
int
istty
=
0
;
int
istty
=
0
;
ttyfd
=
lxc_cmd_
console
(
c
->
name
,
&
ttynum
,
&
ptxfd
,
c
->
config_path
);
ttyfd
=
lxc_cmd_
get_tty_fd
(
c
->
name
,
&
ttynum
,
&
ptxfd
,
c
->
config_path
);
if
(
ttyfd
<
0
)
if
(
ttyfd
<
0
)
return
-
1
;
return
-
1
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment