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
cca31bf0
Unverified
Commit
cca31bf0
authored
Feb 25, 2021
by
Stéphane Graber
Committed by
GitHub
Feb 25, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3697 from brauner/2021-02-25/fixes
commands: improvements and fixes
parents
2be31fed
885bb002
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
534 additions
and
356 deletions
+534
-356
af_unix.c
src/lxc/af_unix.c
+52
-5
af_unix.h
src/lxc/af_unix.h
+76
-3
commands.c
src/lxc/commands.c
+305
-324
commands.h
src/lxc/commands.h
+22
-4
log.h
src/lxc/log.h
+32
-4
macro.h
src/lxc/macro.h
+25
-0
start.c
src/lxc/start.c
+1
-1
lxc-test-lxc-attach
src/tests/lxc-test-lxc-attach
+20
-15
lxc-test-unpriv
src/tests/lxc-test-unpriv
+1
-0
No files found.
src/lxc/af_unix.c
View file @
cca31bf0
...
...
@@ -113,7 +113,7 @@ int lxc_abstract_unix_connect(const char *path)
}
int
lxc_abstract_unix_send_fds_iov
(
int
fd
,
const
int
*
sendfds
,
int
num_sendfds
,
struct
iovec
*
iov
,
size_t
iovlen
)
struct
iovec
*
const
iov
,
size_t
iovlen
)
{
__do_free
char
*
cmsgbuf
=
NULL
;
int
ret
;
...
...
@@ -176,6 +176,12 @@ static ssize_t lxc_abstract_unix_recv_fds_iov(int fd,
size_t
cmsgbufsize
=
CMSG_SPACE
(
sizeof
(
struct
ucred
))
+
CMSG_SPACE
(
ret_fds
->
fd_count_max
*
sizeof
(
int
));
if
(
ret_fds
->
flags
&
~
UNIX_FDS_ACCEPT_MASK
)
return
ret_errno
(
EINVAL
);
if
(
hweight32
((
ret_fds
->
flags
&
~
UNIX_FDS_ACCEPT_NONE
))
>
1
)
return
ret_errno
(
EINVAL
);
cmsgbuf
=
zalloc
(
cmsgbufsize
);
if
(
!
cmsgbuf
)
return
ret_errno
(
ENOMEM
);
...
...
@@ -202,7 +208,7 @@ again:
if
(
cmsg
->
cmsg_level
==
SOL_SOCKET
&&
cmsg
->
cmsg_type
==
SCM_RIGHTS
)
{
__u32
idx
;
/*
* This causes some compilers to complain
g
about
* This causes some compilers to complain about
* increased alignment requirements but I haven't found
* a better way to deal with this yet. Suggestions
* welcome!
...
...
@@ -225,7 +231,22 @@ again:
return
syserrno_set
(
-
EFBIG
,
"Received excessive number of file descriptors"
);
}
if
(
msg
.
msg_flags
&
MSG_CTRUNC
)
{
for
(
idx
=
0
;
idx
<
num_raw
;
idx
++
)
close
(
fds_raw
[
idx
]);
return
syserrno_set
(
-
EFBIG
,
"Control message was truncated; closing all fds and rejecting incomplete message"
);
}
if
(
ret_fds
->
fd_count_max
>
num_raw
)
{
if
(
!
(
ret_fds
->
flags
&
UNIX_FDS_ACCEPT_LESS
))
{
for
(
idx
=
0
;
idx
<
num_raw
;
idx
++
)
close
(
fds_raw
[
idx
]);
return
syserrno_set
(
-
EINVAL
,
"Received fewer file descriptors than we expected %u != %u"
,
ret_fds
->
fd_count_max
,
num_raw
);
}
/*
* Make sure any excess entries in the fd array
* are set to -EBADF so our cleanup functions
...
...
@@ -234,16 +255,33 @@ again:
for
(
idx
=
num_raw
;
idx
<
ret_fds
->
fd_count_max
;
idx
++
)
ret_fds
->
fd
[
idx
]
=
-
EBADF
;
WARN
(
"Received fewer file descriptors than we expected %u != %u"
,
ret_fds
->
fd_count_max
,
num_raw
)
;
ret_fds
->
flags
|=
UNIX_FDS_RECEIVED_LESS
;
}
else
if
(
ret_fds
->
fd_count_max
<
num_raw
)
{
if
(
!
(
ret_fds
->
flags
&
UNIX_FDS_ACCEPT_MORE
))
{
for
(
idx
=
0
;
idx
<
num_raw
;
idx
++
)
close
(
fds_raw
[
idx
]);
return
syserrno_set
(
-
EINVAL
,
"Received more file descriptors than we expected %u != %u"
,
ret_fds
->
fd_count_max
,
num_raw
);
}
/* Make sure we close any excess fds we received. */
for
(
idx
=
ret_fds
->
fd_count_max
;
idx
<
num_raw
;
idx
++
)
close
(
fds_raw
[
idx
]);
WARN
(
"Received more file descriptors than we expected %u != %u"
,
ret_fds
->
fd_count_max
,
num_raw
);
/* Cap the number of received file descriptors. */
num_raw
=
ret_fds
->
fd_count_max
;
ret_fds
->
flags
|=
UNIX_FDS_RECEIVED_MORE
;
}
else
{
ret_fds
->
flags
|=
UNIX_FDS_RECEIVED_EXACT
;
}
if
(
hweight32
((
ret_fds
->
flags
&
~
UNIX_FDS_ACCEPT_MASK
))
>
1
)
{
for
(
idx
=
0
;
idx
<
num_raw
;
idx
++
)
close
(
fds_raw
[
idx
]);
return
syserrno_set
(
-
EINVAL
,
"Invalid flag combination; closing to not risk leaking fds %u != %u"
,
ret_fds
->
fd_count_max
,
num_raw
);
}
memcpy
(
ret_fds
->
fd
,
CMSG_DATA
(
cmsg
),
num_raw
*
sizeof
(
int
));
...
...
@@ -252,6 +290,15 @@ again:
}
}
if
(
ret_fds
->
fd_count_ret
==
0
)
{
ret_fds
->
flags
|=
UNIX_FDS_RECEIVED_NONE
;
/* We expected to receive file descriptors. */
if
((
ret_fds
->
flags
&
UNIX_FDS_ACCEPT_MASK
)
&&
!
(
ret_fds
->
flags
&
UNIX_FDS_ACCEPT_NONE
))
return
syserrno_set
(
-
EINVAL
,
"Received no file descriptors"
);
}
return
ret
;
}
...
...
src/lxc/af_unix.h
View file @
cca31bf0
...
...
@@ -12,15 +12,88 @@
#include "macro.h"
#include "memory_utils.h"
#define KERNEL_SCM_MAX_FD 253
/* Allow the caller to set expectations. */
/*
* UNIX_FDS_ACCEPT_EXACT will only succeed if the exact amount of fds has been
* received (unless combined with UNIX_FDS_ACCEPT_NONE).
*/
#define UNIX_FDS_ACCEPT_EXACT ((__u32)(1 << 0))
/* default */
/*
* UNIX_FDS_ACCEPT_LESS will also succeed if less than the requested number of
* fd has been received. If the UNIX_FDS_ACCEPT_NONE flag is not raised than at
* least one fd must be received.
* */
#define UNIX_FDS_ACCEPT_LESS ((__u32)(1 << 1))
/*
* UNIX_FDS_ACCEPT_MORE will also succeed if more than the requested number of
* fds have been received. Any additional fds will be silently closed. If the
* UNIX_FDS_ACCEPT_NONE flag is not raised than at least one fd must be
* received.
*/
#define UNIX_FDS_ACCEPT_MORE ((__u32)(1 << 2))
/* wipe any extra fds */
/*
*
Technically 253 is the kernel limit but we want to the struct to be a
*
multiple of 8
.
*
UNIX_FDS_ACCEPT_NONE can be specified with any of the above flags and
*
indicates that the caller will accept no file descriptors to be received
.
*/
#define
KERNEL_SCM_MAX_FD 252
#define
UNIX_FDS_ACCEPT_NONE ((__u32)(1 << 3))
/* UNIX_FDS_ACCEPT_MASK is the value of all the above flags or-ed together. */
#define UNIX_FDS_ACCEPT_MASK (UNIX_FDS_ACCEPT_EXACT | UNIX_FDS_ACCEPT_LESS | UNIX_FDS_ACCEPT_MORE | UNIX_FDS_ACCEPT_NONE)
/* Allow the callee to communicate reality. */
/* UNIX_FDS_RECEIVED_EXACT indicates that the exact number of fds was received. */
#define UNIX_FDS_RECEIVED_EXACT ((__u32)(1 << 16))
/*
* UNIX_FDS_RECEIVED_LESS indicates that less than the requested number of fd
* has been received.
*/
#define UNIX_FDS_RECEIVED_LESS ((__u32)(1 << 17))
/*
* UNIX_FDS_RECEIVED_MORE indicates that more than the requested number of fd
* has been received.
*/
#define UNIX_FDS_RECEIVED_MORE ((__u32)(1 << 18))
/* UNIX_FDS_RECEIVED_NONE indicates that no fds have been received. */
#define UNIX_FDS_RECEIVED_NONE ((__u32)(1 << 19))
/**
* Defines a generic struct to receive file descriptors from unix sockets.
* @fd_count_max : Either the exact or maximum number of file descriptors the
* caller is willing to accept. Must be smaller than
* KERNEL_SCM_MAX_FDs; larger values will be rejected.
* Filled in by the caller.
* @fd_count_ret : The actually received number of file descriptors.
* Filled in by the callee.
* @flags : Flags to negotiate expectations about the number of file
* descriptors to receive.
* Filled in by the caller and callee. The caller's flag space
* is UNIX_FDS_ACCEPT_* other values will be rejected. The
* caller may only set one of {EXACT, LESS, MORE}. In addition
* they can raise the NONE flag. Any combination of {EXACT,
* LESS, MORE} will be rejected.
* The callee's flag space is UNIX_FDS_RECEIVED_*. Only ever
* one of those values will be set.
* @fd : Array to store received file descriptors into. Filled by the
* callee on success. If less file descriptors are received
* than requested in @fd_count_max the callee will ensure that
* all additional slots will be set to -EBADF. Nonetheless, the
* caller should only ever use @fd_count_ret to iterate through
* @fd after a successful receive.
*/
struct
unix_fds
{
__u32
fd_count_max
;
__u32
fd_count_ret
;
__u32
flags
;
__s32
fd
[
KERNEL_SCM_MAX_FD
];
}
__attribute__
((
aligned
(
8
)));
...
...
src/lxc/commands.c
View file @
cca31bf0
...
...
@@ -118,6 +118,38 @@ static int __transfer_cgroup_fd(struct unix_fds *fds, struct cgroup_fd *fd)
return
0
;
}
static
ssize_t
lxc_cmd_rsp_recv_fds
(
int
fd_sock
,
struct
unix_fds
*
fds
,
struct
lxc_cmd_rsp
*
rsp
,
const
char
*
cur_cmdstr
)
{
ssize_t
ret
;
ret
=
lxc_abstract_unix_recv_fds
(
fd_sock
,
fds
,
rsp
,
sizeof
(
*
rsp
));
if
(
ret
<
0
)
return
ret
;
/*
* If we end up here with fewer or more file descriptors the caller
* must have set flags to indicate that they are fine with this.
* Otherwise the call would have failed.
*/
if
(
fds
->
flags
&
UNIX_FDS_RECEIVED_EXACT
)
return
log_info
(
ret
,
"Received exact number of file descriptors %u == %u"
,
fds
->
fd_count_max
,
fds
->
fd_count_ret
);
if
(
fds
->
flags
&
UNIX_FDS_RECEIVED_LESS
)
return
log_info
(
ret
,
"Received less file descriptors %u < %u"
,
fds
->
fd_count_ret
,
fds
->
fd_count_max
);
if
(
fds
->
flags
&
UNIX_FDS_RECEIVED_MORE
)
return
log_info
(
ret
,
"Received more file descriptors (excessive fds were automatically closed) %u > %u"
,
fds
->
fd_count_ret
,
fds
->
fd_count_max
);
INFO
(
"Command
\"
%s
\"
received response"
,
cur_cmdstr
);
return
ret
;
}
/*
* lxc_cmd_rsp_recv: Receive a response to a command
*
...
...
@@ -134,15 +166,17 @@ static int __transfer_cgroup_fd(struct unix_fds *fds, struct cgroup_fd *fd)
* As a special case, the response for LXC_CMD_GET_TTY_FD is created here as
* it contains an fd for the ptx pty passed through the unix socket.
*/
static
in
t
lxc_cmd_rsp_recv
(
int
sock
,
struct
lxc_cmd_rr
*
cmd
)
static
ssize_
t
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
){
.
fd
[
0
...
KERNEL_SCM_MAX_FD
-
1
]
=
-
EBADF
,
};
struct
lxc_cmd_rsp
*
rsp
=
&
cmd
->
rsp
;
int
cur_cmd
=
cmd
->
req
.
cmd
,
fret
=
0
;
int
cur_cmd
=
cmd
->
req
.
cmd
;
const
char
*
cur_cmdstr
;
int
ret
;
ssize_t
bytes_recv
;
/*
* Determine whether this command will receive file descriptors and how
...
...
@@ -163,12 +197,24 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
case
LXC_CMD_GET_SECCOMP_NOTIFY_FD
:
__fallthrough
;
case
LXC_CMD_GET_DEVPTS_FD
:
__fallthrough
;
fds
->
fd_count_max
=
1
;
/*
* The kernel might not support the required features or the
* server might be too old.
*/
fds
->
flags
=
UNIX_FDS_ACCEPT_EXACT
|
UNIX_FDS_ACCEPT_NONE
;
break
;
case
LXC_CMD_GET_TTY_FD
:
/*
* The requested terminal can be busy so it's perfectly fine
* for LXC_CMD_GET_TTY to receive no file descriptor.
*/
fds
->
fd_count_max
=
1
;
fds
->
flags
=
UNIX_FDS_ACCEPT_EXACT
|
UNIX_FDS_ACCEPT_NONE
;
break
;
case
LXC_CMD_GET_CGROUP_CTX
:
fds
->
fd_count_max
=
CGROUP_CTX_MAX_FD
;
fds
->
flags
|=
UNIX_FDS_ACCEPT_LESS
;
break
;
default:
fds
->
fd_count_max
=
0
;
...
...
@@ -176,22 +222,9 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
}
/* Receive the first response including file descriptors if any. */
ret
=
lxc_abstract_unix_recv_fds
(
sock
,
fds
,
rsp
,
sizeof
(
*
rsp
));
if
(
ret
<
0
)
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
)
{
WARN
(
"Command
\"
%s
\"
received response"
,
cur_cmdstr
);
}
else
if
(
fds
->
fd_count_ret
==
0
)
{
TRACE
(
"Command
\"
%s
\"
received response without any of the expected %u file descriptors"
,
cur_cmdstr
,
fds
->
fd_count_max
);
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
);
}
bytes_recv
=
lxc_cmd_rsp_recv_fds
(
sock
,
fds
,
rsp
,
cur_cmdstr
);
if
(
bytes_recv
<
0
)
return
bytes_recv
;
/*
* Ensure that no excessive data is sent unless someone retrieves the
...
...
@@ -199,7 +232,7 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
*/
if
((
rsp
->
datalen
>
LXC_CMD_DATA_MAX
)
&&
(
cur_cmd
!=
LXC_CMD_CONSOLE_LOG
))
return
syserrno_set
(
fret
?:
-
E2BIG
,
"Response data for command
\"
%s
\"
is too long: %d bytes > %d"
,
return
syserrno_set
(
-
E2BIG
,
"Response data for command
\"
%s
\"
is too long: %d bytes > %d"
,
cur_cmdstr
,
rsp
->
datalen
,
LXC_CMD_DATA_MAX
);
/*
...
...
@@ -216,23 +249,20 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
case
LXC_CMD_GET_DEVPTS_FD
:
/* no data */
__fallthrough
;
case
LXC_CMD_GET_SECCOMP_NOTIFY_FD
:
/* no data */
if
(
!
fret
)
rsp
->
data
=
INT_TO_PTR
(
move_fd
(
fds
->
fd
[
0
]));
/* Return for any command that doesn't expect additional data. */
return
log_debug
(
fret
?:
ret
,
"Finished processing
\"
%s
\"
with file descriptor %d"
,
cur_cmdstr
,
PTR_TO_INT
(
rsp
->
data
));
rsp
->
data
=
INT_TO_PTR
(
move_fd
(
fds
->
fd
[
0
]));
return
log_debug
(
0
,
"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
(
-
EINVAL
,
"Invalid response size from server for
\"
%s
\"
"
,
cur_cmdstr
);
/* Don't pointlessly allocate. */
rsp
->
data
=
(
void
*
)
cmd
->
req
.
data
;
break
;
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
);
return
syserrno_set
(
-
EINVAL
,
"Invalid response size from server for
\"
%s
\"
"
,
cur_cmdstr
);
/* Don't pointlessly allocate. */
rsp
->
data
=
(
void
*
)
cmd
->
req
.
data
;
...
...
@@ -240,14 +270,14 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
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
* rsp->ret is < 0 when the peer permission check failed
.
*/
if
(
ret
==
0
||
rsp
->
ret
<
0
)
if
(
bytes_recv
==
0
||
rsp
->
ret
<
0
)
return
0
;
__private_ptr
=
malloc
(
sizeof
(
struct
lxc_cmd_tty_rsp_data
));
if
(
!
__private_ptr
)
return
syserrno_set
(
fret
?:
-
ENOMEM
,
"Failed to receive response for command
\"
%s
\"
"
,
cur_cmdstr
);
return
syserrno_set
(
-
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
);
...
...
@@ -267,48 +297,40 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
break
;
}
if
(
rsp
->
datalen
==
0
)
{
DEBUG
(
"Command
\"
%s
\"
requested no additional data"
,
cur_cmdstr
);
if
(
rsp
->
datalen
>
0
)
{
int
err
;
/*
* 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.
* All commands ending up here expect data so rsp->data must be valid.
* Either static or allocated memory.
*/
goto
no_data
;
}
/*
* All commands ending up here expect data so rsp->data must be valid.
* Either static or allocated memory.
*/
if
(
!
rsp
->
data
)
return
syserrno_set
(
fret
?:
-
ENOMEM
,
"Failed to prepare response buffer for command
\"
%s
\"
"
,
cur_cmdstr
);
ret
=
lxc_recv_nointr
(
sock
,
rsp
->
data
,
rsp
->
datalen
,
0
);
if
(
ret
!=
rsp
->
datalen
)
return
syserrno
(
-
errno
,
"Failed to receive response data for command
\"
%s
\"
: %d != %d"
,
cur_cmdstr
,
ret
,
rsp
->
datalen
);
switch
(
cur_cmd
)
{
case
LXC_CMD_GET_CGROUP_CTX
:
if
(
!
fret
)
ret
=
__transfer_cgroup_ctx_fds
(
fds
,
rsp
->
data
);
/* Make sure any received fds are wiped by us. */
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
;
if
(
!
rsp
->
data
)
return
syserrno_set
(
-
ENOMEM
,
"Failed to prepare response buffer for command
\"
%s
\"
"
,
cur_cmdstr
);
bytes_recv
=
lxc_recv_nointr
(
sock
,
rsp
->
data
,
rsp
->
datalen
,
0
);
if
(
bytes_recv
!=
rsp
->
datalen
)
return
syserrno
(
-
errno
,
"Failed to receive response data for command
\"
%s
\"
: %zd != %d"
,
cur_cmdstr
,
bytes_recv
,
rsp
->
datalen
);
switch
(
cur_cmd
)
{
case
LXC_CMD_GET_CGROUP_CTX
:
err
=
__transfer_cgroup_ctx_fds
(
fds
,
rsp
->
data
);
break
;
case
LXC_CMD_GET_CGROUP_FD
:
__fallthrough
;
case
LXC_CMD_GET_LIMIT_CGROUP_FD
:
err
=
__transfer_cgroup_fd
(
fds
,
rsp
->
data
);
break
;
default:
err
=
0
;
}
if
(
err
<
0
)
return
syserrno
(
err
,
"Failed to transfer file descriptors for command
\"
%s
\"
"
,
cur_cmdstr
);
}
no_data:
if
(
!
fret
&&
ret
>=
0
)
move_ptr
(
__private_ptr
);
return
fret
?:
ret
;
move_ptr
(
__private_ptr
);
return
bytes_recv
;
}
/*
...
...
@@ -376,6 +398,17 @@ static inline int rsp_one_fd(int fd, int fd_send, struct lxc_cmd_rsp *rsp)
return
LXC_CMD_REAP_CLIENT_FD
;
}
static
inline
int
rsp_one_fd_keep
(
int
fd
,
int
fd_send
,
struct
lxc_cmd_rsp
*
rsp
)
{
int
ret
;
ret
=
rsp_one_fd
(
fd
,
fd_send
,
rsp
);
if
(
ret
==
LXC_CMD_REAP_CLIENT_FD
)
ret
=
LXC_CMD_KEEP_CLIENT_FD
;
return
ret
;
}
__access_r
(
3
,
2
)
static
int
rsp_many_fds
(
int
fd
,
__u32
fds_len
,
const
__s32
fds
[
static
2
],
struct
lxc_cmd_rsp
*
rsp
)
...
...
@@ -456,12 +489,12 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
* the slot with lxc_cmd_fd_cleanup(). The socket fd will be returned in the
* cmd response structure.
*/
static
int
lxc_cmd
(
const
char
*
name
,
struct
lxc_cmd_rr
*
cmd
,
int
*
stopped
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
static
ssize_t
lxc_cmd
(
const
char
*
name
,
struct
lxc_cmd_rr
*
cmd
,
bool
*
stopped
,
const
char
*
lxcpath
,
const
char
*
hashed_sock_name
)
{
__do_close
int
client_fd
=
-
EBADF
;
int
ret
=
-
1
;
bool
stay_connected
=
false
;
ssize_t
ret
;
if
(
cmd
->
req
.
cmd
==
LXC_CMD_GET_TTY_FD
||
cmd
->
req
.
cmd
==
LXC_CMD_ADD_STATE_CLIENT
)
...
...
@@ -471,11 +504,10 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
client_fd
=
lxc_cmd_send
(
name
,
cmd
,
lxcpath
,
hashed_sock_name
);
if
(
client_fd
<
0
)
{
if
(
errno
==
ECONNREFUSED
||
errno
==
EPIPE
)
if
(
IN_SET
(
errno
,
ECONNREFUSED
,
EPIPE
)
)
*
stopped
=
1
;
return
log_trace_errno
(
-
1
,
errno
,
"Command
\"
%s
\"
failed to connect command socket"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
return
systrace
(
-
errno
,
"Command
\"
%s
\"
failed to connect command socket"
,
lxc_cmd_str
(
cmd
->
req
.
cmd
));
}
ret
=
lxc_cmd_rsp_recv
(
client_fd
,
cmd
);
...
...
@@ -493,10 +525,11 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
int
lxc_try_cmd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
stopped
,
ret
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_INIT_PID
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_INIT_PID
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
stopped
)
...
...
@@ -508,7 +541,8 @@ int lxc_try_cmd(const char *name, const char *lxcpath)
if
(
ret
>
0
)
return
0
;
/* At this point we weren't denied access, and the container *was*
/*
* At this point we weren't denied access, and the container *was*
* started. There was some inexplicable error in the protocol. I'm not
* clear on whether we should return -1 here, but we didn't receive a
* -EACCES, so technically it's not that we're not allowed to control
...
...
@@ -552,16 +586,12 @@ static int validate_string_request(int fd, const struct lxc_cmd_req *req)
*/
pid_t
lxc_cmd_get_init_pid
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
pid_t
pid
=
-
1
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_INIT_PID
},
.
rsp
=
{
.
data
=
PID_TO_PTR
(
pid
)
}
};
bool
stopped
=
false
;
ssize_t
ret
;
pid_t
pid
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_INIT_PID
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -571,7 +601,8 @@ pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
if
(
pid
<
0
)
return
-
1
;
/* We need to assume that pid_t can actually hold any pid given to us
/*
* We need to assume that pid_t can actually hold any pid given to us
* by the kernel. If it can't it's a libc bug.
*/
return
(
pid_t
)
pid
;
...
...
@@ -590,28 +621,22 @@ static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
int
lxc_cmd_get_init_pidfd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
pidfd
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_INIT_PIDFD
,
},
.
rsp
=
{
.
data
=
INT_TO_PTR
(
-
EBADF
),
.
ret
=
ENOSYS
,
},
};
bool
stopped
=
false
;
int
pidfd
,
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_INIT_PIDFD
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
return
log_debug_errno
(
-
1
,
errno
,
"Failed to process init pidfd command"
);
return
sysdebug
(
"Failed to process init pidfd command"
);
if
(
cmd
.
rsp
.
ret
<
0
)
return
sys
errno
_set
(
cmd
.
rsp
.
ret
,
"Failed to receive init pidfd"
);
return
sys
debug
_set
(
cmd
.
rsp
.
ret
,
"Failed to receive init pidfd"
);
pidfd
=
PTR_TO_INT
(
cmd
.
rsp
.
data
);
if
(
pidfd
<
0
)
return
sys
errno
_set
(
pidfd
,
"Failed to receive init pidfd"
);
return
sys
debug
_set
(
pidfd
,
"Failed to receive init pidfd"
);
return
pidfd
;
}
...
...
@@ -633,12 +658,11 @@ static int lxc_cmd_get_init_pidfd_callback(int fd, struct lxc_cmd_req *req,
int
lxc_cmd_get_devpts_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_DEVPTS_FD
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_DEVPTS_FD
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -668,12 +692,11 @@ static int lxc_cmd_get_devpts_fd_callback(int fd, struct lxc_cmd_req *req,
int
lxc_cmd_get_seccomp_notify_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
#ifdef HAVE_SECCOMP_NOTIFY
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_SECCOMP_NOTIFY_FD
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_SECCOMP_NOTIFY_FD
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -710,17 +733,12 @@ 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
,
size_t
size_ret_ctx
,
struct
cgroup_ctx
*
ret_ctx
)
{
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_CGROUP_CTX
,
.
datalen
=
size_ret_ctx
,
.
data
=
ret_ctx
,
},
.
rsp
=
{
.
ret
=
-
ENOSYS
,
},
};
int
ret
,
stopped
;
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_CGROUP_CTX
);
lxc_cmd_data
(
&
cmd
,
size_ret_ctx
,
ret_ctx
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -741,7 +759,7 @@ static int lxc_cmd_get_cgroup_ctx_callback(int fd, struct lxc_cmd_req *req,
};
struct
cgroup_ops
*
cgroup_ops
=
handler
->
cgroup_ops
;
struct
cgroup_ctx
ctx_server
=
{};
in
t
ret
;
ssize_
t
ret
;
ret
=
copy_struct_from_client
(
sizeof
(
struct
cgroup_ctx
),
&
ctx_server
,
req
->
datalen
,
req
->
data
);
...
...
@@ -770,12 +788,11 @@ static int lxc_cmd_get_cgroup_ctx_callback(int fd, struct lxc_cmd_req *req,
*/
int
lxc_cmd_get_clone_flags
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_CLONE_FLAGS
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_CLONE_FLAGS
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -795,23 +812,18 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
}
static
char
*
lxc_cmd_get_cgroup_path_do
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
subsystem
,
lxc_cmd_t
command
)
static
char
*
lxc_cmd_get_cgroup_path_callback
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
controller
,
lxc_cmd_t
command
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
command
,
.
data
=
subsystem
,
.
datalen
=
0
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
cmd
.
req
.
data
=
subsystem
;
cmd
.
req
.
datalen
=
0
;
if
(
subsystem
)
cmd
.
req
.
datalen
=
strlen
(
subsystem
)
+
1
;
lxc_cmd_init
(
&
cmd
,
command
);
if
(
controller
)
lxc_cmd_data
(
&
cmd
,
strlen
(
controller
)
+
1
,
controller
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -826,9 +838,9 @@ static char *lxc_cmd_get_cgroup_path_do(const char *name, const char *lxcpath,
* it sees an unknown command and just closes the
* socket, sending us an EOF.
*/
return
lxc_cmd_get_cgroup_path_
do
(
name
,
lxcpath
,
subsystem
,
LXC_CMD_GET_CGROUP
);
return
lxc_cmd_get_cgroup_path_
callback
(
name
,
lxcpath
,
controller
,
LXC_CMD_GET_CGROUP
);
}
return
NULL
;
}
...
...
@@ -841,50 +853,50 @@ static char *lxc_cmd_get_cgroup_path_do(const char *name, const char *lxcpath,
/*
* lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
* particular
subsystem
. This is the cgroup path relative to the root
* particular
controller
. This is the cgroup path relative to the root
* of the cgroup filesystem.
*
* @name : name of container to connect to
* @lxcpath : the lxcpath in which the container is running
* @
subsystem : the subsystem
being asked about
* @
controller : the controller
being asked about
*
* Returns the path on success, NULL on failure. The caller must free() the
* returned path.
*/
char
*
lxc_cmd_get_cgroup_path
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
subsystem
)
const
char
*
controller
)
{
return
lxc_cmd_get_cgroup_path_
do
(
name
,
lxcpath
,
subsystem
,
LXC_CMD_GET_CGROUP
);
return
lxc_cmd_get_cgroup_path_
callback
(
name
,
lxcpath
,
controller
,
LXC_CMD_GET_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
controller
. This is the cgroup path relative to the
* 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 path prefix
* set.
*
* @name : name of container to connect to
* @lxcpath : the lxcpath in which the container is running
* @
subsystem : the subsystem
being asked about
* @
controller : the controller
being asked about
*
* Returns the path on success, NULL on failure. The caller must free() the
* returned path.
*/
char
*
lxc_cmd_get_limit_cgroup_path
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
subsystem
)
const
char
*
controller
)
{
return
lxc_cmd_get_cgroup_path_
do
(
name
,
lxcpath
,
subsystem
,
LXC_CMD_GET_LIMIT_CGROUP
);
return
lxc_cmd_get_cgroup_path_
callback
(
name
,
lxcpath
,
controller
,
LXC_CMD_GET_LIMIT_CGROUP
);
}
static
int
lxc_cmd_get_cgroup_callback_do
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
,
bool
limiting_cgroup
)
static
int
__lxc_cmd_get_cgroup_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
,
bool
limiting_cgroup
)
{
in
t
ret
;
ssize_
t
ret
;
const
char
*
path
;
const
void
*
reqdata
;
struct
lxc_cmd_rsp
rsp
;
...
...
@@ -919,14 +931,14 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
{
return
lxc_cmd_get_cgroup_callback_do
(
fd
,
req
,
handler
,
descr
,
false
);
return
__lxc_cmd_get_cgroup_callback
(
fd
,
req
,
handler
,
descr
,
false
);
}
static
int
lxc_cmd_get_limit_cgroup_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
{
return
lxc_cmd_get_cgroup_callback_do
(
fd
,
req
,
handler
,
descr
,
true
);
return
__lxc_cmd_get_cgroup_callback
(
fd
,
req
,
handler
,
descr
,
true
);
}
/*
...
...
@@ -942,13 +954,15 @@ static int lxc_cmd_get_limit_cgroup_callback(int fd, struct lxc_cmd_req *req,
char
*
lxc_cmd_get_config_item
(
const
char
*
name
,
const
char
*
item
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_CONFIG_ITEM
,
.
data
=
item
,
.
datalen
=
strlen
(
item
)
+
1
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
if
(
is_empty_string
(
item
))
return
NULL
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_CONFIG_ITEM
);
lxc_cmd_data
(
&
cmd
,
strlen
(
item
)
+
1
,
item
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1004,12 +1018,11 @@ out:
*/
int
lxc_cmd_get_state
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_STATE
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_STATE
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
&&
stopped
)
...
...
@@ -1048,12 +1061,11 @@ static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
*/
int
lxc_cmd_stop
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_STOP
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_STOP
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
{
...
...
@@ -1145,13 +1157,12 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
int
lxc_cmd_get_tty_fd
(
const
char
*
name
,
int
*
ttynum
,
int
*
fd
,
const
char
*
lxcpath
)
{
__do_free
struct
lxc_cmd_tty_rsp_data
*
rspdata
=
NULL
;
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_TTY_FD
,
.
data
=
INT_TO_PTR
(
*
ttynum
),
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_TTY_FD
);
lxc_cmd_data
(
&
cmd
,
ENCODE_INTO_PTR_LEN
,
INT_TO_PTR
(
*
ttynum
));
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1171,32 +1182,32 @@ int lxc_cmd_get_tty_fd(const char *name, int *ttynum, int *fd, const char *lxcpa
*
fd
=
rspdata
->
ptxfd
;
*
ttynum
=
rspdata
->
ttynum
;
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 %
z
d"
,
*
fd
,
rspdata
->
ttynum
,
ret
);
}
static
int
lxc_cmd_get_tty_fd_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
{
int
ptxfd
,
ret
;
struct
lxc_cmd_rsp
rsp
=
{
.
ret
=
-
EBADF
,
.
ret
=
-
EBADF
,
};
int
ttynum
=
PTR_TO_INT
(
req
->
data
)
;
int
ptxfd
,
ret
,
ttynum
;
ttynum
=
PTR_TO_INT
(
req
->
data
);
ptxfd
=
lxc_terminal_allocate
(
handler
->
conf
,
fd
,
&
ttynum
);
if
(
ptxfd
<
0
)
return
lxc_cmd_rsp_send_reap
(
fd
,
&
rsp
);
rsp
.
ret
=
0
;
rsp
.
data
=
INT_TO_PTR
(
ttynum
);
ret
=
lxc_abstract_unix_send_fds
(
fd
,
&
ptxfd
,
1
,
&
rsp
,
sizeof
(
rsp
)
);
ret
=
rsp_one_fd_keep
(
fd
,
ptxfd
,
&
rsp
);
if
(
ret
<
0
)
{
lxc_terminal_free
(
handler
->
conf
,
fd
);
return
ret
;
}
return
log_debug
(
0
,
"Send tty to client"
);
return
log_debug
(
ret
,
"Send tty to client"
);
}
/*
...
...
@@ -1208,12 +1219,11 @@ static int lxc_cmd_get_tty_fd_callback(int fd, struct lxc_cmd_req *req,
*/
char
*
lxc_cmd_get_name
(
const
char
*
hashed_sock_name
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_NAME
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_NAME
);
ret
=
lxc_cmd
(
NULL
,
&
cmd
,
&
stopped
,
NULL
,
hashed_sock_name
);
if
(
ret
<
0
)
...
...
@@ -1249,12 +1259,11 @@ static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
*/
char
*
lxc_cmd_get_lxcpath
(
const
char
*
hashed_sock_name
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_LXCPATH
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_LXCPATH
);
ret
=
lxc_cmd
(
NULL
,
&
cmd
,
&
stopped
,
NULL
,
hashed_sock_name
);
if
(
ret
<
0
)
...
...
@@ -1284,15 +1293,13 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
int
*
state_client_fd
)
{
__do_close
int
clientfd
=
-
EBADF
;
int
state
,
stopped
;
bool
stopped
=
false
;
int
state
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_ADD_STATE_CLIENT
,
.
data
=
states
,
.
datalen
=
(
sizeof
(
lxc_state_t
)
*
MAX_STATE
)
},
};
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_ADD_STATE_CLIENT
);
lxc_cmd_data
(
&
cmd
,
(
sizeof
(
lxc_state_t
)
*
MAX_STATE
),
states
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
states
[
STOPPED
]
!=
0
&&
stopped
!=
0
)
...
...
@@ -1353,23 +1360,22 @@ reap_fd:
int
lxc_cmd_add_bpf_device_cgroup
(
const
char
*
name
,
const
char
*
lxcpath
,
struct
device_item
*
device
)
{
int
stopped
=
0
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_ADD_BPF_DEVICE_CGROUP
,
.
data
=
device
,
.
datalen
=
sizeof
(
struct
device_item
),
},
};
int
ret
;
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
if
(
strlen
(
device
->
access
)
>
STRLITERALLEN
(
"rwm"
))
return
log_error_errno
(
-
1
,
EINVAL
,
"Invalid access mode specified %s"
,
device
->
access
);
return
syserrno_set
(
-
EINVAL
,
"Invalid access mode specified %s"
,
device
->
access
);
lxc_cmd_init
(
&
cmd
,
LXC_CMD_ADD_BPF_DEVICE_CGROUP
);
lxc_cmd_data
(
&
cmd
,
sizeof
(
struct
device_item
),
device
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
||
cmd
.
rsp
.
ret
<
0
)
return
log_error_errno
(
-
1
,
errno
,
"Failed to add new bpf device cgroup rule"
);
if
(
ret
<
0
)
return
syserrno_set
(
ret
,
"Failed to process new bpf device cgroup command"
);
if
(
cmd
.
rsp
.
ret
<
0
)
return
syserrno_set
(
cmd
.
rsp
.
ret
,
"Failed to add new bpf device cgroup rule"
);
return
0
;
}
...
...
@@ -1407,17 +1413,17 @@ out:
int
lxc_cmd_console_log
(
const
char
*
name
,
const
char
*
lxcpath
,
struct
lxc_console_log
*
log
)
{
int
ret
,
stopped
;
struct
lxc_cmd_console_log
data
;
bool
stopped
=
false
;
struct
lxc_cmd_console_log
data
=
{
.
clear
=
log
->
clear
,
.
read
=
log
->
read
,
.
read_max
=
*
log
->
read_max
,
};
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
data
.
clear
=
log
->
clear
;
data
.
read
=
log
->
read
;
data
.
read_max
=
*
log
->
read_max
;
cmd
.
req
.
cmd
=
LXC_CMD_CONSOLE_LOG
;
cmd
.
req
.
data
=
&
data
;
cmd
.
req
.
datalen
=
sizeof
(
struct
lxc_cmd_console_log
);
lxc_cmd_init
(
&
cmd
,
LXC_CMD_CONSOLE_LOG
);
lxc_cmd_data
(
&
cmd
,
sizeof
(
struct
lxc_cmd_console_log
),
&
data
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1435,8 +1441,8 @@ int lxc_cmd_console_log(const char *name, const char *lxcpath,
if
(
cmd
.
rsp
.
ret
<
0
)
return
cmd
.
rsp
.
ret
;
*
log
->
read_max
=
cmd
.
rsp
.
datalen
;
log
->
data
=
cmd
.
rsp
.
data
;
*
log
->
read_max
=
cmd
.
rsp
.
datalen
;
log
->
data
=
cmd
.
rsp
.
data
;
return
0
;
}
...
...
@@ -1483,14 +1489,12 @@ out:
int
lxc_cmd_serve_state_clients
(
const
char
*
name
,
const
char
*
lxcpath
,
lxc_state_t
state
)
{
int
stopped
;
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_SERVE_STATE_CLIENTS
,
.
data
=
INT_TO_PTR
(
state
)
},
};
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_SERVE_STATE_CLIENTS
);
lxc_cmd_data
(
&
cmd
,
ENCODE_INTO_PTR_LEN
,
INT_TO_PTR
(
state
));
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1521,13 +1525,12 @@ int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
{
#ifdef HAVE_SECCOMP_NOTIFY
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER
,
.
data
=
INT_TO_PTR
(
fd
),
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER
);
lxc_cmd_data
(
&
cmd
,
ENCODE_INTO_PTR_LEN
,
INT_TO_PTR
(
fd
));
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1581,13 +1584,12 @@ out:
int
lxc_cmd_freeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_FREEZE
,
.
data
=
INT_TO_PTR
(
timeout
),
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_FREEZE
);
lxc_cmd_data
(
&
cmd
,
ENCODE_INTO_PTR_LEN
,
INT_TO_PTR
(
timeout
));
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<=
0
||
cmd
.
rsp
.
ret
<
0
)
...
...
@@ -1614,13 +1616,12 @@ static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req,
int
lxc_cmd_unfreeze
(
const
char
*
name
,
const
char
*
lxcpath
,
int
timeout
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_UNFREEZE
,
.
data
=
INT_TO_PTR
(
timeout
),
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_UNFREEZE
);
lxc_cmd_data
(
&
cmd
,
ENCODE_INTO_PTR_LEN
,
INT_TO_PTR
(
timeout
));
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<=
0
||
cmd
.
rsp
.
ret
<
0
)
...
...
@@ -1648,17 +1649,12 @@ static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
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
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_CGROUP_FD
);
lxc_cmd_data
(
&
cmd
,
sizeof
(
struct
cgroup_fd
),
ret_fd
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1673,17 +1669,12 @@ int lxc_cmd_get_cgroup_fd(const char *name, const char *lxcpath,
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
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_LIMIT_CGROUP_FD
);
lxc_cmd_data
(
&
cmd
,
sizeof
(
struct
cgroup_fd
),
ret_fd
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1743,15 +1734,11 @@ static int lxc_cmd_get_limit_cgroup_fd_callback(int fd, struct lxc_cmd_req *req,
int
lxc_cmd_get_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_CGROUP2_FD
,
},
.
rsp
=
{
ret
=
-
ENOSYS
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_CGROUP2_FD
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1765,15 +1752,11 @@ int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
int
lxc_cmd_get_limit_cgroup2_fd
(
const
char
*
name
,
const
char
*
lxcpath
)
{
int
ret
,
stopped
;
struct
lxc_cmd_rr
cmd
=
{
.
req
=
{
.
cmd
=
LXC_CMD_GET_LIMIT_CGROUP2_FD
,
},
.
rsp
=
{
.
ret
=
-
ENOSYS
,
},
};
bool
stopped
=
false
;
ssize_t
ret
;
struct
lxc_cmd_rr
cmd
;
lxc_cmd_init
(
&
cmd
,
LXC_CMD_GET_LIMIT_CGROUP2_FD
);
ret
=
lxc_cmd
(
name
,
&
cmd
,
&
stopped
,
lxcpath
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -1785,10 +1768,10 @@ int lxc_cmd_get_limit_cgroup2_fd(const char *name, const char *lxcpath)
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
,
bool
limiting_cgroup
)
static
int
__lxc_cmd_get_cgroup2_fd_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
,
bool
limiting_cgroup
)
{
struct
lxc_cmd_rsp
rsp
=
{
.
ret
=
-
EINVAL
,
...
...
@@ -1815,16 +1798,14 @@ static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
{
return
lxc_cmd_get_cgroup2_fd_callback_do
(
fd
,
req
,
handler
,
descr
,
false
);
return
__lxc_cmd_get_cgroup2_fd_callback
(
fd
,
req
,
handler
,
descr
,
false
);
}
static
int
lxc_cmd_get_limit_cgroup2_fd_callback
(
int
fd
,
struct
lxc_cmd_req
*
req
,
struct
lxc_handler
*
handler
,
struct
lxc_epoll_descr
*
descr
)
{
return
lxc_cmd_get_cgroup2_fd_callback_do
(
fd
,
req
,
handler
,
descr
,
true
);
return
__lxc_cmd_get_cgroup2_fd_callback
(
fd
,
req
,
handler
,
descr
,
true
);
}
static
int
lxc_cmd_rsp_send_enosys
(
int
fd
,
int
id
)
...
...
@@ -2018,7 +1999,7 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
return
ret
;
}
int
lxc_
cmd
_init
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
suffix
)
int
lxc_
server
_init
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
suffix
)
{
__do_close
int
fd
=
-
EBADF
;
int
ret
;
...
...
src/lxc/commands.h
View file @
cca31bf0
...
...
@@ -3,6 +3,7 @@
#ifndef __LXC_COMMANDS_H
#define __LXC_COMMANDS_H
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
...
...
@@ -19,6 +20,7 @@
* have specific reasons to keep the file descriptor alive.
*/
#define LXC_CMD_REAP_CLIENT_FD 1
#define LXC_CMD_KEEP_CLIENT_FD 2
typedef
enum
{
LXC_CMD_GET_TTY_FD
=
0
,
...
...
@@ -56,6 +58,8 @@ struct lxc_cmd_req {
const
void
*
data
;
};
#define ENCODE_INTO_PTR_LEN 0
struct
lxc_cmd_rsp
{
int
ret
;
/* 0 on success, -errno on failure */
int
datalen
;
...
...
@@ -67,6 +71,20 @@ struct lxc_cmd_rr {
struct
lxc_cmd_rsp
rsp
;
};
static
inline
void
lxc_cmd_init
(
struct
lxc_cmd_rr
*
cmd
,
lxc_cmd_t
command
)
{
*
cmd
=
(
struct
lxc_cmd_rr
){
.
req
=
{.
cmd
=
command
},
.
rsp
=
{.
ret
=
-
ENOSYS
},
};
}
static
inline
void
lxc_cmd_data
(
struct
lxc_cmd_rr
*
cmd
,
int
len_data
,
const
void
*
data
)
{
cmd
->
req
.
data
=
data
;
cmd
->
req
.
datalen
=
len_data
;
}
struct
lxc_cmd_tty_rsp_data
{
int
ptxfd
;
int
ttynum
;
...
...
@@ -85,10 +103,10 @@ __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
* for a particular
subsystem
* for a particular
controller
*/
__hidden
extern
char
*
lxc_cmd_get_cgroup_path
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
subsystem
);
const
char
*
controller
);
__hidden
extern
int
lxc_cmd_get_clone_flags
(
const
char
*
name
,
const
char
*
lxcpath
);
__hidden
extern
char
*
lxc_cmd_get_config_item
(
const
char
*
name
,
const
char
*
item
,
const
char
*
lxcpath
);
...
...
@@ -122,7 +140,7 @@ __hidden extern int lxc_cmd_serve_state_clients(const char *name, const char *lx
struct
lxc_epoll_descr
;
struct
lxc_handler
;
__hidden
extern
int
lxc_
cmd
_init
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
suffix
);
__hidden
extern
int
lxc_
server
_init
(
const
char
*
name
,
const
char
*
lxcpath
,
const
char
*
suffix
);
__hidden
extern
int
lxc_cmd_mainloop_add
(
const
char
*
name
,
struct
lxc_epoll_descr
*
descr
,
struct
lxc_handler
*
handler
);
__hidden
extern
int
lxc_try_cmd
(
const
char
*
name
,
const
char
*
lxcpath
);
...
...
@@ -147,7 +165,7 @@ __hidden extern int lxc_cmd_get_cgroup_fd(const char *name, const char *lxcpath,
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
*
controller
);
__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
,
...
...
src/lxc/log.h
View file @
cca31bf0
...
...
@@ -508,10 +508,10 @@ __lxc_unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \
__internal_ret__; \
})
#define sys
debug
(__ret__, format, ...) \
#define sys
trace
(__ret__, format, ...) \
({ \
typeof(__ret__) __internal_ret__ = (__ret__); \
SYS
DEBUG
(format, ##__VA_ARGS__); \
SYS
TRACE
(format, ##__VA_ARGS__); \
__internal_ret__; \
})
...
...
@@ -525,7 +525,7 @@ __lxc_unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \
#define syserrno_set(__ret__, format, ...) \
({ \
typeof(__ret__) __internal_ret__ = (__ret__); \
errno =
abs(__ret__);
\
errno =
labs(__ret__);
\
SYSERROR(format, ##__VA_ARGS__); \
__internal_ret__; \
})
...
...
@@ -533,11 +533,39 @@ __lxc_unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \
#define syswarn_set(__ret__, format, ...) \
({ \
typeof(__ret__) __internal_ret__ = (__ret__); \
errno =
abs(__ret__);
\
errno =
labs(__ret__);
\
SYSWARN(format, ##__VA_ARGS__); \
__internal_ret__; \
})
#define syserror(format, ...) \
({ \
SYSERROR(format, ##__VA_ARGS__); \
(-errno); \
})
#define syserror_set(__ret__, format, ...) \
({ \
typeof(__ret__) __internal_ret__ = (__ret__); \
errno = labs(__ret__); \
SYSERROR(format, ##__VA_ARGS__); \
__internal_ret__; \
})
#define sysdebug(format, ...) \
({ \
SYSDEBUG(format, ##__VA_ARGS__); \
(-errno); \
})
#define sysdebug_set(__ret__, format, ...) \
({ \
typeof(__ret__) __internal_ret__ = (__ret__); \
errno = labs(__ret__); \
SYSDEBUG(format, ##__VA_ARGS__); \
__internal_ret__; \
})
#define log_error(__ret__, format, ...) \
({ \
typeof(__ret__) __internal_ret__ = (__ret__); \
...
...
src/lxc/macro.h
View file @
cca31bf0
...
...
@@ -708,4 +708,29 @@ enum {
_min1 < _min2 ? _min1 : _min2; \
})
#define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); })))
/*
* Compile time versions of __arch_hweightN()
*/
#define __const_hweight8(w) \
((unsigned int) \
((!!((w) & (1ULL << 0))) + \
(!!((w) & (1ULL << 1))) + \
(!!((w) & (1ULL << 2))) + \
(!!((w) & (1ULL << 3))) + \
(!!((w) & (1ULL << 4))) + \
(!!((w) & (1ULL << 5))) + \
(!!((w) & (1ULL << 6))) + \
(!!((w) & (1ULL << 7)))))
#define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8 ))
#define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
#define __const_hweight64(w) (__const_hweight32(w) + __const_hweight32((w) >> 32))
#define hweight8(w) __const_hweight8(w)
#define hweight16(w) __const_hweight16(w)
#define hweight32(w) __const_hweight32(w)
#define hweight64(w) __const_hweight64(w)
#endif
/* __LXC_MACRO_H */
src/lxc/start.c
View file @
cca31bf0
...
...
@@ -715,7 +715,7 @@ struct lxc_handler *lxc_init_handler(struct lxc_handler *old,
}
if
(
handler
->
conf
->
reboot
==
REBOOT_NONE
)
{
handler
->
conf
->
maincmd_fd
=
lxc_
cmd
_init
(
name
,
lxcpath
,
"command"
);
handler
->
conf
->
maincmd_fd
=
lxc_
server
_init
(
name
,
lxcpath
,
"command"
);
if
(
handler
->
conf
->
maincmd_fd
<
0
)
{
ERROR
(
"Failed to set up command socket"
);
goto
on_error
;
...
...
src/tests/lxc-test-lxc-attach
View file @
cca31bf0
...
...
@@ -45,17 +45,21 @@ set -e
allocate_pty
=
"nopty"
ATTACH_LOG
=
$(
mktemp
--dry-run
)
FAIL
()
{
echo
-n
"Failed "
>
&2
echo
"
$*
"
>
&2
cat
"
${
ATTACH_LOG
}
"
rm
-f
"
${
ATTACH_LOG
}
"
||
true
lxc-destroy
-n
busy
-f
exit
1
}
# Create a container, start it and wait for it to be in running state.
lxc-create
-t
busybox
-n
busy
||
FAIL
"creating busybox container"
lxc-start
-n
busy
-d
||
FAIL
"starting busybox container"
lxc-wait
-n
busy
-s
RUNNING
||
FAIL
"waiting for busybox container to run"
lxc-create
-t
busybox
-n
busy
-l
trace
-o
"
${
ATTACH_LOG
}
"
||
FAIL
"creating busybox container"
lxc-start
-n
busy
-d
-l
trace
-o
"
${
ATTACH_LOG
}
"
||
FAIL
"starting busybox container"
lxc-wait
-n
busy
-s
RUNNING
-l
trace
-o
"
${
ATTACH_LOG
}
"
||
FAIL
"waiting for busybox container to run"
if
[
-t
0
]
&&
[
-t
1
]
&&
[
-t
2
]
;
then
allocate_pty
=
"pty"
...
...
@@ -68,7 +72,7 @@ fi
# stdout --> attached to pty
# stderr --> attached to pty
for
i
in
`
seq
1 100
`
;
do
attach
=
$(
lxc-attach
-n
busy
--
hostname
||
FAIL
"to allocate or setup pty"
)
attach
=
$(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
hostname
||
FAIL
"to allocate or setup pty"
)
if
[
"
$attach
"
!=
"busy"
]
;
then
FAIL
"lxc-attach -n busy -- hostname"
fi
...
...
@@ -77,7 +81,7 @@ done
# stdin --> /dev/null
# stdout --> attached to pty
# stderr --> attached to pty
attach
=
$(
lxc-attach
-n
busy
--
hostname
< /dev/null
||
FAIL
"to allocate or setup pty"
)
attach
=
$(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
hostname
< /dev/null
||
FAIL
"to allocate or setup pty"
)
if
[
"
$attach
"
!=
"busy"
]
;
then
FAIL
"lxc-attach -n busy -- hostname < /dev/null"
fi
...
...
@@ -85,7 +89,7 @@ fi
# stdin --> attached to pty
# stdout --> /dev/null
# stderr --> attached to pty
attach
=
$(
lxc-attach
-n
busy
--
hostname
>
/dev/null
||
FAIL
"to allocate or setup pty"
)
attach
=
$(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
hostname
>
/dev/null
||
FAIL
"to allocate or setup pty"
)
if
[
-n
"
$attach
"
]
;
then
FAIL
"lxc-attach -n busy -- hostname > /dev/null"
fi
...
...
@@ -93,7 +97,7 @@ fi
# stdin --> attached to pty
# stdout --> attached to pty
# stderr --> /dev/null
attach
=
$(
lxc-attach
-n
busy
--
hostname
2> /dev/null
||
FAIL
"to allocate or setup pty"
)
attach
=
$(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
hostname
2> /dev/null
||
FAIL
"to allocate or setup pty"
)
if
[
"
$attach
"
!=
"busy"
]
;
then
FAIL
"lxc-attach -n busy -- hostname 2> /dev/null < /dev/null"
fi
...
...
@@ -101,7 +105,7 @@ fi
# stdin --> /dev/null
# stdout --> attached to pty
# stderr --> /dev/null
attach
=
$(
lxc-attach
-n
busy
--
hostname
2> /dev/null < /dev/null
||
FAIL
"to allocate or setup pty"
)
attach
=
$(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
hostname
2> /dev/null < /dev/null
||
FAIL
"to allocate or setup pty"
)
if
[
"
$attach
"
!=
"busy"
]
;
then
FAIL
"lxc-attach -n busy -- hostname 2> /dev/null < /dev/null"
fi
...
...
@@ -114,7 +118,7 @@ fi
# stdin --> attached to pty
# stdout --> /dev/null
# stderr --> attached to pty
attach
=
$(
(
lxc-attach
-n
busy
--
sh
-c
'hostname >&2'
>
/dev/null
)
2>&1
||
FAIL
"to allocate or setup pty"
)
attach
=
$(
(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
sh
-c
'hostname >&2'
>
/dev/null
)
2>&1
||
FAIL
"to allocate or setup pty"
)
if
[
"
$attach
"
!=
"busy"
]
;
then
FAIL
"lxc-attach -n busy -- sh -c 'hostname >&2' > /dev/null"
fi
...
...
@@ -126,7 +130,7 @@ fi
# stdin --> attached to pty
# stdout --> attach to pty
# stderr --> /dev/null
attach
=
$(
(
lxc-attach
-n
busy
--
sh
-c
'hostname >&2'
2> /dev/null
)
2>&1
||
FAIL
"to allocate or setup pty"
)
attach
=
$(
(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
sh
-c
'hostname >&2'
2> /dev/null
)
2>&1
||
FAIL
"to allocate or setup pty"
)
if
[
-n
"
$attach
"
]
;
then
FAIL
"lxc-attach -n busy -- sh -c 'hostname >&2' 2> /dev/null"
fi
...
...
@@ -136,7 +140,7 @@ fi
# stdout --> /dev/null
# stderr --> attached to pty
# (As we expect the exit code of the command to be 1 we ignore it.)
attach
=
$(
lxc-attach
-n
busy
--
sh
-c
'rm 2>&1'
>
/dev/null
||
true
)
attach
=
$(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
sh
-c
'rm 2>&1'
>
/dev/null
||
true
)
if
[
-n
"
$attach
"
]
;
then
FAIL
"lxc-attach -n busy -- sh -c 'rm 2>&1' > /dev/null"
fi
...
...
@@ -146,7 +150,7 @@ fi
# - stdout --> attached to pty
# - stderr --> /dev/null
# (As we expect the exit code of the command to be 1 we ignore it.)
attach
=
$(
lxc-attach
-n
busy
--
sh
-c
'rm 2>&1'
2> /dev/null
||
true
)
attach
=
$(
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
sh
-c
'rm 2>&1'
2> /dev/null
||
true
)
if
[
-z
"
$attach
"
]
;
then
FAIL
"lxc-attach -n busy -- sh -c 'rm 2>&1' 2> /dev/null"
fi
...
...
@@ -154,7 +158,7 @@ fi
# stdin --> $in
# stdout --> attached to pty
# stderr --> attached to pty
attach
=
$(
echo hostname
| lxc-attach
-n
busy
--
||
FAIL
"to allocate or setup pty"
)
attach
=
$(
echo hostname
| lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
||
FAIL
"to allocate or setup pty"
)
if
[
"
$attach
"
!=
"busy"
]
;
then
FAIL
"echo hostname | lxc-attach -n busy --"
fi
...
...
@@ -165,7 +169,7 @@ fi
out
=
$(
mktemp
/tmp/out_XXXX
)
err
=
$(
mktemp
/tmp/err_XXXX
)
trap
"rm -f
$out
$err
"
EXIT INT QUIT PIPE
lxc-attach
-n
busy
--
sh
-c
'echo OUT; echo ERR >&2'
>
$out
2>
$err
||
FAIL
"to allocate or setup pty"
lxc-attach
-n
busy
-
l
trace
-o
"
${
ATTACH_LOG
}
"
-
-
sh
-c
'echo OUT; echo ERR >&2'
>
$out
2>
$err
||
FAIL
"to allocate or setup pty"
outcontent
=
$(
cat
$out
)
errcontent
=
$(
cat
$err
)
if
[
"
$outcontent
"
!=
"OUT"
]
||
[
"
$errcontent
"
!=
"ERR"
]
;
then
...
...
@@ -181,7 +185,7 @@ rm -f $out $err
out
=
$(
mktemp
/tmp/out_XXXX
)
err
=
$(
mktemp
/tmp/err_XXXX
)
trap
"rm -f
$out
$err
"
EXIT INT QUIT PIPE
echo
"hostname; rm"
| lxc-attach
-n
busy
>
$out
2>
$err
||
true
echo
"hostname; rm"
| lxc-attach
-n
busy
-l
trace
-o
"
${
ATTACH_LOG
}
"
>
$out
2>
$err
||
true
outcontent
=
$(
cat
$out
)
errcontent
=
$(
cat
$err
)
if
[
"
$outcontent
"
!=
"busy"
]
||
[
-z
"
$errcontent
"
]
;
then
...
...
@@ -191,5 +195,6 @@ fi
rm
-f
$out
$err
lxc-destroy
-n
busy
-f
rm
-f
"
${
ATTACH_LOG
}
"
||
true
exit
0
src/tests/lxc-test-unpriv
View file @
cca31bf0
...
...
@@ -87,6 +87,7 @@ cleanup() {
echo
"FAIL"
exit
1
fi
rm
-f
"
${
UNPRIV_LOG
}
"
||
true
echo
"PASS"
}
...
...
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