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
010a85d1
Unverified
Commit
010a85d1
authored
Jul 21, 2018
by
Christian Brauner
Committed by
GitHub
Jul 21, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2482 from 2xsec/bugfix
error handling cleanups #2471
parents
8fd3e219
9044b79e
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
391 additions
and
163 deletions
+391
-163
af_unix.c
src/lxc/af_unix.c
+18
-13
af_unix.h
src/lxc/af_unix.h
+1
-1
attach.c
src/lxc/attach.c
+12
-3
lxc_monitord.c
src/lxc/cmd/lxc_monitord.c
+45
-31
commands.c
src/lxc/commands.c
+20
-17
confile_utils.c
src/lxc/confile_utils.c
+37
-17
confile_utils.h
src/lxc/confile_utils.h
+1
-1
lxccontainer.c
src/lxc/lxccontainer.c
+242
-74
start.c
src/lxc/start.c
+15
-6
No files found.
src/lxc/af_unix.c
View file @
010a85d1
...
...
@@ -74,30 +74,28 @@ int lxc_abstract_unix_open(const char *path, int type, int flags)
ret
=
bind
(
fd
,
(
struct
sockaddr
*
)
&
addr
,
offsetof
(
struct
sockaddr_un
,
sun_path
)
+
len
+
1
);
if
(
ret
<
0
)
{
int
tmp
=
errno
;
int
saved_erron
=
errno
;
close
(
fd
);
errno
=
tmp
;
errno
=
saved_erron
;
return
-
1
;
}
if
(
type
==
SOCK_STREAM
)
{
ret
=
listen
(
fd
,
100
);
if
(
ret
<
0
)
{
int
tmp
=
errno
;
int
saved_erron
=
errno
;
close
(
fd
);
errno
=
tmp
;
errno
=
saved_erron
;
return
-
1
;
}
}
return
fd
;
}
int
lxc_abstract_unix_close
(
int
fd
)
void
lxc_abstract_unix_close
(
int
fd
)
{
close
(
fd
);
return
0
;
}
int
lxc_abstract_unix_connect
(
const
char
*
path
)
...
...
@@ -128,7 +126,9 @@ int lxc_abstract_unix_connect(const char *path)
ret
=
connect
(
fd
,
(
struct
sockaddr
*
)
&
addr
,
offsetof
(
struct
sockaddr_un
,
sun_path
)
+
len
+
1
);
if
(
ret
<
0
)
{
int
saved_errno
=
errno
;
close
(
fd
);
errno
=
saved_errno
;
return
-
1
;
}
...
...
@@ -150,8 +150,10 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
memset
(
&
iov
,
0
,
sizeof
(
iov
));
cmsgbuf
=
malloc
(
cmsgbufsize
);
if
(
!
cmsgbuf
)
if
(
!
cmsgbuf
)
{
errno
=
ENOMEM
;
return
-
1
;
}
msg
.
msg_control
=
cmsgbuf
;
msg
.
msg_controllen
=
cmsgbufsize
;
...
...
@@ -190,8 +192,10 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
memset
(
&
iov
,
0
,
sizeof
(
iov
));
cmsgbuf
=
malloc
(
cmsgbufsize
);
if
(
!
cmsgbuf
)
if
(
!
cmsgbuf
)
{
errno
=
ENOMEM
;
return
-
1
;
}
msg
.
msg_control
=
cmsgbuf
;
msg
.
msg_controllen
=
cmsgbufsize
;
...
...
@@ -209,9 +213,8 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
memset
(
recvfds
,
-
1
,
num_recvfds
*
sizeof
(
int
));
if
(
cmsg
&&
cmsg
->
cmsg_len
==
CMSG_LEN
(
num_recvfds
*
sizeof
(
int
))
&&
cmsg
->
cmsg_level
==
SOL_SOCKET
&&
cmsg
->
cmsg_type
==
SCM_RIGHTS
)
{
cmsg
->
cmsg_level
==
SOL_SOCKET
&&
cmsg
->
cmsg_type
==
SCM_RIGHTS
)
memcpy
(
recvfds
,
CMSG_DATA
(
cmsg
),
num_recvfds
*
sizeof
(
int
));
}
out:
free
(
cmsgbuf
);
...
...
@@ -281,10 +284,12 @@ int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size)
memcpy
(
&
cred
,
CMSG_DATA
(
cmsg
),
sizeof
(
cred
));
if
(
cred
.
uid
&&
(
cred
.
uid
!=
getuid
()
||
cred
.
gid
!=
getgid
()))
{
INFO
(
"message denied for '%d/%d'"
,
cred
.
uid
,
cred
.
gid
);
return
-
EACCES
;
INFO
(
"Message denied for '%d/%d'"
,
cred
.
uid
,
cred
.
gid
);
errno
=
EACCES
;
return
-
1
;
}
}
out:
return
ret
;
}
src/lxc/af_unix.h
View file @
010a85d1
...
...
@@ -28,7 +28,7 @@
/* does not enforce \0-termination */
extern
int
lxc_abstract_unix_open
(
const
char
*
path
,
int
type
,
int
flags
);
extern
int
lxc_abstract_unix_close
(
int
fd
);
extern
void
lxc_abstract_unix_close
(
int
fd
);
/* does not enforce \0-termination */
extern
int
lxc_abstract_unix_connect
(
const
char
*
path
);
extern
int
lxc_abstract_unix_send_fds
(
int
fd
,
int
*
sendfds
,
int
num_sendfds
,
...
...
src/lxc/attach.c
View file @
010a85d1
...
...
@@ -828,8 +828,13 @@ static int attach_child_main(struct attach_clone_payload *payload)
*/
if
(
needs_lsm
)
{
ret
=
lxc_abstract_unix_recv_fds
(
payload
->
ipc_socket
,
&
lsm_fd
,
1
,
NULL
,
0
);
if
(
ret
<=
0
)
if
(
ret
<=
0
)
{
if
(
ret
<
0
)
SYSERROR
(
"Failed to receive lsm label fd"
);
goto
on_error
;
}
TRACE
(
"Received LSM label file descriptor %d from parent"
,
lsm_fd
);
}
...
...
@@ -1330,11 +1335,15 @@ int lxc_attach(const char *name, const char *lxcpath,
/* Send child fd of the LSM security module to write to. */
ret
=
lxc_abstract_unix_send_fds
(
ipc_sockets
[
0
],
&
labelfd
,
1
,
NULL
,
0
);
close
(
labelfd
);
if
(
ret
<=
0
)
{
SYSERROR
(
"%d"
,
(
int
)
ret
);
if
(
ret
<
0
)
SYSERROR
(
"Failed to send lsm label fd"
);
close
(
labelfd
);
goto
close_mainloop
;
}
close
(
labelfd
);
TRACE
(
"Sent LSM label file descriptor %d to child"
,
labelfd
);
}
...
...
src/lxc/cmd/lxc_monitord.c
View file @
010a85d1
...
...
@@ -97,8 +97,8 @@ static int lxc_monitord_fifo_create(struct lxc_monitor *mon)
mon
->
fifofd
=
open
(
fifo_path
,
O_RDWR
);
if
(
mon
->
fifofd
<
0
)
{
SYSERROR
(
"Failed to open monitor fifo %s"
,
fifo_path
);
unlink
(
fifo_path
);
ERROR
(
"Failed to open monitor fifo."
);
return
-
1
;
}
...
...
@@ -106,12 +106,14 @@ static int lxc_monitord_fifo_create(struct lxc_monitor *mon)
lk
.
l_whence
=
SEEK_SET
;
lk
.
l_start
=
0
;
lk
.
l_len
=
0
;
if
(
fcntl
(
mon
->
fifofd
,
F_SETLK
,
&
lk
)
!=
0
)
{
/* another lxc-monitord is already running, don't start up */
DEBUG
(
"lxc-monitord already running on lxcpath %s.
"
,
mon
->
lxcpath
);
SYSDEBUG
(
"lxc-monitord already running on lxcpath %s
"
,
mon
->
lxcpath
);
close
(
mon
->
fifofd
);
return
-
1
;
}
return
0
;
}
...
...
@@ -132,15 +134,15 @@ static void lxc_monitord_sockfd_remove(struct lxc_monitor *mon, int fd) {
int
i
;
if
(
lxc_mainloop_del_handler
(
&
mon
->
descr
,
fd
))
CRIT
(
"File descriptor %d not found in mainloop
.
"
,
fd
);
CRIT
(
"File descriptor %d not found in mainloop"
,
fd
);
close
(
fd
);
for
(
i
=
0
;
i
<
mon
->
clientfds_cnt
;
i
++
)
{
for
(
i
=
0
;
i
<
mon
->
clientfds_cnt
;
i
++
)
if
(
mon
->
clientfds
[
i
]
==
fd
)
break
;
}
if
(
i
>=
mon
->
clientfds_cnt
)
{
CRIT
(
"File descriptor %d not found in clients array
.
"
,
fd
);
CRIT
(
"File descriptor %d not found in clients array"
,
fd
);
lxc_monitord_cleanup
();
exit
(
EXIT_FAILURE
);
}
...
...
@@ -166,6 +168,7 @@ static int lxc_monitord_sock_handler(int fd, uint32_t events, void *data,
if
(
events
&
EPOLLHUP
)
lxc_monitord_sockfd_remove
(
mon
,
fd
);
return
quit
;
}
...
...
@@ -180,53 +183,55 @@ static int lxc_monitord_sock_accept(int fd, uint32_t events, void *data,
ret
=
LXC_MAINLOOP_ERROR
;
clientfd
=
accept
(
fd
,
NULL
,
0
);
if
(
clientfd
<
0
)
{
SYSERROR
(
"Failed to accept connection for client file descriptor %d
.
"
,
fd
);
SYSERROR
(
"Failed to accept connection for client file descriptor %d"
,
fd
);
goto
out
;
}
if
(
fcntl
(
clientfd
,
F_SETFD
,
FD_CLOEXEC
))
{
SYSERROR
(
"Failed to set FD_CLOEXEC on client socket connection %d
.
"
,
clientfd
);
SYSERROR
(
"Failed to set FD_CLOEXEC on client socket connection %d"
,
clientfd
);
goto
err1
;
}
if
(
getsockopt
(
clientfd
,
SOL_SOCKET
,
SO_PEERCRED
,
&
cred
,
&
credsz
))
{
ERROR
(
"Failed to get credentials on client socket connection %d."
,
clientfd
);
if
(
getsockopt
(
clientfd
,
SOL_SOCKET
,
SO_PEERCRED
,
&
cred
,
&
credsz
))
{
SYSERROR
(
"Failed to get credentials on client socket connection %d"
,
clientfd
);
goto
err1
;
}
if
(
cred
.
uid
&&
cred
.
uid
!=
geteuid
())
{
WARN
(
"Monitor denied for uid %d on client socket connection %d."
,
cred
.
uid
,
clientfd
);
ret
=
-
EACCES
;
WARN
(
"Monitor denied for uid %d on client socket connection %d"
,
cred
.
uid
,
clientfd
);
goto
err1
;
}
if
(
mon
->
clientfds_cnt
+
1
>
mon
->
clientfds_size
)
{
int
*
clientfds
;
clientfds
=
realloc
(
mon
->
clientfds
,
(
mon
->
clientfds_size
+
CLIENTFDS_CHUNK
)
*
sizeof
(
mon
->
clientfds
[
0
]));
if
(
clientfds
==
NULL
)
{
ERROR
(
"Failed to realloc memory for %d client file "
"descriptors."
,
ERROR
(
"Failed to realloc memory for %d client file descriptors"
,
mon
->
clientfds_size
+
CLIENTFDS_CHUNK
);
goto
err1
;
}
mon
->
clientfds
=
clientfds
;
mon
->
clientfds_size
+=
CLIENTFDS_CHUNK
;
}
ret
=
lxc_mainloop_add_handler
(
&
mon
->
descr
,
clientfd
,
lxc_monitord_sock_handler
,
mon
);
if
(
ret
)
{
ERROR
(
"Failed to add socket handler
.
"
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to add socket handler"
);
goto
err1
;
}
mon
->
clientfds
[
mon
->
clientfds_cnt
++
]
=
clientfd
;
INFO
(
"Accepted client file descriptor %d. Number of accepted file descriptors is now %d."
,
clientfd
,
mon
->
clientfds_cnt
);
INFO
(
"Accepted client file descriptor %d. Number of accepted file descriptors is now %d"
,
clientfd
,
mon
->
clientfds_cnt
);
goto
out
;
err1:
close
(
clientfd
);
out:
return
ret
;
}
...
...
@@ -255,8 +260,10 @@ static int lxc_monitord_sock_delete(struct lxc_monitor *mon)
if
(
lxc_monitor_sock_name
(
mon
->
lxcpath
,
&
addr
)
<
0
)
return
-
1
;
if
(
addr
.
sun_path
[
0
])
unlink
(
addr
.
sun_path
);
return
0
;
}
...
...
@@ -268,8 +275,7 @@ static int lxc_monitord_create(struct lxc_monitor *mon)
if
(
ret
<
0
)
return
ret
;
ret
=
lxc_monitord_sock_create
(
mon
);
return
ret
;
return
lxc_monitord_sock_create
(
mon
);
}
static
void
lxc_monitord_delete
(
struct
lxc_monitor
*
mon
)
...
...
@@ -277,7 +283,7 @@ static void lxc_monitord_delete(struct lxc_monitor *mon)
int
i
;
lxc_mainloop_del_handler
(
&
mon
->
descr
,
mon
->
listenfd
);
close
(
mon
->
listenfd
);
lxc_abstract_unix_
close
(
mon
->
listenfd
);
lxc_monitord_sock_delete
(
mon
);
lxc_mainloop_del_handler
(
&
mon
->
descr
,
mon
->
fifofd
);
...
...
@@ -288,6 +294,7 @@ static void lxc_monitord_delete(struct lxc_monitor *mon)
lxc_mainloop_del_handler
(
&
mon
->
descr
,
mon
->
clientfds
[
i
]);
close
(
mon
->
clientfds
[
i
]);
}
mon
->
clientfds_cnt
=
0
;
}
...
...
@@ -321,14 +328,14 @@ static int lxc_monitord_mainloop_add(struct lxc_monitor *mon)
ret
=
lxc_mainloop_add_handler
(
&
mon
->
descr
,
mon
->
fifofd
,
lxc_monitord_fifo_handler
,
mon
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to add to mainloop monitor handler for fifo
.
"
);
ERROR
(
"Failed to add to mainloop monitor handler for fifo"
);
return
-
1
;
}
ret
=
lxc_mainloop_add_handler
(
&
mon
->
descr
,
mon
->
listenfd
,
lxc_monitord_sock_accept
,
mon
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to add to mainloop monitor handler for listen socket
.
"
);
ERROR
(
"Failed to add to mainloop monitor handler for listen socket"
);
return
-
1
;
}
...
...
@@ -374,9 +381,10 @@ int main(int argc, char *argv[])
log
.
prefix
=
"lxc-monitord"
;
log
.
quiet
=
0
;
log
.
lxcpath
=
lxcpath
;
ret
=
lxc_log_init
(
&
log
);
if
(
ret
)
INFO
(
"Failed to open log file %s, log will be lost
.
"
,
lxcpath
);
INFO
(
"Failed to open log file %s, log will be lost"
,
lxcpath
);
lxc_log_options_no_override
();
if
(
lxc_safe_int
(
argv
[
2
],
&
pipefd
)
<
0
)
...
...
@@ -388,7 +396,7 @@ int main(int argc, char *argv[])
sigdelset
(
&
mask
,
SIGBUS
)
||
sigdelset
(
&
mask
,
SIGTERM
)
||
pthread_sigmask
(
SIG_BLOCK
,
&
mask
,
NULL
))
{
SYSERROR
(
"Failed to set signal mask
.
"
);
SYSERROR
(
"Failed to set signal mask"
);
exit
(
EXIT_FAILURE
);
}
...
...
@@ -401,10 +409,11 @@ int main(int argc, char *argv[])
goto
on_signal
;
ret
=
EXIT_FAILURE
;
memset
(
&
mon
,
0
,
sizeof
(
mon
));
mon
.
lxcpath
=
lxcpath
;
if
(
lxc_mainloop_open
(
&
mon
.
descr
))
{
ERROR
(
"Failed to create mainloop
.
"
);
ERROR
(
"Failed to create mainloop"
);
goto
on_error
;
}
mainloop_opened
=
true
;
...
...
@@ -424,33 +433,38 @@ int main(int argc, char *argv[])
close
(
pipefd
);
if
(
lxc_monitord_mainloop_add
(
&
mon
))
{
ERROR
(
"Failed to add mainloop handlers
.
"
);
ERROR
(
"Failed to add mainloop handlers"
);
goto
on_error
;
}
NOTICE
(
"lxc-monitord with pid %d is now monitoring lxcpath %s
.
"
,
NOTICE
(
"lxc-monitord with pid %d is now monitoring lxcpath %s"
,
lxc_raw_getpid
(),
mon
.
lxcpath
);
for
(;;)
{
ret
=
lxc_mainloop
(
&
mon
.
descr
,
1000
*
30
);
if
(
ret
)
{
ERROR
(
"mainloop returned an error"
);
break
;
}
if
(
mon
.
clientfds_cnt
<=
0
)
{
NOTICE
(
"No remaining clients. lxc-monitord is exiting
.
"
);
NOTICE
(
"No remaining clients. lxc-monitord is exiting"
);
break
;
}
if
(
quit
==
1
)
{
NOTICE
(
"got quit command. lxc-monitord is exitting."
);
if
(
quit
==
LXC_MAINLOOP_CLOSE
)
{
NOTICE
(
"Got quit command. lxc-monitord is exitting"
);
break
;
}
}
on_signal:
ret
=
EXIT_SUCCESS
;
on_error:
if
(
monitord_created
)
lxc_monitord_cleanup
();
if
(
mainloop_opened
)
lxc_mainloop_close
(
&
mon
.
descr
);
...
...
src/lxc/commands.c
View file @
010a85d1
...
...
@@ -240,18 +240,21 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
ret
=
lxc_abstract_unix_send_credential
(
client_fd
,
&
cmd
->
req
,
sizeof
(
cmd
->
req
));
if
(
ret
<
0
||
(
size_t
)
ret
!=
sizeof
(
cmd
->
req
))
{
close
(
client_fd
);
if
(
errno
==
EPIPE
)
if
(
ret
<
0
)
{
if
(
errno
==
EPIPE
)
{
close
(
client_fd
);
return
-
EPIPE
;
if
(
ret
>=
0
)
return
-
EMSGSIZE
;
}
close
(
client_fd
);
return
-
1
;
}
if
((
size_t
)
ret
!=
sizeof
(
cmd
->
req
))
{
close
(
client_fd
);
return
-
EMSGSIZE
;
}
if
(
cmd
->
req
.
datalen
<=
0
)
return
client_fd
;
...
...
@@ -754,7 +757,7 @@ static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
rsp
.
data
=
INT_TO_PTR
(
ttynum
);
ret
=
lxc_abstract_unix_send_fds
(
fd
,
&
masterfd
,
1
,
&
rsp
,
sizeof
(
rsp
));
if
(
ret
<
0
)
{
ERROR
(
"Failed to send tty to client"
);
SYS
ERROR
(
"Failed to send tty to client"
);
lxc_terminal_free
(
handler
->
conf
,
fd
);
goto
out_close
;
}
...
...
@@ -1112,17 +1115,17 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
struct
lxc_handler
*
handler
=
data
;
ret
=
lxc_abstract_unix_rcv_credential
(
fd
,
&
req
,
sizeof
(
req
));
if
(
ret
==
-
EACCES
)
{
/* We don't care for the peer, just send and close. */
struct
lxc_cmd_rsp
rsp
=
{.
ret
=
ret
};
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
goto
out_close
;
}
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to receive data on command socket for command "
"
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
"
\"
%s
\"
"
,
lxc_cmd_str
(
req
.
cmd
));
if
(
errno
==
EACCES
)
{
/* We don't care for the peer, just send and close. */
struct
lxc_cmd_rsp
rsp
=
{.
ret
=
ret
};
lxc_cmd_rsp_send
(
fd
,
&
rsp
);
}
goto
out_close
;
}
...
...
src/lxc/confile_utils.c
View file @
010a85d1
...
...
@@ -149,6 +149,7 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid,
*/
if
(
*
(
slide
+
strspn
(
slide
,
"
\t\r\n
"
))
!=
'\0'
)
goto
on_error
;
/* Mark end of range. */
*
slide
=
'\0'
;
...
...
@@ -211,6 +212,7 @@ struct lxc_netdev *lxc_network_add(struct lxc_list *networks, int idx, bool tail
lxc_list_add_tail
(
networks
,
newlist
);
else
lxc_list_add
(
networks
,
newlist
);
return
netdev
;
}
...
...
@@ -265,23 +267,29 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
TRACE
(
"index: %zd"
,
netdev
->
idx
);
TRACE
(
"ifindex: %d"
,
netdev
->
ifindex
);
switch
(
netdev
->
type
)
{
case
LXC_NET_VETH
:
TRACE
(
"type: veth"
);
if
(
netdev
->
priv
.
veth_attr
.
pair
[
0
]
!=
'\0'
)
TRACE
(
"veth pair: %s"
,
netdev
->
priv
.
veth_attr
.
pair
);
if
(
netdev
->
priv
.
veth_attr
.
veth1
[
0
]
!=
'\0'
)
TRACE
(
"veth1 : %s"
,
netdev
->
priv
.
veth_attr
.
veth1
);
if
(
netdev
->
priv
.
veth_attr
.
ifindex
>
0
)
TRACE
(
"host side ifindex for veth device: %d"
,
netdev
->
priv
.
veth_attr
.
ifindex
);
break
;
case
LXC_NET_MACVLAN
:
TRACE
(
"type: macvlan"
);
if
(
netdev
->
priv
.
macvlan_attr
.
mode
>
0
)
{
char
*
macvlan_mode
;
macvlan_mode
=
lxc_macvlan_flag_to_mode
(
netdev
->
priv
.
macvlan_attr
.
mode
);
TRACE
(
"macvlan mode: %s"
,
...
...
@@ -295,10 +303,10 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
break
;
case
LXC_NET_PHYS
:
TRACE
(
"type: phys"
);
if
(
netdev
->
priv
.
phys_attr
.
ifindex
>
0
)
{
if
(
netdev
->
priv
.
phys_attr
.
ifindex
>
0
)
TRACE
(
"host side ifindex for phys device: %d"
,
netdev
->
priv
.
phys_attr
.
ifindex
);
}
break
;
case
LXC_NET_EMPTY
:
TRACE
(
"type: empty"
);
...
...
@@ -314,16 +322,22 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
if
(
netdev
->
type
!=
LXC_NET_EMPTY
)
{
TRACE
(
"flags: %s"
,
netdev
->
flags
==
IFF_UP
?
"up"
:
"none"
);
if
(
netdev
->
link
[
0
]
!=
'\0'
)
TRACE
(
"link: %s"
,
netdev
->
link
);
if
(
netdev
->
name
[
0
]
!=
'\0'
)
TRACE
(
"name: %s"
,
netdev
->
name
);
if
(
netdev
->
hwaddr
)
TRACE
(
"hwaddr: %s"
,
netdev
->
hwaddr
);
if
(
netdev
->
mtu
)
TRACE
(
"mtu: %s"
,
netdev
->
mtu
);
if
(
netdev
->
upscript
)
TRACE
(
"upscript: %s"
,
netdev
->
upscript
);
if
(
netdev
->
downscript
)
TRACE
(
"downscript: %s"
,
netdev
->
downscript
);
...
...
@@ -345,11 +359,13 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
TRACE
(
"ipv6 gateway auto: %s"
,
netdev
->
ipv6_gateway_auto
?
"true"
:
"false"
);
if
(
netdev
->
ipv6_gateway
)
{
inet_ntop
(
AF_INET6
,
netdev
->
ipv6_gateway
,
bufinet6
,
sizeof
(
bufinet6
));
TRACE
(
"ipv6 gateway: %s"
,
bufinet6
);
}
lxc_list_for_each_safe
(
cur
,
&
netdev
->
ipv6
,
next
)
{
inet6dev
=
cur
->
elem
;
inet_ntop
(
AF_INET6
,
&
inet6dev
->
addr
,
bufinet6
,
...
...
@@ -477,7 +493,7 @@ int set_config_string_item(char **conf_item, const char *value)
new_value
=
strdup
(
value
);
if
(
!
new_value
)
{
SYSERROR
(
"
f
ailed to duplicate string
\"
%s
\"
"
,
value
);
SYSERROR
(
"
F
ailed to duplicate string
\"
%s
\"
"
,
value
);
return
-
1
;
}
...
...
@@ -505,8 +521,10 @@ int config_ip_prefix(struct in_addr *addr)
{
if
(
IN_CLASSA
(
addr
->
s_addr
))
return
32
-
IN_CLASSA_NSHIFT
;
if
(
IN_CLASSB
(
addr
->
s_addr
))
return
32
-
IN_CLASSB_NSHIFT
;
if
(
IN_CLASSC
(
addr
->
s_addr
))
return
32
-
IN_CLASSC_NSHIFT
;
...
...
@@ -521,15 +539,14 @@ int network_ifname(char *valuep, const char *value, size_t size)
return
-
1
;
retlen
=
strlcpy
(
valuep
,
value
,
size
);
if
(
retlen
>=
size
)
{
if
(
retlen
>=
size
)
ERROR
(
"Network devie name
\"
%s
\"
is too long (>= %zu)"
,
value
,
size
);
}
return
0
;
}
int
rand_complete_hwaddr
(
char
*
hwaddr
)
void
rand_complete_hwaddr
(
char
*
hwaddr
)
{
const
char
hex
[]
=
"0123456789abcdef"
;
char
*
curs
=
hwaddr
;
...
...
@@ -558,7 +575,6 @@ int rand_complete_hwaddr(char *hwaddr)
}
curs
++
;
}
return
0
;
}
bool
lxc_config_net_hwaddr
(
const
char
*
line
)
...
...
@@ -568,11 +584,15 @@ bool lxc_config_net_hwaddr(const char *line)
if
(
strncmp
(
line
,
"lxc.net"
,
7
)
!=
0
)
return
false
;
if
(
strncmp
(
line
,
"lxc.net.hwaddr"
,
14
)
==
0
)
return
true
;
if
(
strncmp
(
line
,
"lxc.network.hwaddr"
,
18
)
==
0
)
return
true
;
if
(
sscanf
(
line
,
"lxc.net.%u.%6s"
,
&
index
,
tmp
)
==
2
||
sscanf
(
line
,
"lxc.network.%u.%6s"
,
&
index
,
tmp
)
==
2
)
if
(
sscanf
(
line
,
"lxc.net.%u.%6s"
,
&
index
,
tmp
)
==
2
||
sscanf
(
line
,
"lxc.network.%u.%6s"
,
&
index
,
tmp
)
==
2
)
return
strncmp
(
tmp
,
"hwaddr"
,
6
)
==
0
;
return
false
;
...
...
@@ -639,7 +659,7 @@ int lxc_get_conf_str(char *retv, int inlen, const char *value)
if
(
retv
&&
inlen
>=
value_len
+
1
)
memcpy
(
retv
,
value
,
value_len
+
1
);
return
strlen
(
value
)
;
return
value_len
;
}
int
lxc_get_conf_int
(
struct
lxc_conf
*
c
,
char
*
retv
,
int
inlen
,
int
v
)
...
...
@@ -701,6 +721,7 @@ bool parse_limit_value(const char **value, rlim_t *res)
*
res
=
strtoull
(
*
value
,
&
endptr
,
10
);
if
(
errno
||
!
endptr
)
return
false
;
*
value
=
endptr
;
return
true
;
...
...
@@ -744,7 +765,7 @@ static int lxc_container_name_to_pid(const char *lxcname_or_pid,
ret
=
kill
(
pid
,
0
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to send signal to pid %d"
,
(
int
)
pid
);
return
-
EPERM
;
return
-
1
;
}
return
pid
;
...
...
@@ -760,7 +781,7 @@ int lxc_inherit_namespace(const char *lxcname_or_pid, const char *lxcpath,
if
(
lastslash
)
{
dup
=
strdup
(
lxcname_or_pid
);
if
(
!
dup
)
return
-
ENOMEM
;
return
-
1
;
dup
[
lastslash
-
lxcname_or_pid
]
=
'\0'
;
pid
=
lxc_container_name_to_pid
(
lastslash
+
1
,
dup
);
...
...
@@ -770,11 +791,11 @@ int lxc_inherit_namespace(const char *lxcname_or_pid, const char *lxcpath,
}
if
(
pid
<
0
)
return
-
EINVAL
;
return
-
1
;
fd
=
lxc_preserve_ns
(
pid
,
namespace
);
if
(
fd
<
0
)
return
-
EINVAL
;
return
-
1
;
return
fd
;
}
...
...
@@ -877,9 +898,8 @@ static int rt_sig_num(const char *signame)
{
int
rtmax
=
0
,
sig_n
=
0
;
if
(
strncasecmp
(
signame
,
"max-"
,
4
)
==
0
)
{
if
(
strncasecmp
(
signame
,
"max-"
,
4
)
==
0
)
rtmax
=
1
;
}
signame
+=
4
;
if
(
!
isdigit
(
*
signame
))
...
...
@@ -903,10 +923,10 @@ int sig_parse(const char *signame)
signame
+=
3
;
if
(
strncasecmp
(
signame
,
"rt"
,
2
)
==
0
)
return
rt_sig_num
(
signame
+
2
);
for
(
n
=
0
;
n
<
sizeof
(
signames
)
/
sizeof
((
signames
)[
0
]);
n
++
)
{
for
(
n
=
0
;
n
<
sizeof
(
signames
)
/
sizeof
((
signames
)[
0
]);
n
++
)
if
(
strcasecmp
(
signames
[
n
].
name
,
signame
)
==
0
)
return
signames
[
n
].
num
;
}
}
return
-
1
;
...
...
src/lxc/confile_utils.h
View file @
010a85d1
...
...
@@ -81,7 +81,7 @@ extern int set_config_string_item_max(char **conf_item, const char *value,
extern
int
set_config_path_item
(
char
**
conf_item
,
const
char
*
value
);
extern
int
config_ip_prefix
(
struct
in_addr
*
addr
);
extern
int
network_ifname
(
char
*
valuep
,
const
char
*
value
,
size_t
size
);
extern
int
rand_complete_hwaddr
(
char
*
hwaddr
);
extern
void
rand_complete_hwaddr
(
char
*
hwaddr
);
extern
bool
lxc_config_net_hwaddr
(
const
char
*
line
);
extern
void
update_hwaddr
(
const
char
*
line
);
extern
bool
new_hwaddr
(
char
*
hwaddr
);
...
...
src/lxc/lxccontainer.c
View file @
010a85d1
...
...
@@ -167,11 +167,12 @@ static int ongoing_create(struct lxc_container *c)
ret
=
fcntl
(
fd
,
F_OFD_GETLK
,
&
lk
);
if
(
ret
<
0
&&
errno
==
EINVAL
)
ret
=
flock
(
fd
,
LOCK_EX
|
LOCK_NB
);
close
(
fd
);
if
(
ret
==
0
&&
lk
.
l_pid
!=
-
1
)
{
if
(
ret
==
0
&&
lk
.
l_pid
!=
-
1
)
/* create is still ongoing */
return
1
;
}
/* Create completed but partial is still there. */
return
2
;
...
...
@@ -221,6 +222,7 @@ static void remove_partial(struct lxc_container *c, int fd)
char
*
path
;
close
(
fd
);
/* $lxcpath + '/' + $name + '/partial' + \0 */
len
=
strlen
(
c
->
config_path
)
+
strlen
(
c
->
name
)
+
10
;
path
=
alloca
(
len
);
...
...
@@ -254,7 +256,6 @@ static void remove_partial(struct lxc_container *c, int fd)
* decrement numthreads under privlock, then if it hits 0 you can delete.
* Do not ever use a lxccontainer whose numthreads you did not bump.
*/
static
void
lxc_container_free
(
struct
lxc_container
*
c
)
{
if
(
!
c
)
...
...
@@ -358,7 +359,6 @@ int lxc_container_put(struct lxc_container *c)
}
container_mem_unlock
(
c
);
return
0
;
}
...
...
@@ -385,7 +385,6 @@ static bool do_lxcapi_is_defined(struct lxc_container *c)
on_error:
container_mem_unlock
(
c
);
return
ret
;
}
...
...
@@ -596,7 +595,6 @@ static bool load_config_locked(struct lxc_container *c, const char *fname)
return
false
;
c
->
lxc_conf
->
name
=
c
->
name
;
return
true
;
}
...
...
@@ -610,8 +608,10 @@ static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
return
false
;
fname
=
c
->
configfile
;
if
(
alt_file
)
fname
=
alt_file
;
if
(
!
fname
)
return
false
;
...
...
@@ -746,9 +746,8 @@ static char **split_init_cmd(const char *incmd)
len
=
strlen
(
incmd
)
+
1
;
copy
=
alloca
(
len
);
retlen
=
strlcpy
(
copy
,
incmd
,
len
);
if
(
retlen
>=
len
)
{
if
(
retlen
>=
len
)
return
NULL
;
}
do
{
argv
=
malloc
(
sizeof
(
char
*
));
...
...
@@ -781,62 +780,62 @@ static void free_init_cmd(char **argv)
static
int
lxc_rcv_status
(
int
state_socket
)
{
int
ret
;
int
state
=
-
1
;
int
ret
;
int
state
=
-
1
;
again
:
/* Receive container state. */
ret
=
lxc_abstract_unix_rcv_credential
(
state_socket
,
&
state
,
sizeof
(
int
));
if
(
ret
<=
0
)
{
/* Receive container state. */
ret
=
lxc_abstract_unix_rcv_credential
(
state_socket
,
&
state
,
sizeof
(
int
));
if
(
ret
<=
0
)
{
if
(
errno
!=
EINTR
)
return
-
1
;
TRACE
(
"Caught EINTR; retrying"
);
goto
again
;
}
return
state
;
return
state
;
}
static
bool
wait_on_daemonized_start
(
struct
lxc_handler
*
handler
,
int
pid
)
{
int
ret
,
state
;
int
ret
,
state
;
/* Close write end of the socket pair. */
close
(
handler
->
state_socket_pair
[
1
]);
handler
->
state_socket_pair
[
1
]
=
-
1
;
/* Close write end of the socket pair. */
close
(
handler
->
state_socket_pair
[
1
]);
handler
->
state_socket_pair
[
1
]
=
-
1
;
state
=
lxc_rcv_status
(
handler
->
state_socket_pair
[
0
]);
state
=
lxc_rcv_status
(
handler
->
state_socket_pair
[
0
]);
/* Close read end of the socket pair. */
close
(
handler
->
state_socket_pair
[
0
]);
handler
->
state_socket_pair
[
0
]
=
-
1
;
/* Close read end of the socket pair. */
close
(
handler
->
state_socket_pair
[
0
]);
handler
->
state_socket_pair
[
0
]
=
-
1
;
/* The first child is going to fork() again and then exits. So we reap
* the first child here.
*/
/* The first child is going to fork() again and then exits. So we reap
* the first child here.
*/
ret
=
wait_for_pid
(
pid
);
if
(
ret
<
0
)
DEBUG
(
"Failed waiting on first child %d"
,
pid
);
DEBUG
(
"Failed waiting on first child %d"
,
pid
);
else
DEBUG
(
"First child %d exited"
,
pid
);
DEBUG
(
"First child %d exited"
,
pid
);
if
(
state
<
0
)
{
SYSERROR
(
"Failed to receive the container state"
);
return
false
;
}
if
(
state
<
0
)
{
SYSERROR
(
"Failed to receive the container state"
);
return
false
;
}
/* If we receive anything else then running we know that the container
* failed to start.
*/
if
(
state
!=
RUNNING
)
{
ERROR
(
"Received container state
\"
%s
\"
instead of
\"
RUNNING
\"
"
,
lxc_state2str
(
state
));
return
false
;
}
/* If we receive anything else then running we know that the container
* failed to start.
*/
if
(
state
!=
RUNNING
)
{
ERROR
(
"Received container state
\"
%s
\"
instead of
\"
RUNNING
\"
"
,
lxc_state2str
(
state
));
return
false
;
}
TRACE
(
"Container is in
\"
RUNNING
\"
state"
);
return
true
;
TRACE
(
"Container is in
\"
RUNNING
\"
state"
);
return
true
;
}
static
bool
do_lxcapi_start
(
struct
lxc_container
*
c
,
int
useinit
,
char
*
const
argv
[])
...
...
@@ -1147,6 +1146,7 @@ static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
on_error
:
if
(
inargs
)
{
char
**
arg
;
for
(
arg
=
inargs
;
*
arg
;
arg
++
)
free
(
*
arg
);
free
(
inargs
);
...
...
@@ -1405,9 +1405,9 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
* args.
*/
if
(
argv
)
for
(
nargs
=
0
;
argv
[
nargs
];
nargs
++
)
{
for
(
nargs
=
0
;
argv
[
nargs
];
nargs
++
)
;
}
/* template, path, rootfs and name args */
nargs
+=
4
;
...
...
@@ -1421,6 +1421,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
patharg
=
malloc
(
len
);
if
(
!
patharg
)
_exit
(
EXIT_FAILURE
);
ret
=
snprintf
(
patharg
,
len
,
"--path=%s/%s"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
len
)
_exit
(
EXIT_FAILURE
);
...
...
@@ -1431,6 +1432,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
namearg
=
malloc
(
len
);
if
(
!
namearg
)
_exit
(
EXIT_FAILURE
);
ret
=
snprintf
(
namearg
,
len
,
"--name=%s"
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
len
)
_exit
(
EXIT_FAILURE
);
...
...
@@ -1441,6 +1443,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
rootfsarg
=
malloc
(
len
);
if
(
!
rootfsarg
)
_exit
(
EXIT_FAILURE
);
ret
=
snprintf
(
rootfsarg
,
len
,
"--rootfs=%s"
,
bdev
->
dest
);
if
(
ret
<
0
||
ret
>=
len
)
_exit
(
EXIT_FAILURE
);
...
...
@@ -1478,6 +1481,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
newargv
[
0
]
=
tpath
;
tpath
=
"lxc-usernsexec"
;
n2
[
0
]
=
"lxc-usernsexec"
;
lxc_list_for_each
(
it
,
&
conf
->
id_map
)
{
map
=
it
->
elem
;
n2args
+=
2
;
...
...
@@ -1499,6 +1503,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
hostuid_mapped
=
mapped_hostid
(
geteuid
(),
conf
,
ID_TYPE_UID
);
extraargs
=
hostuid_mapped
>=
0
?
1
:
3
;
n2
=
realloc
(
n2
,
(
nargs
+
n2args
+
extraargs
)
*
sizeof
(
char
*
));
if
(
!
n2
)
_exit
(
EXIT_FAILURE
);
...
...
@@ -1516,6 +1521,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
SYSERROR
(
"out of memory"
);
_exit
(
EXIT_FAILURE
);
}
ret
=
snprintf
(
n2
[
n2args
-
1
],
200
,
"u:%d:%d:1"
,
hostuid_mapped
,
geteuid
());
if
(
ret
<
0
||
ret
>=
200
)
...
...
@@ -1524,6 +1530,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
hostgid_mapped
=
mapped_hostid
(
getegid
(),
conf
,
ID_TYPE_GID
);
extraargs
=
hostgid_mapped
>=
0
?
1
:
3
;
n2
=
realloc
(
n2
,
(
nargs
+
n2args
+
extraargs
)
*
sizeof
(
char
*
));
if
(
!
n2
)
_exit
(
EXIT_FAILURE
);
...
...
@@ -1547,7 +1554,9 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
if
(
ret
<
0
||
ret
>=
200
)
_exit
(
EXIT_FAILURE
);
}
n2
[
n2args
++
]
=
"--"
;
for
(
i
=
0
;
i
<
nargs
;
i
++
)
n2
[
i
+
n2args
]
=
newargv
[
i
];
n2args
+=
nargs
;
...
...
@@ -1644,6 +1653,7 @@ static bool prepend_lxc_header(char *path, const char *t, char *const argv[])
goto
out_free_contents
;
contents
[
flen
]
=
'\0'
;
ret
=
fclose
(
f
);
f
=
NULL
;
if
(
ret
<
0
)
...
...
@@ -1681,6 +1691,7 @@ static bool prepend_lxc_header(char *path, const char *t, char *const argv[])
}
fprintf
(
f
,
"
\n
"
);
}
#if HAVE_LIBGNUTLS
fprintf
(
f
,
"# Template script checksum (SHA-1): "
);
for
(
i
=
0
;
i
<
SHA_DIGEST_LENGTH
;
i
++
)
...
...
@@ -1770,7 +1781,7 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
* existing container. Return an error, but do NOT delete the container.
*/
if
(
do_lxcapi_is_defined
(
c
)
&&
c
->
lxc_conf
&&
c
->
lxc_conf
->
rootfs
.
path
&&
access
(
c
->
lxc_conf
->
rootfs
.
path
,
F_OK
)
==
0
&&
tpath
)
{
access
(
c
->
lxc_conf
->
rootfs
.
path
,
F_OK
)
==
0
&&
tpath
)
{
ERROR
(
"Container
\"
%s
\"
already exists in
\"
%s
\"
"
,
c
->
name
,
c
->
config_path
);
goto
free_tpath
;
...
...
@@ -1811,6 +1822,7 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
*/
if
(
!
c
->
save_config
(
c
,
NULL
))
ERROR
(
"Failed to save initial config for
\"
%s
\"
"
,
c
->
name
);
ret
=
true
;
goto
out
;
}
...
...
@@ -1856,14 +1868,17 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
bdev
->
ops
->
destroy
(
bdev
);
_exit
(
EXIT_FAILURE
);
}
_exit
(
EXIT_SUCCESS
);
}
if
(
wait_for_pid
(
pid
)
!=
0
)
goto
out_unlock
;
/* Reload config to get the rootfs. */
lxc_conf_free
(
c
->
lxc_conf
);
c
->
lxc_conf
=
NULL
;
if
(
!
load_config_locked
(
c
,
c
->
configfile
))
goto
out_unlock
;
...
...
@@ -1881,15 +1896,18 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
goto
out_unlock
;
}
}
ret
=
load_config_locked
(
c
,
c
->
configfile
);
out_unlock
:
umask
(
mask
);
if
(
partial_fd
>=
0
)
remove_partial
(
c
,
partial_fd
);
out
:
if
(
!
ret
)
container_destroy
(
c
,
NULL
);
free_tpath
:
free
(
tpath
);
return
ret
;
...
...
@@ -1900,7 +1918,9 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
int
flags
,
char
*
const
argv
[])
{
bool
ret
;
current_config
=
c
?
c
->
lxc_conf
:
NULL
;
ret
=
do_lxcapi_create
(
c
,
t
,
bdevtype
,
specs
,
flags
,
argv
);
current_config
=
NULL
;
return
ret
;
...
...
@@ -1981,6 +2001,7 @@ static bool do_lxcapi_reboot2(struct lxc_container *c, int timeout)
if
(
killret
<
0
)
{
if
(
state_client_fd
>=
0
)
close
(
state_client_fd
);
WARN
(
"Failed to send signal %d to pid %d"
,
rebootsignal
,
pid
);
return
false
;
}
...
...
@@ -2051,6 +2072,7 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
if
(
killret
<
0
)
{
if
(
state_client_fd
>=
0
)
close
(
state_client_fd
);
WARN
(
"Failed to send signal %d to pid %d"
,
haltsignal
,
pid
);
return
false
;
}
...
...
@@ -2151,6 +2173,7 @@ static bool do_lxcapi_clear_config_item(struct lxc_container *c,
*/
if
(
config
&&
config
->
clr
)
ret
=
config
->
clr
(
key
,
c
->
lxc_conf
,
NULL
);
if
(
!
ret
)
do_clear_unexp_config_line
(
c
->
lxc_conf
,
key
);
...
...
@@ -2164,10 +2187,11 @@ static inline bool enter_net_ns(struct lxc_container *c)
{
pid_t
pid
=
do_lxcapi_init_pid
(
c
);
if
((
geteuid
()
!=
0
||
(
c
->
lxc_conf
&&
!
lxc_list_empty
(
&
c
->
lxc_conf
->
id_map
)))
&&
access
(
"/proc/self/ns/user"
,
F_OK
)
==
0
)
{
if
((
geteuid
()
!=
0
||
(
c
->
lxc_conf
&&
!
lxc_list_empty
(
&
c
->
lxc_conf
->
id_map
)))
&&
(
access
(
"/proc/self/ns/user"
,
F_OK
)
==
0
))
if
(
!
switch_to_ns
(
pid
,
"user"
))
return
false
;
}
return
switch_to_ns
(
pid
,
"net"
);
}
...
...
@@ -2229,10 +2253,11 @@ static char** get_from_array(char ***names, char *cname, int size)
return
(
char
**
)
bsearch
(
&
cname
,
*
names
,
size
,
sizeof
(
char
*
),
(
int
(
*
)(
const
void
*
,
const
void
*
))
string_cmp
);
}
static
bool
array_contains
(
char
***
names
,
char
*
cname
,
int
size
)
{
static
bool
array_contains
(
char
***
names
,
char
*
cname
,
int
size
)
{
if
(
get_from_array
(
names
,
cname
,
size
)
!=
NULL
)
return
true
;
return
false
;
}
...
...
@@ -2243,6 +2268,7 @@ static bool remove_from_array(char ***names, char *cname, int size)
free
(
result
);
return
true
;
}
return
false
;
}
...
...
@@ -2293,6 +2319,7 @@ static char ** do_lxcapi_get_interfaces(struct lxc_container *c)
}
count
++
;
}
ret
=
0
;
out
:
...
...
@@ -2322,6 +2349,7 @@ static char ** do_lxcapi_get_interfaces(struct lxc_container *c)
if
(
wait_for_pid
(
pid
)
!=
0
)
{
for
(
i
=
0
;
i
<
count
;
i
++
)
free
(
interfaces
[
i
]);
free
(
interfaces
);
interfaces
=
NULL
;
}
...
...
@@ -2422,8 +2450,10 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
address
);
goto
out
;
}
count
++
;
}
ret
=
0
;
out
:
...
...
@@ -2497,8 +2527,10 @@ static char* do_lxcapi_get_running_config_item(struct lxc_container *c, const ch
if
(
!
c
||
!
c
->
lxc_conf
)
return
NULL
;
if
(
container_mem_lock
(
c
))
return
NULL
;
ret
=
lxc_cmd_get_config_item
(
c
->
name
,
key
,
do_lxcapi_get_config_path
(
c
));
container_mem_unlock
(
c
);
return
ret
;
...
...
@@ -2542,6 +2574,7 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
if
(
!
alt_file
)
alt_file
=
c
->
configfile
;
if
(
!
alt_file
)
return
false
;
...
...
@@ -2615,6 +2648,7 @@ static bool mod_rdep(struct lxc_container *c0, struct lxc_container *c, bool inc
ret
=
snprintf
(
path
,
MAXPATHLEN
,
"%s/%s/lxc_snapshots"
,
c0
->
config_path
,
c0
->
name
);
if
(
ret
<
0
||
ret
>
MAXPATHLEN
)
goto
out
;
ret
=
snprintf
(
newpath
,
MAXPATHLEN
,
"%s
\n
%s
\n
"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>
MAXPATHLEN
)
goto
out
;
...
...
@@ -2702,6 +2736,7 @@ static bool mod_rdep(struct lxc_container *c0, struct lxc_container *c, bool inc
goto
out
;
}
}
close
(
fd
);
}
...
...
@@ -2737,9 +2772,11 @@ void mod_all_rdeps(struct lxc_container *c, bool inc)
ERROR
(
"Path name too long"
);
return
;
}
f
=
fopen
(
path
,
"r"
);
if
(
f
==
NULL
)
return
;
while
(
getline
(
&
lxcpath
,
&
pathlen
,
f
)
!=
-
1
)
{
if
(
getline
(
&
lxcname
,
&
namelen
,
f
)
==
-
1
)
{
ERROR
(
"badly formatted file %s"
,
path
);
...
...
@@ -2754,11 +2791,14 @@ void mod_all_rdeps(struct lxc_container *c, bool inc)
lxcpath
,
lxcname
);
continue
;
}
if
(
!
mod_rdep
(
p
,
c
,
inc
))
ERROR
(
"Failed to update snapshots file for %s:%s"
,
lxcpath
,
lxcname
);
lxc_container_put
(
p
);
}
out
:
free
(
lxcpath
);
free
(
lxcname
);
...
...
@@ -2777,20 +2817,24 @@ static bool has_fs_snapshots(struct lxc_container *c)
c
->
name
);
if
(
ret
<
0
||
ret
>
MAXPATHLEN
)
goto
out
;
/* If the file doesn't exist there are no snapshots. */
if
(
stat
(
path
,
&
fbuf
)
<
0
)
goto
out
;
v
=
fbuf
.
st_size
;
if
(
v
!=
0
)
{
f
=
fopen
(
path
,
"r"
);
if
(
!
f
)
goto
out
;
ret
=
fscanf
(
f
,
"%d"
,
&
v
);
fclose
(
f
);
/* TODO: Figure out what to do with the return value of fscanf. */
if
(
ret
!=
1
)
INFO
(
"Container uses new lxc-snapshots format %s"
,
path
);
}
bret
=
v
!=
0
;
out
:
...
...
@@ -2806,9 +2850,11 @@ static bool has_snapshots(struct lxc_container *c)
if
(
!
get_snappath_dir
(
c
,
path
))
return
false
;
dir
=
opendir
(
path
);
if
(
!
dir
)
return
false
;
while
((
direntp
=
readdir
(
dir
)))
{
if
(
!
strcmp
(
direntp
->
d_name
,
"."
))
continue
;
...
...
@@ -2818,6 +2864,7 @@ static bool has_snapshots(struct lxc_container *c)
count
++
;
break
;
}
closedir
(
dir
);
return
count
>
0
;
}
...
...
@@ -2901,6 +2948,7 @@ static bool container_destroy(struct lxc_container *c,
if
(
current_config
&&
conf
==
current_config
)
{
current_config
=
NULL
;
if
(
conf
->
logfd
!=
-
1
)
{
close
(
conf
->
logfd
);
conf
->
logfd
=
-
1
;
...
...
@@ -2966,6 +3014,7 @@ static bool container_destroy(struct lxc_container *c,
ret
=
snprintf
(
path
,
len
,
"%s/%s"
,
p1
,
c
->
name
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
goto
out
;
if
(
am_guest_unpriv
())
ret
=
userns_exec_full
(
conf
,
lxc_rmdir_onedev_wrapper
,
path
,
"lxc_rmdir_onedev_wrapper"
);
...
...
@@ -2983,6 +3032,7 @@ static bool container_destroy(struct lxc_container *c,
out
:
if
(
path
)
free
(
path
);
container_disk_unlock
(
c
);
return
bret
;
}
...
...
@@ -3011,10 +3061,12 @@ static bool do_lxcapi_destroy_with_snapshots(struct lxc_container *c)
{
if
(
!
c
||
!
lxcapi_is_defined
(
c
))
return
false
;
if
(
!
lxcapi_snapshot_destroy_all
(
c
))
{
ERROR
(
"Error deleting all snapshots"
);
return
false
;
}
return
lxcapi_destroy
(
c
);
}
...
...
@@ -3085,6 +3137,7 @@ static char *lxcapi_config_file_name(struct lxc_container *c)
{
if
(
!
c
||
!
c
->
configfile
)
return
NULL
;
return
strdup
(
c
->
configfile
);
}
...
...
@@ -3092,6 +3145,7 @@ static const char *lxcapi_get_config_path(struct lxc_container *c)
{
if
(
!
c
||
!
c
->
config_path
)
return
NULL
;
return
(
const
char
*
)(
c
->
config_path
);
}
...
...
@@ -3160,6 +3214,7 @@ static bool do_lxcapi_set_config_path(struct lxc_container *c, const char *path)
c
->
config_path
=
oldpath
;
oldpath
=
NULL
;
}
err
:
free
(
oldpath
);
container_mem_unlock
(
c
);
...
...
@@ -3248,6 +3303,7 @@ static int copy_file(const char *old, const char *new)
ERROR
(
"copy destination %s exists"
,
new
);
return
-
1
;
}
ret
=
stat
(
old
,
&
sbuf
);
if
(
ret
<
0
)
{
INFO
(
"Error stat'ing %s"
,
old
);
...
...
@@ -3259,6 +3315,7 @@ static int copy_file(const char *old, const char *new)
SYSERROR
(
"Error opening original file %s"
,
old
);
return
-
1
;
}
out
=
open
(
new
,
O_CREAT
|
O_EXCL
|
O_WRONLY
,
0644
);
if
(
out
<
0
)
{
SYSERROR
(
"Error opening new file %s"
,
new
);
...
...
@@ -3272,14 +3329,17 @@ static int copy_file(const char *old, const char *new)
SYSERROR
(
"Error reading old file %s"
,
old
);
goto
err
;
}
if
(
len
==
0
)
break
;
ret
=
write
(
out
,
buf
,
len
);
if
(
ret
<
len
)
{
/* should we retry? */
SYSERROR
(
"Error: write to new file %s was interrupted"
,
new
);
goto
err
;
}
}
close
(
in
);
close
(
out
);
...
...
@@ -3317,19 +3377,24 @@ static int copyhooks(struct lxc_container *oldc, struct lxc_container *c)
char
tmppath
[
MAXPATHLEN
];
if
(
!
fname
)
/* relative path - we don't support, but maybe we should */
return
0
;
if
(
strncmp
(
hookname
,
cpath
,
len
-
1
)
!=
0
)
{
/* this hook is public - ignore */
continue
;
}
/* copy the script, and change the entry in confile */
ret
=
snprintf
(
tmppath
,
MAXPATHLEN
,
"%s/%s/%s"
,
c
->
config_path
,
c
->
name
,
fname
+
1
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
-
1
;
ret
=
copy_file
(
it
->
elem
,
tmppath
);
if
(
ret
<
0
)
return
-
1
;
free
(
it
->
elem
);
it
->
elem
=
strdup
(
tmppath
);
if
(
!
it
->
elem
)
{
ERROR
(
"out of memory copying hook path"
);
...
...
@@ -3343,6 +3408,7 @@ static int copyhooks(struct lxc_container *oldc, struct lxc_container *c)
ERROR
(
"Error saving new hooks in clone"
);
return
-
1
;
}
do_lxcapi_save_config
(
c
,
NULL
);
return
0
;
}
...
...
@@ -3362,12 +3428,14 @@ static int copy_fstab(struct lxc_container *oldc, struct lxc_container *c)
char
*
p
=
strrchr
(
oldpath
,
'/'
);
if
(
!
p
)
return
-
1
;
ret
=
snprintf
(
newpath
,
MAXPATHLEN
,
"%s/%s%s"
,
c
->
config_path
,
c
->
name
,
p
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
{
ERROR
(
"error printing new path for %s"
,
oldpath
);
return
-
1
;
}
if
(
file_exists
(
newpath
))
{
ERROR
(
"error: fstab file %s exists"
,
newpath
);
return
-
1
;
...
...
@@ -3377,12 +3445,15 @@ static int copy_fstab(struct lxc_container *oldc, struct lxc_container *c)
ERROR
(
"error: copying %s to %s"
,
oldpath
,
newpath
);
return
-
1
;
}
free
(
c
->
lxc_conf
->
fstab
);
c
->
lxc_conf
->
fstab
=
strdup
(
newpath
);
if
(
!
c
->
lxc_conf
->
fstab
)
{
ERROR
(
"error: allocating pathname"
);
return
-
1
;
}
if
(
!
do_append_unexp_config_line
(
c
->
lxc_conf
,
"lxc.mount.fstab"
,
newpath
))
{
ERROR
(
"error saving new lxctab"
);
return
-
1
;
...
...
@@ -3402,12 +3473,14 @@ static void copy_rdepends(struct lxc_container *c, struct lxc_container *c0)
WARN
(
"Error copying reverse dependencies"
);
return
;
}
ret
=
snprintf
(
path1
,
MAXPATHLEN
,
"%s/%s/lxc_rdepends"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
{
WARN
(
"Error copying reverse dependencies"
);
return
;
}
if
(
copy_file
(
path0
,
path1
)
<
0
)
{
INFO
(
"Error copying reverse dependencies"
);
return
;
...
...
@@ -3425,15 +3498,20 @@ static bool add_rdepends(struct lxc_container *c, struct lxc_container *c0)
c
->
name
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
false
;
f
=
fopen
(
path
,
"a"
);
if
(
!
f
)
return
false
;
bret
=
true
;
/* If anything goes wrong, just return an error. */
if
(
fprintf
(
f
,
"%s
\n
%s
\n
"
,
c0
->
config_path
,
c0
->
name
)
<
0
)
bret
=
false
;
if
(
fclose
(
f
)
!=
0
)
bret
=
false
;
return
bret
;
}
...
...
@@ -3506,6 +3584,7 @@ static int copy_storage(struct lxc_container *c0, struct lxc_container *c,
if
(
flags
&
LXC_CLONE_SNAPSHOT
)
copy_rdepends
(
c
,
c0
);
if
(
need_rdep
)
{
if
(
!
add_rdepends
(
c
,
c0
))
WARN
(
"Error adding reverse dependency from %s to %s"
,
...
...
@@ -3543,30 +3622,36 @@ static int clone_update_rootfs(struct clone_update_data *data)
ERROR
(
"Failed to setgid to 0"
);
return
-
1
;
}
if
(
setuid
(
0
)
<
0
)
{
ERROR
(
"Failed to setuid to 0"
);
return
-
1
;
}
if
(
setgroups
(
0
,
NULL
)
<
0
)
WARN
(
"Failed to clear groups"
);
if
(
unshare
(
CLONE_NEWNS
)
<
0
)
return
-
1
;
bdev
=
storage_init
(
c
->
lxc_conf
);
if
(
!
bdev
)
return
-
1
;
if
(
strcmp
(
bdev
->
type
,
"dir"
)
!=
0
)
{
if
(
unshare
(
CLONE_NEWNS
)
<
0
)
{
ERROR
(
"error unsharing mounts"
);
storage_put
(
bdev
);
return
-
1
;
}
if
(
detect_shared_rootfs
())
{
if
(
mount
(
NULL
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
NULL
))
{
SYSERROR
(
"Failed to make / rslave"
);
ERROR
(
"Continuing..."
);
}
}
if
(
bdev
->
ops
->
mount
(
bdev
)
<
0
)
{
storage_put
(
bdev
);
return
-
1
;
...
...
@@ -3578,21 +3663,20 @@ static int clone_update_rootfs(struct clone_update_data *data)
if
(
!
lxc_list_empty
(
&
conf
->
hooks
[
LXCHOOK_CLONE
]))
{
/* Start of environment variable setup for hooks */
if
(
c0
->
name
&&
setenv
(
"LXC_SRC_NAME"
,
c0
->
name
,
1
))
{
if
(
c0
->
name
&&
setenv
(
"LXC_SRC_NAME"
,
c0
->
name
,
1
))
SYSERROR
(
"failed to set environment variable for source container name"
);
}
if
(
setenv
(
"LXC_NAME"
,
c
->
name
,
1
))
{
if
(
setenv
(
"LXC_NAME"
,
c
->
name
,
1
))
SYSERROR
(
"failed to set environment variable for container name"
);
}
if
(
conf
->
rcfile
&&
setenv
(
"LXC_CONFIG_FILE"
,
conf
->
rcfile
,
1
))
{
if
(
conf
->
rcfile
&&
setenv
(
"LXC_CONFIG_FILE"
,
conf
->
rcfile
,
1
))
SYSERROR
(
"failed to set environment variable for config path"
);
}
if
(
bdev
->
dest
&&
setenv
(
"LXC_ROOTFS_MOUNT"
,
bdev
->
dest
,
1
))
{
if
(
bdev
->
dest
&&
setenv
(
"LXC_ROOTFS_MOUNT"
,
bdev
->
dest
,
1
))
SYSERROR
(
"failed to set environment variable for rootfs mount"
);
}
if
(
conf
->
rootfs
.
path
&&
setenv
(
"LXC_ROOTFS_PATH"
,
conf
->
rootfs
.
path
,
1
))
{
if
(
conf
->
rootfs
.
path
&&
setenv
(
"LXC_ROOTFS_PATH"
,
conf
->
rootfs
.
path
,
1
))
SYSERROR
(
"failed to set environment variable for rootfs mount"
);
}
if
(
run_lxc_hooks
(
c
->
name
,
"clone"
,
conf
,
hookargs
))
{
ERROR
(
"Error executing clone hook for %s"
,
c
->
name
);
...
...
@@ -3607,16 +3691,20 @@ static int clone_update_rootfs(struct clone_update_data *data)
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
-
1
;
if
(
!
file_exists
(
path
))
return
0
;
if
(
!
(
fout
=
fopen
(
path
,
"w"
)))
{
SYSERROR
(
"unable to open %s: ignoring"
,
path
);
return
0
;
}
if
(
fprintf
(
fout
,
"%s"
,
c
->
name
)
<
0
)
{
fclose
(
fout
);
return
-
1
;
}
if
(
fclose
(
fout
)
<
0
)
return
-
1
;
}
else
{
...
...
@@ -3650,9 +3738,11 @@ static int create_file_dirname(char *path, struct lxc_conf *conf)
if
(
!
p
)
return
-
1
;
*
p
=
'\0'
;
ret
=
do_create_container_dir
(
path
,
conf
);
*
p
=
'/'
;
return
ret
;
}
...
...
@@ -3684,8 +3774,10 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
/* Make sure the container doesn't yet exist. */
if
(
!
newname
)
newname
=
c
->
name
;
if
(
!
lxcpath
)
lxcpath
=
do_lxcapi_get_config_path
(
c
);
ret
=
snprintf
(
newpath
,
MAXPATHLEN
,
"%s/%s/config"
,
lxcpath
,
newname
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
{
SYSERROR
(
"clone: failed making config pathname"
);
...
...
@@ -3727,7 +3819,9 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
clear_unexp_config_line
(
c
->
lxc_conf
,
"lxc.rootfs.path"
,
false
);
write_config
(
fd
,
c
->
lxc_conf
);
close
(
fd
);
c
->
lxc_conf
->
rootfs
.
path
=
origroot
;
free
(
c
->
lxc_conf
->
unexpanded_config
);
c
->
lxc_conf
->
unexpanded_config
=
saved_unexp_conf
;
saved_unexp_conf
=
NULL
;
...
...
@@ -3771,7 +3865,6 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
if
(
ret
<
0
)
goto
out
;
/* update utsname */
if
(
!
(
flags
&
LXC_CLONE_KEEPNAME
))
{
clear_unexp_config_line
(
c2
->
lxc_conf
,
"lxc.utsname"
,
false
);
...
...
@@ -3819,17 +3912,21 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
SYSERROR
(
"fork"
);
goto
out
;
}
if
(
pid
>
0
)
{
ret
=
wait_for_pid
(
pid
);
if
(
ret
)
goto
out
;
container_mem_unlock
(
c
);
return
c2
;
}
data
.
c0
=
c
;
data
.
c1
=
c2
;
data
.
flags
=
flags
;
data
.
hookargs
=
hookargs
;
if
(
am_guest_unpriv
())
ret
=
userns_exec_full
(
c
->
lxc_conf
,
clone_update_rootfs_wrapper
,
&
data
,
"clone_update_rootfs_wrapper"
);
...
...
@@ -3846,6 +3943,7 @@ out:
if
(
c2
)
{
if
(
!
storage_copied
)
c2
->
lxc_conf
->
rootfs
.
path
=
NULL
;
c2
->
destroy
(
c2
);
lxc_container_put
(
c2
);
}
...
...
@@ -3859,9 +3957,11 @@ static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *n
char
**
hookargs
)
{
struct
lxc_container
*
ret
;
current_config
=
c
?
c
->
lxc_conf
:
NULL
;
ret
=
do_lxcapi_clone
(
c
,
newname
,
lxcpath
,
flags
,
bdevtype
,
bdevdata
,
newsize
,
hookargs
);
current_config
=
NULL
;
return
ret
;
}
...
...
@@ -3877,6 +3977,7 @@ static bool do_lxcapi_rename(struct lxc_container *c, const char *newname)
ERROR
(
"Renaming a container with snapshots is not supported"
);
return
false
;
}
bdev
=
storage_init
(
c
->
lxc_conf
);
if
(
!
bdev
)
{
ERROR
(
"Failed to find original backing store type"
);
...
...
@@ -3897,6 +3998,7 @@ static bool do_lxcapi_rename(struct lxc_container *c, const char *newname)
ERROR
(
"Could not destroy existing container %s"
,
c
->
name
);
return
false
;
}
return
true
;
}
...
...
@@ -3927,20 +4029,24 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options
command
.
program
=
(
char
*
)
program
;
command
.
argv
=
(
char
**
)
argv
;
r
=
lxc_attach
(
c
->
name
,
c
->
config_path
,
lxc_attach_run_command
,
&
command
,
options
,
&
pid
);
if
(
r
<
0
)
{
ERROR
(
"ups"
);
return
r
;
}
return
lxc_wait_for_pid_status
(
pid
);
}
static
int
lxcapi_attach_run_wait
(
struct
lxc_container
*
c
,
lxc_attach_options_t
*
options
,
const
char
*
program
,
const
char
*
const
argv
[])
{
int
ret
;
current_config
=
c
?
c
->
lxc_conf
:
NULL
;
ret
=
do_lxcapi_attach_run_wait
(
c
,
options
,
program
,
argv
);
current_config
=
NULL
;
return
ret
;
}
...
...
@@ -3951,11 +4057,14 @@ static int get_next_index(const char *lxcpath, char *cname)
int
i
=
0
,
ret
;
fname
=
alloca
(
strlen
(
lxcpath
)
+
20
);
while
(
1
)
{
sprintf
(
fname
,
"%s/snap%d"
,
lxcpath
,
i
);
ret
=
stat
(
fname
,
&
sb
);
if
(
ret
!=
0
)
return
i
;
i
++
;
}
}
...
...
@@ -3963,6 +4072,7 @@ static int get_next_index(const char *lxcpath, char *cname)
static
bool
get_snappath_dir
(
struct
lxc_container
*
c
,
char
*
snappath
)
{
int
ret
;
/*
* If the old style snapshot path exists, use it
* /var/lib/lxc -> /var/lib/lxcsnaps
...
...
@@ -3970,10 +4080,12 @@ static bool get_snappath_dir(struct lxc_container *c, char *snappath)
ret
=
snprintf
(
snappath
,
MAXPATHLEN
,
"%ssnaps"
,
c
->
config_path
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
false
;
if
(
dir_exists
(
snappath
))
{
ret
=
snprintf
(
snappath
,
MAXPATHLEN
,
"%ssnaps/%s"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
false
;
return
true
;
}
...
...
@@ -3984,6 +4096,7 @@ static bool get_snappath_dir(struct lxc_container *c, char *snappath)
ret
=
snprintf
(
snappath
,
MAXPATHLEN
,
"%s/%s/snaps"
,
c
->
config_path
,
c
->
name
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
false
;
return
true
;
}
...
...
@@ -4029,6 +4142,7 @@ static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
ERROR
(
"and keep the original container pristine."
);
flags
&=
~
LXC_CLONE_SNAPSHOT
|
LXC_CLONE_MAYBE_SNAPSHOT
;
}
c2
=
do_lxcapi_clone
(
c
,
newname
,
snappath
,
flags
,
NULL
,
NULL
,
0
,
NULL
);
if
(
!
c2
)
{
ERROR
(
"clone of %s:%s failed"
,
c
->
config_path
,
c
->
name
);
...
...
@@ -4055,11 +4169,13 @@ static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
ERROR
(
"Failed to open %s"
,
dfnam
);
return
-
1
;
}
if
(
fprintf
(
f
,
"%s"
,
buffer
)
<
0
)
{
SYSERROR
(
"Writing timestamp"
);
fclose
(
f
);
return
-
1
;
}
ret
=
fclose
(
f
);
if
(
ret
!=
0
)
{
SYSERROR
(
"Writing timestamp"
);
...
...
@@ -4070,6 +4186,7 @@ static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
/* $p / $name / comment \0 */
int
len
=
strlen
(
snappath
)
+
strlen
(
newname
)
+
10
;
char
*
path
=
alloca
(
len
);
sprintf
(
path
,
"%s/%s/comment"
,
snappath
,
newname
);
return
copy_file
(
commentfile
,
path
)
<
0
?
-
1
:
i
;
}
...
...
@@ -4100,6 +4217,7 @@ static char *get_snapcomment_path(char* snappath, char *name)
s
=
NULL
;
}
}
return
s
;
}
...
...
@@ -4112,9 +4230,11 @@ static char *get_timestamp(char* snappath, char *name)
ret
=
snprintf
(
path
,
MAXPATHLEN
,
"%s/%s/ts"
,
snappath
,
name
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
NULL
;
fin
=
fopen
(
path
,
"r"
);
if
(
!
fin
)
return
NULL
;
(
void
)
fseek
(
fin
,
0
,
SEEK_END
);
len
=
ftell
(
fin
);
(
void
)
fseek
(
fin
,
0
,
SEEK_SET
);
...
...
@@ -4129,6 +4249,7 @@ static char *get_timestamp(char* snappath, char *name)
}
}
}
fclose
(
fin
);
return
s
;
}
...
...
@@ -4148,9 +4269,10 @@ static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot
ERROR
(
"path name too long"
);
return
-
1
;
}
dir
=
opendir
(
snappath
);
if
(
!
dir
)
{
INFO
(
"
f
ailed to open %s - assuming no snapshots"
,
snappath
);
INFO
(
"
F
ailed to open %s - assuming no snapshots"
,
snappath
);
return
0
;
}
...
...
@@ -4166,30 +4288,35 @@ static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot
ERROR
(
"pathname too long"
);
goto
out_free
;
}
if
(
!
file_exists
(
path2
))
continue
;
nsnaps
=
realloc
(
snaps
,
(
count
+
1
)
*
sizeof
(
*
snaps
));
if
(
!
nsnaps
)
{
SYSERROR
(
"Out of memory"
);
goto
out_free
;
}
snaps
=
nsnaps
;
snaps
[
count
].
free
=
lxcsnap_free
;
snaps
[
count
].
name
=
strdup
(
direntp
->
d_name
);
if
(
!
snaps
[
count
].
name
)
goto
out_free
;
snaps
[
count
].
lxcpath
=
strdup
(
snappath
);
if
(
!
snaps
[
count
].
lxcpath
)
{
free
(
snaps
[
count
].
name
);
goto
out_free
;
}
snaps
[
count
].
comment_pathname
=
get_snapcomment_path
(
snappath
,
direntp
->
d_name
);
snaps
[
count
].
timestamp
=
get_timestamp
(
snappath
,
direntp
->
d_name
);
count
++
;
}
if
(
closedir
(
dir
))
WARN
(
"
f
ailed to close directory"
);
WARN
(
"
F
ailed to close directory"
);
*
ret_snaps
=
snaps
;
return
count
;
...
...
@@ -4197,12 +4324,16 @@ static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot
out_free
:
if
(
snaps
)
{
int
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
lxcsnap_free
(
&
snaps
[
i
]);
free
(
snaps
);
}
if
(
closedir
(
dir
))
WARN
(
"failed to close directory"
);
WARN
(
"Failed to close directory"
);
return
-
1
;
}
...
...
@@ -4250,8 +4381,10 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
snap
=
lxc_container_new
(
snapname
,
clonelxcpath
);
if
(
!
snap
||
!
lxcapi_is_defined
(
snap
))
{
ERROR
(
"Could not open snapshot %s"
,
snapname
);
if
(
snap
)
lxc_container_put
(
snap
);
storage_put
(
bdev
);
return
false
;
}
...
...
@@ -4270,11 +4403,13 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
if
(
!
strcmp
(
bdev
->
type
,
"overlay"
)
||
!
strcmp
(
bdev
->
type
,
"overlayfs"
))
flags
|=
LXC_STORAGE_INTERNAL_OVERLAY_RESTORE
;
rest
=
lxcapi_clone
(
snap
,
newname
,
c
->
config_path
,
flags
,
bdev
->
type
,
NULL
,
0
,
NULL
);
storage_put
(
bdev
);
if
(
rest
&&
lxcapi_is_defined
(
rest
))
b
=
true
;
if
(
rest
)
lxc_container_put
(
rest
);
...
...
@@ -4299,11 +4434,13 @@ static bool do_snapshot_destroy(const char *snapname, const char *clonelxcpath)
ERROR
(
"Could not destroy snapshot %s"
,
snapname
);
goto
err
;
}
bret
=
true
;
err
:
if
(
snap
)
lxc_container_put
(
snap
);
return
bret
;
}
...
...
@@ -4318,11 +4455,14 @@ static bool remove_all_snapshots(const char *path)
SYSERROR
(
"opendir on snapshot path %s"
,
path
);
return
false
;
}
while
((
direntp
=
readdir
(
dir
)))
{
if
(
!
strcmp
(
direntp
->
d_name
,
"."
))
continue
;
if
(
!
strcmp
(
direntp
->
d_name
,
".."
))
continue
;
if
(
!
do_snapshot_destroy
(
direntp
->
d_name
,
path
))
{
bret
=
false
;
continue
;
...
...
@@ -4507,6 +4647,7 @@ static bool do_lxcapi_add_device_node(struct lxc_container *c, const char *src_p
ERROR
(
LXC_UNPRIV_EOPNOTSUPP
,
__FUNCTION__
);
return
false
;
}
return
add_remove_device_node
(
c
,
src_path
,
dest_path
,
true
);
}
...
...
@@ -4518,6 +4659,7 @@ static bool do_lxcapi_remove_device_node(struct lxc_container *c, const char *sr
ERROR
(
LXC_UNPRIV_EOPNOTSUPP
,
__FUNCTION__
);
return
false
;
}
return
add_remove_device_node
(
c
,
src_path
,
dest_path
,
false
);
}
...
...
@@ -4621,6 +4763,7 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
ERROR
(
"Network device
\"
%s
\"
not found"
,
ifname
);
else
ERROR
(
"Failed to remove network device
\"
%s
\"
"
,
ifname
);
_exit
(
EXIT_FAILURE
);
}
...
...
@@ -4654,11 +4797,10 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
addr
=
(
void
*
)
opts
+
sizeof
(
*
opts
);
end
=
(
void
*
)
opts
+
size
;
for
(;
addr
<
end
;
addr
++
)
{
if
(
*
addr
)
{
for
(;
addr
<
end
;
addr
++
)
if
(
*
addr
)
return
-
E2BIG
;
}
}
}
/* If the caller has a smaller struct, let's zero out the end for them
...
...
@@ -4680,6 +4822,7 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
ERROR
(
"container is not running"
);
goto
on_error
;
}
ret
=
!
__criu_pre_dump
(
c
,
valid_opts
);
break
;
case
MIGRATE_DUMP
:
...
...
@@ -4687,6 +4830,7 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
ERROR
(
"container is not running"
);
goto
on_error
;
}
ret
=
!
__criu_dump
(
c
,
valid_opts
);
break
;
case
MIGRATE_RESTORE
:
...
...
@@ -4694,6 +4838,7 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
ERROR
(
"container is already running"
);
goto
on_error
;
}
ret
=
!
__criu_restore
(
c
,
valid_opts
);
break
;
case
MIGRATE_FEATURE_CHECK
:
...
...
@@ -4772,6 +4917,7 @@ static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t
ret
=
do_lxcapi_attach_run_wait
(
c
,
options
,
program
,
(
const
char
*
const
*
)
argv
);
free
((
void
*
)
argv
);
out
:
current_config
=
NULL
;
return
ret
;
...
...
@@ -4796,7 +4942,6 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
c
->
config_path
=
strdup
(
configpath
);
else
c
->
config_path
=
strdup
(
lxc_global_config_value
(
"lxc.lxcpath"
));
if
(
!
c
->
config_path
)
{
fprintf
(
stderr
,
"Failed to allocate memory for %s
\n
"
,
name
);
goto
err
;
...
...
@@ -4840,6 +4985,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
container_destroy
(
c
,
NULL
);
lxcapi_clear_config
(
c
);
}
c
->
daemonize
=
true
;
c
->
pidfile
=
NULL
;
...
...
@@ -4914,6 +5060,7 @@ int lxc_get_wait_states(const char **states)
if
(
states
)
for
(
i
=
0
;
i
<
MAX_STATE
;
i
++
)
states
[
i
]
=
lxc_state2str
(
i
);
return
MAX_STATE
;
}
...
...
@@ -4939,6 +5086,7 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta
if
(
cret
)
*
cret
=
NULL
;
if
(
names
)
*
names
=
NULL
;
...
...
@@ -4950,10 +5098,10 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta
if
(
!
config_file_exists
(
lxcpath
,
direntp
->
d_name
))
continue
;
if
(
names
)
{
if
(
names
)
if
(
!
add_to_array
(
names
,
direntp
->
d_name
,
cfound
))
goto
free_bad
;
}
cfound
++
;
if
(
!
cret
)
{
...
...
@@ -4965,17 +5113,22 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta
if
(
!
c
)
{
INFO
(
"Container %s:%s has a config but could not be loaded"
,
lxcpath
,
direntp
->
d_name
);
if
(
names
)
if
(
!
remove_from_array
(
names
,
direntp
->
d_name
,
cfound
--
))
goto
free_bad
;
continue
;
}
if
(
!
do_lxcapi_is_defined
(
c
))
{
INFO
(
"Container %s:%s has a config but is not defined"
,
lxcpath
,
direntp
->
d_name
);
if
(
names
)
if
(
!
remove_from_array
(
names
,
direntp
->
d_name
,
cfound
--
))
goto
free_bad
;
lxc_container_put
(
c
);
continue
;
}
...
...
@@ -4984,6 +5137,7 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta
lxc_container_put
(
c
);
goto
free_bad
;
}
nfound
++
;
}
...
...
@@ -4996,11 +5150,13 @@ free_bad:
free
((
*
names
)[
i
]);
free
(
*
names
);
}
if
(
cret
&&
*
cret
)
{
for
(
i
=
0
;
i
<
nfound
;
i
++
)
lxc_container_put
((
*
cret
)[
i
]);
free
(
*
cret
);
}
closedir
(
dir
);
return
-
1
;
}
...
...
@@ -5022,6 +5178,7 @@ int list_active_containers(const char *lxcpath, char ***nret,
if
(
cret
)
*
cret
=
NULL
;
if
(
nret
)
*
nret
=
NULL
;
...
...
@@ -5030,16 +5187,17 @@ int list_active_containers(const char *lxcpath, char ***nret,
return
-
1
;
while
(
getline
(
&
line
,
&
len
,
f
)
!=
-
1
)
{
char
*
p
=
strrchr
(
line
,
' '
),
*
p2
;
if
(
!
p
)
continue
;
p
++
;
if
(
*
p
!=
0x40
)
continue
;
p
++
;
is_hashed
=
false
;
if
(
strncmp
(
p
,
lxcpath
,
lxcpath_len
)
==
0
)
{
p
+=
lxcpath_len
;
}
else
if
(
strncmp
(
p
,
"lxc/"
,
4
)
==
0
)
{
...
...
@@ -5062,11 +5220,13 @@ int list_active_containers(const char *lxcpath, char ***nret,
char
*
recvpath
=
lxc_cmd_get_lxcpath
(
p
);
if
(
!
recvpath
)
continue
;
if
(
strncmp
(
lxcpath
,
recvpath
,
lxcpath_len
)
!=
0
)
{
free
(
recvpath
);
continue
;
}
free
(
recvpath
);
p
=
lxc_cmd_get_name
(
p
);
if
(
!
p
)
continue
;
...
...
@@ -5096,9 +5256,11 @@ int list_active_containers(const char *lxcpath, char ***nret,
if
(
!
c
)
{
INFO
(
"Container %s:%s is running but could not be loaded"
,
lxcpath
,
p
);
remove_from_array
(
&
ct_name
,
p
,
ct_name_cnt
--
);
if
(
is_hashed
)
free
(
p
);
continue
;
}
...
...
@@ -5115,6 +5277,7 @@ int list_active_containers(const char *lxcpath, char ***nret,
lxc_container_put
(
c
);
goto
free_cret_list
;
}
cret_cnt
++
;
}
...
...
@@ -5129,6 +5292,7 @@ int list_active_containers(const char *lxcpath, char ***nret,
*
nret
=
ct_name
;
else
goto
free_ct_name
;
goto
out
;
free_cret_list
:
...
...
@@ -5147,7 +5311,6 @@ free_ct_name:
out
:
free
(
line
);
fclose
(
f
);
return
ret
;
}
...
...
@@ -5176,11 +5339,14 @@ int list_all_containers(const char *lxcpath, char ***nret,
ret
=
-
1
;
goto
free_active_name
;
}
ct_cnt
++
;
}
free
(
active_name
[
i
]);
active_name
[
i
]
=
NULL
;
}
free
(
active_name
);
active_name
=
NULL
;
active_cnt
=
0
;
...
...
@@ -5200,18 +5366,20 @@ int list_all_containers(const char *lxcpath, char ***nret,
ret
=
-
1
;
goto
free_ct_list
;
}
ct_list_cnt
++
;
}
if
(
cret
)
*
cret
=
ct_list
;
if
(
nret
)
if
(
nret
)
{
*
nret
=
ct_name
;
else
{
}
else
{
ret
=
ct_cnt
;
goto
free_ct_name
;
}
return
ct_cnt
;
free_ct_list
:
...
...
src/lxc/start.c
View file @
010a85d1
...
...
@@ -490,11 +490,17 @@ static int lxc_serve_state_socket_pair(const char *name,
again:
ret
=
lxc_abstract_unix_send_credential
(
handler
->
state_socket_pair
[
1
],
&
(
int
){
state
},
sizeof
(
int
));
if
(
ret
!=
sizeof
(
int
))
{
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to send state to %d"
,
handler
->
state_socket_pair
[
1
]);
if
(
errno
==
EINTR
)
goto
again
;
SYSERROR
(
"Failed to send state to %d"
,
handler
->
state_socket_pair
[
1
]);
return
-
1
;
}
if
(
ret
!=
sizeof
(
int
))
{
ERROR
(
"Message too long : %d"
,
handler
->
state_socket_pair
[
1
]);
return
-
1
;
}
...
...
@@ -649,7 +655,7 @@ void lxc_free_handler(struct lxc_handler *handler)
if
(
handler
->
conf
&&
handler
->
conf
->
reboot
==
REBOOT_NONE
)
if
(
handler
->
conf
->
maincmd_fd
>=
0
)
close
(
handler
->
conf
->
maincmd_fd
);
lxc_abstract_unix_
close
(
handler
->
conf
->
maincmd_fd
);
if
(
handler
->
state_socket_pair
[
0
]
>=
0
)
close
(
handler
->
state_socket_pair
[
0
]);
...
...
@@ -671,6 +677,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
handler
=
malloc
(
sizeof
(
*
handler
));
if
(
!
handler
)
return
NULL
;
memset
(
handler
,
0
,
sizeof
(
*
handler
));
/* Note that am_guest_unpriv() checks the effective uid. We
...
...
@@ -704,6 +711,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
ERROR
(
"Failed to create anonymous pair of unix sockets"
);
goto
on_error
;
}
TRACE
(
"Created anonymous pair {%d,%d} of unix sockets"
,
handler
->
state_socket_pair
[
0
],
handler
->
state_socket_pair
[
1
]);
...
...
@@ -716,6 +724,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
goto
on_error
;
}
}
TRACE
(
"Unix domain socket %d for command server is ready"
,
handler
->
conf
->
maincmd_fd
);
...
...
@@ -866,7 +875,7 @@ out_delete_tty:
out_aborting:
(
void
)
lxc_set_state
(
name
,
handler
,
ABORTING
);
out_close_maincmd_fd:
close
(
conf
->
maincmd_fd
);
lxc_abstract_unix_
close
(
conf
->
maincmd_fd
);
conf
->
maincmd_fd
=
-
1
;
return
-
1
;
}
...
...
@@ -953,7 +962,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
* the command socket causing a new process to get ECONNREFUSED
* because we haven't yet closed the command socket.
*/
close
(
handler
->
conf
->
maincmd_fd
);
lxc_abstract_unix_
close
(
handler
->
conf
->
maincmd_fd
);
handler
->
conf
->
maincmd_fd
=
-
1
;
TRACE
(
"Closed command socket"
);
...
...
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