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
ba2be1a8
Unverified
Commit
ba2be1a8
authored
Dec 24, 2017
by
Christian Brauner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
attach: move pty allocation into api
Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
79bd7662
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
274 additions
and
242 deletions
+274
-242
lxc-attach.sgml.in
doc/lxc-attach.sgml.in
+0
-17
attach.c
src/lxc/attach.c
+192
-35
attach_options.h
src/lxc/attach_options.h
+1
-0
lxc_attach.c
src/lxc/tools/lxc_attach.c
+27
-168
attach.c
src/tests/attach.c
+54
-11
lxc-test-lxc-attach
src/tests/lxc-test-lxc-attach
+0
-11
No files found.
doc/lxc-attach.sgml.in
View file @
ba2be1a8
...
...
@@ -58,7 +58,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<arg choice="opt">-R, --remount-sys-proc</arg>
<arg choice="opt">--keep-env</arg>
<arg choice="opt">--clear-env</arg>
<arg choice="opt">-L, --pty-log <replaceable>file</replaceable></arg>
<arg choice="opt">-v, --set-var <replaceable>variable</replaceable></arg>
<arg choice="opt">--keep-var <replaceable>variable</replaceable></arg>
<arg choice="opt">-- <replaceable>command</replaceable></arg>
...
...
@@ -258,22 +257,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<varlistentry>
<term>
<option>-L, --pty-log <replaceable>file</replaceable></option>
</term>
<listitem>
<para>
Specify a file where the output of <command>lxc-attach</command> will be
logged.
</para>
<para>
<emphasis>Important:</emphasis> When a standard file descriptor
does not refer to a pty output produced on it will not be logged.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-v, --set-var <replaceable>variable</replaceable></option>
</term>
<listitem>
...
...
src/lxc/attach.c
View file @
ba2be1a8
...
...
@@ -66,6 +66,7 @@
#include "lsm/lsm.h"
#include "lxclock.h"
#include "lxcseccomp.h"
#include "mainloop.h"
#include "namespace.h"
#include "utils.h"
...
...
@@ -819,12 +820,30 @@ static signed long get_personality(const char *name, const char *lxcpath)
struct
attach_clone_payload
{
int
ipc_socket
;
int
pty_fd
;
lxc_attach_options_t
*
options
;
struct
lxc_proc_context_info
*
init_ctx
;
lxc_attach_exec_t
exec_function
;
void
*
exec_payload
;
};
static
void
lxc_put_attach_clone_payload
(
struct
attach_clone_payload
*
p
)
{
if
(
p
->
ipc_socket
>=
0
)
{
shutdown
(
p
->
ipc_socket
,
SHUT_RDWR
);
close
(
p
->
ipc_socket
);
p
->
ipc_socket
=
-
EBADF
;
}
if
(
p
->
pty_fd
>=
0
)
{
close
(
p
->
pty_fd
);
p
->
pty_fd
=
-
EBADF
;
}
if
(
p
->
init_ctx
)
lxc_proc_put_context_info
(
p
->
init_ctx
);
}
static
int
attach_child_main
(
struct
attach_clone_payload
*
payload
)
{
int
fd
,
lsm_fd
,
ret
;
...
...
@@ -961,7 +980,8 @@ static int attach_child_main(struct attach_clone_payload *payload)
}
shutdown
(
payload
->
ipc_socket
,
SHUT_RDWR
);
close
(
payload
->
ipc_socket
);
payload
->
ipc_socket
=
-
1
;
payload
->
ipc_socket
=
-
EBADF
;
lxc_proc_put_context_info
(
init_ctx
);
/* The following is done after the communication socket is shut down.
* That way, all errors that might (though unlikely) occur up until this
...
...
@@ -1011,19 +1031,107 @@ static int attach_child_main(struct attach_clone_payload *payload)
}
}
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
{
ret
=
lxc_login_pty
(
payload
->
pty_fd
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to prepare pty file descriptor %d"
,
payload
->
pty_fd
);
goto
on_error
;
}
TRACE
(
"Prepared pty file descriptor %d"
,
payload
->
pty_fd
);
}
/* We're done, so we can now do whatever the user intended us to do. */
rexit
(
payload
->
exec_function
(
payload
->
exec_payload
));
on_error:
if
(
payload
->
ipc_socket
>=
0
)
{
shutdown
(
payload
->
ipc_socket
,
SHUT_RDWR
);
close
(
payload
->
ipc_socket
);
payload
->
ipc_socket
=
-
1
;
}
lxc_proc_put_context_info
(
init_ctx
);
lxc_put_attach_clone_payload
(
payload
);
rexit
(
EXIT_FAILURE
);
}
static
int
lxc_attach_pty
(
struct
lxc_conf
*
conf
,
struct
lxc_console
*
pty
)
{
int
ret
;
lxc_pty_init
(
pty
);
ret
=
lxc_pty_create
(
pty
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create pty"
);
return
-
1
;
}
/* Shift ttys to container. */
ret
=
lxc_pty_map_ids
(
conf
,
pty
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to shift pty"
);
goto
on_error
;
}
return
0
;
on_error:
lxc_console_delete
(
pty
);
lxc_pty_conf_free
(
pty
);
return
-
1
;
}
static
int
lxc_attach_pty_mainloop_init
(
struct
lxc_console
*
pty
,
struct
lxc_epoll_descr
*
descr
)
{
int
ret
;
ret
=
lxc_mainloop_open
(
descr
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create mainloop"
);
return
-
1
;
}
ret
=
lxc_console_mainloop_add
(
descr
,
pty
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to add handlers to mainloop"
);
lxc_mainloop_close
(
descr
);
return
-
1
;
}
return
0
;
}
static
inline
void
lxc_attach_pty_close_master
(
struct
lxc_console
*
pty
)
{
if
(
pty
->
master
<
0
)
return
;
close
(
pty
->
master
);
pty
->
master
=
-
EBADF
;
}
static
inline
void
lxc_attach_pty_close_slave
(
struct
lxc_console
*
pty
)
{
if
(
pty
->
slave
<
0
)
return
;
close
(
pty
->
slave
);
pty
->
slave
=
-
EBADF
;
}
static
inline
void
lxc_attach_pty_close_peer
(
struct
lxc_console
*
pty
)
{
if
(
pty
->
peer
<
0
)
return
;
close
(
pty
->
peer
);
pty
->
peer
=
-
EBADF
;
}
static
inline
void
lxc_attach_pty_close_log
(
struct
lxc_console
*
pty
)
{
if
(
pty
->
log_fd
<
0
)
return
;
close
(
pty
->
log_fd
);
pty
->
log_fd
=
-
EBADF
;
}
int
lxc_attach
(
const
char
*
name
,
const
char
*
lxcpath
,
lxc_attach_exec_t
exec_function
,
void
*
exec_payload
,
lxc_attach_options_t
*
options
,
pid_t
*
attached_process
)
...
...
@@ -1032,8 +1140,9 @@ int lxc_attach(const char *name, const char *lxcpath,
int
ipc_sockets
[
2
];
char
*
cwd
,
*
new_cwd
;
signed
long
personality
;
pid_t
attached_pid
,
expected
,
init_pid
,
pid
;
pid_t
attached_pid
,
init_pid
,
pid
;
struct
lxc_proc_context_info
*
init_ctx
;
struct
lxc_console
pty
;
struct
attach_clone_payload
payload
=
{
0
};
ret
=
access
(
"/proc/self/ns"
,
X_OK
);
...
...
@@ -1150,6 +1259,18 @@ int lxc_attach(const char *name, const char *lxcpath,
return
-
1
;
}
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
{
ret
=
lxc_attach_pty
(
init_ctx
->
container
->
lxc_conf
,
&
pty
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to allocate pty"
);
free
(
cwd
);
lxc_proc_put_context_info
(
init_ctx
);
return
-
1
;
}
pty
.
log_fd
=
options
->
log_fd
;
}
/* Create a socket pair for IPC communication; set SOCK_CLOEXEC in order
* to make sure we don't irritate other threads that want to fork+exec
* away
...
...
@@ -1210,13 +1331,16 @@ int lxc_attach(const char *name, const char *lxcpath,
}
if
(
pid
)
{
int
ret_parent
=
-
1
;
pid_t
to_cleanup_pid
=
pid
;
struct
lxc_epoll_descr
descr
=
{
0
};
/* Initial thread, we close the socket that is for the
* subprocesses.
*/
/* close unneeded file descriptors */
close
(
ipc_sockets
[
1
]);
free
(
cwd
);
lxc_proc_close_ns_fd
(
init_ctx
);
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
lxc_attach_pty_close_slave
(
&
pty
);
/* Attach to cgroup, if requested. */
if
(
options
->
attach_flags
&
LXC_ATTACH_MOVE_TO_CGROUP
)
{
...
...
@@ -1227,21 +1351,30 @@ int lxc_attach(const char *name, const char *lxcpath,
}
/* Setup resource limits */
if
(
!
lxc_list_empty
(
&
init_ctx
->
container
->
lxc_conf
->
limits
))
if
(
setup_resource_limits
(
&
init_ctx
->
container
->
lxc_conf
->
limits
,
pid
)
<
0
)
if
(
!
lxc_list_empty
(
&
init_ctx
->
container
->
lxc_conf
->
limits
))
{
ret
=
setup_resource_limits
(
&
init_ctx
->
container
->
lxc_conf
->
limits
,
pid
);
if
(
ret
<
0
)
goto
on_error
;
}
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
{
ret
=
lxc_attach_pty_mainloop_init
(
&
pty
,
&
descr
);
if
(
ret
<
0
)
goto
on_error
;
TRACE
(
"Initalized pty mainloop"
);
}
/* Let the child process know to go ahead. */
status
=
0
;
ret
=
lxc_write_nointr
(
ipc_sockets
[
0
],
&
status
,
sizeof
(
status
));
if
(
ret
!=
sizeof
(
status
))
goto
on_error
;
goto
close_mainloop
;
TRACE
(
"Told intermediate process to start initializing"
);
/* Get pid of attached process from intermediate process. */
ret
=
lxc_read_nointr
(
ipc_sockets
[
0
],
&
attached_pid
,
sizeof
(
attached_pid
));
if
(
ret
!=
sizeof
(
attached_pid
))
goto
on_error
;
goto
close_mainloop
;
TRACE
(
"Received pid %d of attached process in parent pid namespace"
,
attached_pid
);
/* Ignore SIGKILL (CTRL-C) and SIGQUIT (CTRL-\) - issue #313. */
...
...
@@ -1253,7 +1386,7 @@ int lxc_attach(const char *name, const char *lxcpath,
/* Reap intermediate process. */
ret
=
wait_for_pid
(
pid
);
if
(
ret
<
0
)
goto
on_error
;
goto
close_mainloop
;
TRACE
(
"Intermediate process %d exited"
,
pid
);
/* We will always have to reap the attached process now. */
...
...
@@ -1269,7 +1402,7 @@ int lxc_attach(const char *name, const char *lxcpath,
on_exec
=
options
->
attach_flags
&
LXC_ATTACH_LSM_EXEC
?
1
:
0
;
labelfd
=
lsm_open
(
attached_pid
,
on_exec
);
if
(
labelfd
<
0
)
goto
on_error
;
goto
close_mainloop
;
TRACE
(
"Opened LSM label file descriptor %d"
,
labelfd
);
/* Send child fd of the LSM security module to write to. */
...
...
@@ -1277,45 +1410,66 @@ int lxc_attach(const char *name, const char *lxcpath,
close
(
labelfd
);
if
(
ret
<=
0
)
{
SYSERROR
(
"%d"
,
(
int
)
ret
);
goto
on_error
;
goto
close_mainloop
;
}
TRACE
(
"Sent LSM label file descriptor %d to child"
,
labelfd
);
}
/* Now shut down communication with child, we're done. */
shutdown
(
ipc_sockets
[
0
],
SHUT_RDWR
);
close
(
ipc_sockets
[
0
]);
lxc_proc_put_context_info
(
init_ctx
);
/* We're done, the child process should now execute whatever it
* is that the user requested. The parent can now track it with
* waitpid() or similar.
*/
*
attached_process
=
attached_pid
;
return
0
;
on_error:
/* First shut down the socket, then wait for the pid, otherwise
* the pid we're waiting for may never exit.
*/
/* Now shut down communication with child, we're done. */
shutdown
(
ipc_sockets
[
0
],
SHUT_RDWR
);
close
(
ipc_sockets
[
0
]);
if
(
to_cleanup_pid
)
ipc_sockets
[
0
]
=
-
1
;
ret_parent
=
0
;
to_cleanup_pid
=
-
1
;
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
{
ret
=
lxc_mainloop
(
&
descr
,
-
1
);
if
(
ret
<
0
)
{
ret_parent
=
-
1
;
to_cleanup_pid
=
attached_pid
;
}
}
close_mainloop:
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
lxc_mainloop_close
(
&
descr
);
on_error:
if
(
ipc_sockets
[
0
]
>=
0
)
{
shutdown
(
ipc_sockets
[
0
],
SHUT_RDWR
);
close
(
ipc_sockets
[
0
]);
}
if
(
to_cleanup_pid
>
0
)
(
void
)
wait_for_pid
(
to_cleanup_pid
);
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
{
lxc_console_delete
(
&
pty
);
lxc_pty_conf_free
(
&
pty
);
}
lxc_proc_put_context_info
(
init_ctx
);
return
-
1
;
return
ret_parent
;
}
/* First subprocess begins here, we close the socket that is for the
* initial thread.
*/
/* close unneeded file descriptors */
close
(
ipc_sockets
[
0
]);
ipc_sockets
[
0
]
=
-
EBADF
;
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
{
lxc_attach_pty_close_master
(
&
pty
);
lxc_attach_pty_close_peer
(
&
pty
);
lxc_attach_pty_close_log
(
&
pty
);
}
/* Wait for the parent to have setup cgroups. */
expected
=
0
;
ret
=
lxc_read_nointr
(
ipc_sockets
[
1
],
&
status
,
sizeof
(
status
));
if
(
ret
!=
sizeof
(
status
)
||
status
!=
expected
)
{
if
(
ret
!=
sizeof
(
status
))
{
shutdown
(
ipc_sockets
[
1
],
SHUT_RDWR
);
lxc_proc_put_context_info
(
init_ctx
);
rexit
(
-
1
);
...
...
@@ -1351,6 +1505,7 @@ int lxc_attach(const char *name, const char *lxcpath,
payload
.
ipc_socket
=
ipc_sockets
[
1
];
payload
.
options
=
options
;
payload
.
init_ctx
=
init_ctx
;
payload
.
pty_fd
=
pty
.
slave
;
payload
.
exec_function
=
exec_function
;
payload
.
exec_payload
=
exec_payload
;
...
...
@@ -1368,6 +1523,8 @@ int lxc_attach(const char *name, const char *lxcpath,
ERROR
(
"Failed to exec"
);
_exit
(
EXIT_FAILURE
);
}
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
lxc_attach_pty_close_slave
(
&
pty
);
/* Tell grandparent the pid of the pid of the newly created child. */
ret
=
lxc_write_nointr
(
ipc_sockets
[
1
],
&
pid
,
sizeof
(
pid
));
...
...
src/lxc/attach_options.h
View file @
ba2be1a8
...
...
@@ -51,6 +51,7 @@ enum {
LXC_ATTACH_LSM_NOW
=
0x00020000
,
/*!< FIXME: unknown */
/* Set PR_SET_NO_NEW_PRIVS to block execve() gainable privileges. */
LXC_ATTACH_NO_NEW_PRIVS
=
0x00040000
,
/*!< PR_SET_NO_NEW_PRIVS */
LXC_ATTACH_ALLOCATE_PTY
=
0x00080000
,
/*!< Allocate new pty for attached process. */
/* We have 16 bits for things that are on by default and 16 bits that
* are off by default, that should be sufficient to keep binary
...
...
src/lxc/tools/lxc_attach.c
View file @
ba2be1a8
...
...
@@ -27,11 +27,12 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <lxc/lxccontainer.h>
...
...
@@ -46,12 +47,6 @@
#include "mainloop.h"
#include "utils.h"
#if HAVE_PTY_H
#include <pty.h>
#else
#include <../include/openpty.h>
#endif
static
const
struct
option
my_longopts
[]
=
{
{
"elevated-privileges"
,
optional_argument
,
0
,
'e'
},
{
"arch"
,
required_argument
,
0
,
'a'
},
...
...
@@ -241,155 +236,29 @@ Options :\n\
.
checker
=
NULL
,
};
struct
wrapargs
{
lxc_attach_options_t
*
options
;
lxc_attach_command_t
*
command
;
struct
lxc_console
*
console
;
int
ptyfd
;
};
/* Minimalistic login_tty() implementation. */
static
int
login_pty
(
int
fd
)
{
setsid
();
if
(
ioctl
(
fd
,
TIOCSCTTY
,
NULL
)
<
0
)
return
-
1
;
if
(
lxc_console_set_stdfds
(
fd
)
<
0
)
return
-
1
;
if
(
fd
>
STDERR_FILENO
)
close
(
fd
);
return
0
;
}
static
int
get_pty_on_host_callback
(
void
*
p
)
static
bool
stdfd_is_pty
(
void
)
{
struct
wrapargs
*
wrap
=
p
;
close
(
wrap
->
console
->
master
);
if
(
login_pty
(
wrap
->
console
->
slave
)
<
0
)
return
-
1
;
if
(
isatty
(
STDIN_FILENO
))
return
true
;
if
(
isatty
(
STDOUT_FILENO
))
return
true
;
if
(
isatty
(
STDERR_FILENO
))
return
true
;
if
(
wrap
->
command
->
program
)
lxc_attach_run_command
(
wrap
->
command
);
else
lxc_attach_run_shell
(
NULL
);
return
-
1
;
return
false
;
}
static
int
get_pty_on_host
(
struct
lxc_container
*
c
,
struct
wrapargs
*
wrap
,
int
*
pid
)
int
lxc_attach_create_log_file
(
const
char
*
log_file
)
{
struct
lxc_epoll_descr
descr
;
struct
lxc_conf
*
conf
;
struct
lxc_tty_state
*
ts
;
int
ret
=
-
1
;
struct
wrapargs
*
args
=
wrap
;
if
(
!
isatty
(
args
->
ptyfd
))
{
fprintf
(
stderr
,
"Standard file descriptor does not refer to a pty
\n
"
);
return
-
1
;
}
if
(
c
->
lxc_conf
)
{
conf
=
c
->
lxc_conf
;
}
else
{
/* If the container is not defined and the user didn't specify a
* config file to load we will simply init a dummy config here.
*/
conf
=
lxc_conf_init
();
if
(
!
conf
)
{
fprintf
(
stderr
,
"Failed to allocate dummy config file for the container
\n
"
);
return
-
1
;
}
int
fd
;
/* We also need a dummy rootfs path otherwise
* lxc_console_create() will not let us create a console. Note,
* I don't want this change to make it into
* lxc_console_create()'s since this function will only be
* responsible for proper /dev/{console,tty<n>} devices.
* lxc-attach is just abusing it to also handle the pty case
* because it is very similar. However, with LXC 3.0 lxc-attach
* will need to move away from using lxc_console_create() since
* this is actually an internal symbol and we only want the
* tools to use the API with LXC 3.0.
*/
conf
->
rootfs
.
path
=
strdup
(
"dummy"
);
if
(
!
conf
->
rootfs
.
path
)
return
-
1
;
}
free
(
conf
->
console
.
log_path
);
if
(
my_args
.
console_log
)
conf
->
console
.
log_path
=
strdup
(
my_args
.
console_log
);
else
conf
->
console
.
log_path
=
NULL
;
/* In the case of lxc-attach our peer pty will always be the current
* controlling terminal. We clear whatever was set by the user for
* lxc.console.path here and set it NULL. lxc_console_peer_default()
* will then try to open /dev/tty. If the process doesn't have a
* controlling terminal we should still proceed.
*/
free
(
conf
->
console
.
path
);
conf
->
console
.
path
=
NULL
;
/* Create pty on the host. */
if
(
lxc_console_create
(
conf
)
<
0
)
fd
=
open
(
log_file
,
O_CLOEXEC
|
O_RDWR
|
O_CREAT
|
O_APPEND
,
0600
);
if
(
fd
<
0
)
{
fprintf
(
stderr
,
"Failed to open log file
\"
%s
\"\n
"
,
log_file
);
return
-
1
;
ts
=
conf
->
console
.
tty_state
;
conf
->
console
.
descr
=
&
descr
;
/* Shift ttys to container. */
ret
=
lxc_pty_map_ids
(
conf
,
&
conf
->
console
);
if
(
ret
<
0
)
{
fprintf
(
stderr
,
"Failed to shift tty into container
\n
"
);
goto
err1
;
}
/* Send wrapper function on its way. */
wrap
->
console
=
&
conf
->
console
;
if
(
c
->
attach
(
c
,
get_pty_on_host_callback
,
wrap
,
wrap
->
options
,
pid
)
<
0
)
goto
err1
;
close
(
conf
->
console
.
slave
);
/* Close slave side. */
conf
->
console
.
slave
=
-
1
;
ret
=
lxc_mainloop_open
(
&
descr
);
if
(
ret
)
{
fprintf
(
stderr
,
"failed to create mainloop
\n
"
);
goto
err2
;
}
if
(
lxc_console_mainloop_add
(
&
descr
,
&
conf
->
console
)
<
0
)
{
fprintf
(
stderr
,
"Failed to add handlers to lxc mainloop.
\n
"
);
goto
err3
;
}
ret
=
lxc_mainloop
(
&
descr
,
-
1
);
if
(
ret
)
{
fprintf
(
stderr
,
"mainloop returned an error
\n
"
);
goto
err3
;
}
ret
=
0
;
err3:
lxc_mainloop_close
(
&
descr
);
err2:
if
(
ts
&&
ts
->
sigfd
!=
-
1
)
lxc_console_signal_fini
(
ts
);
err1:
lxc_console_delete
(
&
conf
->
console
);
return
ret
;
}
static
int
stdfd_is_pty
(
void
)
{
if
(
isatty
(
STDIN_FILENO
))
return
STDIN_FILENO
;
if
(
isatty
(
STDOUT_FILENO
))
return
STDOUT_FILENO
;
if
(
isatty
(
STDERR_FILENO
))
return
STDERR_FILENO
;
return
-
1
;
return
fd
;
}
int
main
(
int
argc
,
char
*
argv
[])
...
...
@@ -463,6 +332,8 @@ int main(int argc, char *argv[])
attach_options
.
attach_flags
|=
LXC_ATTACH_REMOUNT_PROC_SYS
;
if
(
elevated_privileges
)
attach_options
.
attach_flags
&=
~
(
elevated_privileges
);
if
(
stdfd_is_pty
())
attach_options
.
attach_flags
|=
LXC_ATTACH_ALLOCATE_PTY
;
attach_options
.
namespaces
=
namespace_flags
;
attach_options
.
personality
=
new_personality
;
attach_options
.
env_policy
=
env_policy
;
...
...
@@ -474,29 +345,17 @@ int main(int argc, char *argv[])
command
.
argv
=
(
char
**
)
my_args
.
argv
;
}
struct
wrapargs
wrap
=
(
struct
wrapargs
){
.
command
=
&
command
,
.
options
=
&
attach_options
};
wrap
.
ptyfd
=
stdfd_is_pty
();
if
(
wrap
.
ptyfd
>=
0
)
{
if
((
!
isatty
(
STDOUT_FILENO
)
||
!
isatty
(
STDERR_FILENO
))
&&
my_args
.
console_log
)
{
fprintf
(
stderr
,
"-L/--pty-log can only be used when stdout and stderr refer to a pty.
\n
"
);
goto
out
;
}
ret
=
get_pty_on_host
(
c
,
&
wrap
,
&
pid
);
}
else
{
if
(
my_args
.
console_log
)
{
fprintf
(
stderr
,
"-L/--pty-log can only be used when stdout and stderr refer to a pty.
\n
"
);
if
(
my_args
.
console_log
)
{
attach_options
.
log_fd
=
lxc_attach_create_log_file
(
my_args
.
console_log
);
if
(
attach_options
.
log_fd
<
0
)
goto
out
;
}
if
(
command
.
program
)
ret
=
c
->
attach
(
c
,
lxc_attach_run_command
,
&
command
,
&
attach_options
,
&
pid
);
else
ret
=
c
->
attach
(
c
,
lxc_attach_run_shell
,
NULL
,
&
attach_options
,
&
pid
);
}
if
(
command
.
program
)
ret
=
c
->
attach
(
c
,
lxc_attach_run_command
,
&
command
,
&
attach_options
,
&
pid
);
else
ret
=
c
->
attach
(
c
,
lxc_attach_run_shell
,
NULL
,
&
attach_options
,
&
pid
);
if
(
ret
<
0
)
goto
out
;
...
...
src/tests/attach.c
View file @
ba2be1a8
...
...
@@ -19,16 +19,18 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <lxc/lxccontainer.h>
#include "lxc/utils.h"
#include "lxc/lsm/lsm.h"
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <errno.h>
#include <sys/types.h>
#include "lxctest.h"
#include "utils.h"
#include "lsm/lsm.h"
#include <lxc/lxccontainer.h>
#define TSTNAME "lxc-attach-test"
#define TSTOUT(fmt, ...) do { \
...
...
@@ -392,19 +394,60 @@ err1:
int
main
(
int
argc
,
char
*
argv
[])
{
int
ret
;
int
i
,
ret
;
struct
lxc_log
log
;
char
template
[
sizeof
(
P_tmpdir
"/attach_XXXXXX"
)];
int
fret
=
EXIT_FAILURE
;
strcpy
(
template
,
P_tmpdir
"/attach_XXXXXX"
);
i
=
lxc_make_tmpfile
(
template
,
false
);
if
(
i
<
0
)
{
lxc_error
(
"Failed to create temporary log file for container %s
\n
"
,
TSTNAME
);
exit
(
EXIT_FAILURE
);
}
else
{
lxc_debug
(
"Using
\"
%s
\"
as temporary log file for container %s
\n
"
,
template
,
TSTNAME
);
close
(
i
);
}
log
.
name
=
TSTNAME
;
log
.
file
=
template
;
log
.
level
=
"TRACE"
;
log
.
prefix
=
"attach"
;
log
.
quiet
=
false
;
log
.
lxcpath
=
NULL
;
if
(
lxc_log_init
(
&
log
))
goto
on_error
;
test_lsm_detect
();
ret
=
test_attach
(
NULL
,
TSTNAME
,
"busybox"
);
if
(
ret
<
0
)
return
EXIT_FAILURE
;
goto
on_error
;
TSTOUT
(
"
\n
"
);
ret
=
test_attach
(
LXCPATH
"/alternate-path-test"
,
TSTNAME
,
"busybox"
);
if
(
ret
<
0
)
return
EXIT_FAILURE
;
goto
on_error
;
(
void
)
rmdir
(
LXCPATH
"/alternate-path-test"
);
TSTOUT
(
"All tests passed
\n
"
);
return
EXIT_SUCCESS
;
fret
=
EXIT_SUCCESS
;
on_error:
if
(
fret
!=
EXIT_SUCCESS
)
{
int
fd
;
fd
=
open
(
template
,
O_RDONLY
);
if
(
fd
>=
0
)
{
char
buf
[
4096
];
ssize_t
buflen
;
while
((
buflen
=
read
(
fd
,
buf
,
1024
))
>
0
)
{
buflen
=
write
(
STDERR_FILENO
,
buf
,
buflen
);
if
(
buflen
<=
0
)
break
;
}
close
(
fd
);
}
}
(
void
)
rmdir
(
LXCPATH
"/alternate-path-test"
);
(
void
)
unlink
(
template
);
exit
(
fret
);
}
src/tests/lxc-test-lxc-attach
View file @
ba2be1a8
...
...
@@ -190,17 +190,6 @@ fi
rm
-f
$out
$err
if
[
$allocate_pty
=
"pty"
]
;
then
# Test whether logging pty output to a file works.
trap
"rm -f /tmp/ptylog"
EXIT INT QUIT PIPE
lxc-attach
-n
busy
-L
/tmp/ptylog
--
hostname
||
FAIL
"to allocate or setup pty"
if
[
!
-s
/tmp/ptylog
]
;
then
FAIL
"lxc-attach -n busy -L /tmp/ptylog -- hostname"
fi
rm
-f
/tmp/ptylog
fi
lxc-destroy
-n
busy
-f
exit
0
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