Merge pull request #2520 from brauner/2018-08-11/fix_netnsid_allocation

netns: improve netnsid allocation
This commit is contained in:
Stéphane Graber 2018-08-10 20:40:51 -04:00 committed by GitHub
commit d813c8edf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 28 deletions

View File

@ -187,4 +187,8 @@ extern int __build_bug_on_failed;
#define RTM_NEWNSID 88 #define RTM_NEWNSID 88
#endif #endif
#ifndef NLMSG_ERROR
#define NLMSG_ERROR 0x2
#endif
#endif /* __LXC_MACRO_H */ #endif /* __LXC_MACRO_H */

View File

@ -3192,16 +3192,102 @@ enum {
__LXC_NETNSA_MAX, __LXC_NETNSA_MAX,
}; };
static int nl_send(struct nl_handler *handler, struct nlmsghdr *nlmsghdr)
{
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = nlmsghdr,
.iov_len = nlmsghdr->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
int ret;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
ret = sendmsg(handler->fd, &msg, MSG_NOSIGNAL);
if (ret < 0)
return -errno;
return ret;
}
static int nl_recv(struct nl_handler *handler, struct nlmsghdr *nlmsghdr)
{
int ret;
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = nlmsghdr,
.iov_len = nlmsghdr->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
again:
ret = recvmsg(handler->fd, &msg, 0);
if (ret < 0) {
if (errno == EINTR)
goto again;
return -1;
}
if (!ret)
return 0;
if (msg.msg_flags & MSG_TRUNC && (ret == nlmsghdr->nlmsg_len))
return -EMSGSIZE;
return ret;
}
extern int nl_transaction(struct nl_handler *handler, struct nlmsghdr *request,
struct nlmsghdr *answer)
{
int ret;
ret = nl_send(handler, request);
if (ret < 0)
return ret;
ret = nl_recv(handler, answer);
if (ret < 0)
return ret;
if (answer->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(answer);
return err->error;
}
return 0;
}
int lxc_netns_set_nsid(int fd) int lxc_netns_set_nsid(int fd)
{ {
ssize_t ret; ssize_t ret;
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
NLMSG_ALIGN(sizeof(struct rtgenmsg)) + NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
NLMSG_ALIGN(1024)]; NLMSG_ALIGN(1024)];
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsghdr *l_hdr; struct nlmsghdr *hdr;
struct rtgenmsg *l_msg; struct rtgenmsg *msg;
struct sockaddr_nl l_addr;
__s32 ns_id = -1; __s32 ns_id = -1;
__u32 netns_fd = fd; __u32 netns_fd = fd;
@ -3209,25 +3295,21 @@ int lxc_netns_set_nsid(int fd)
if (ret < 0) if (ret < 0)
return ret; return ret;
memset(l_buffer, 0, sizeof(l_buffer)); memset(buf, 0, sizeof(buf));
l_hdr = (struct nlmsghdr *)l_buffer; hdr = (struct nlmsghdr *)buf;
l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr); msg = (struct rtgenmsg *)NLMSG_DATA(hdr);
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg)); hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*msg));
l_hdr->nlmsg_type = RTM_NEWNSID; hdr->nlmsg_type = RTM_NEWNSID;
l_hdr->nlmsg_flags = NLM_F_REQUEST; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
l_hdr->nlmsg_pid = 0; hdr->nlmsg_pid = 0;
l_hdr->nlmsg_seq = RTM_NEWNSID; hdr->nlmsg_seq = RTM_NEWNSID;
l_msg->rtgen_family = AF_UNSPEC; msg->rtgen_family = AF_UNSPEC;
addattr(l_hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd)); addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
addattr(l_hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id)); addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id));
memset(&l_addr, 0, sizeof(l_addr)); ret = nl_transaction(&nlh, hdr, hdr);
l_addr.nl_family = AF_NETLINK;
ret = sendto(nlh.fd, l_hdr, l_hdr->nlmsg_len, 0,
(struct sockaddr *)&l_addr, sizeof(l_addr));
netlink_close(&nlh); netlink_close(&nlh);
if (ret < 0) if (ret < 0)
return -1; return -1;

View File

@ -237,9 +237,6 @@ extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg)
return ret; return ret;
} }
#ifndef NLMSG_ERROR
#define NLMSG_ERROR 0x2
#endif
extern int netlink_transaction(struct nl_handler *handler, extern int netlink_transaction(struct nl_handler *handler,
struct nlmsg *request, struct nlmsg *answer) struct nlmsg *request, struct nlmsg *answer)
{ {

View File

@ -1821,10 +1821,11 @@ static int lxc_spawn(struct lxc_handler *handler)
ret = lxc_netns_set_nsid(handler->nsfd[LXC_NS_NET]); ret = lxc_netns_set_nsid(handler->nsfd[LXC_NS_NET]);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to allocate new network namespace id: %d", ret); errno = -ret;
goto out_delete_net; SYSERROR("Failed to allocate new network namespace id");
} else {
TRACE("Allocated new network namespace id");
} }
TRACE("Allocated new network namespace id");
} }
/* Create the network configuration. */ /* Create the network configuration. */