mirror of
git://github.com/lxc/lxc
synced 2025-08-31 01:19:35 +00:00
lxc-user-nic: check db before trying to delete
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
@@ -3234,7 +3234,7 @@ bool lxc_delete_network(struct lxc_handler *handler)
|
||||
if (am_unpriv()) {
|
||||
if (is_ovs_bridge(netdev->link)) {
|
||||
ret = lxc_unpriv_delete_nic(handler->lxcpath,
|
||||
handler->name, "ovs",
|
||||
handler->name,
|
||||
netdev, getpid());
|
||||
if (ret < 0)
|
||||
WARN("Failed to remove port \"%s\" "
|
||||
@@ -5143,12 +5143,11 @@ struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings)
|
||||
return result;
|
||||
}
|
||||
|
||||
int lxc_unpriv_delete_nic(const char *lxcpath, char *lxcname, char *type,
|
||||
int lxc_unpriv_delete_nic(const char *lxcpath, char *lxcname,
|
||||
struct lxc_netdev *netdev, pid_t pid)
|
||||
{
|
||||
pid_t child;
|
||||
int bytes, pipefd[2];
|
||||
char netdev_link[IFNAMSIZ + 1];
|
||||
char buffer[MAX_BUFFER_SIZE] = {0};
|
||||
|
||||
if (netdev->type != LXC_NET_VETH) {
|
||||
@@ -5187,20 +5186,19 @@ int lxc_unpriv_delete_nic(const char *lxcpath, char *lxcname, char *type,
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (netdev->link)
|
||||
strncpy(netdev_link, netdev->link, IFNAMSIZ);
|
||||
else
|
||||
strncpy(netdev_link, "none", IFNAMSIZ);
|
||||
if (!netdev->link)
|
||||
SYSERROR("Network link for network device \"%s\" is "
|
||||
"missing", netdev->priv.veth_attr.pair);
|
||||
|
||||
ret = snprintf(pidstr, LXC_NUMSTRLEN64, "%d", pid);
|
||||
if (ret < 0 || ret >= LXC_NUMSTRLEN64)
|
||||
exit(EXIT_FAILURE);
|
||||
pidstr[LXC_NUMSTRLEN64 - 1] = '\0';
|
||||
|
||||
INFO("Execing lxc-user-nic delete %s %s %s ovs %s %s", lxcpath,
|
||||
lxcname, pidstr, netdev_link, netdev->priv.veth_attr.pair);
|
||||
INFO("Execing lxc-user-nic delete %s %s %s veth %s %s", lxcpath,
|
||||
lxcname, pidstr, netdev->link, netdev->priv.veth_attr.pair);
|
||||
execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "delete", lxcpath,
|
||||
lxcname, pidstr, "ovs", netdev_link,
|
||||
lxcname, pidstr, "veth", netdev->link,
|
||||
netdev->priv.veth_attr.pair, (char *)NULL);
|
||||
SYSERROR("Failed to exec lxc-user-nic.");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@@ -500,7 +500,7 @@ extern FILE *make_anonymous_mount_file(struct lxc_list *mount);
|
||||
extern struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings);
|
||||
extern unsigned long add_required_remount_flags(const char *s, const char *d,
|
||||
unsigned long flags);
|
||||
extern int lxc_unpriv_delete_nic(const char *lxcpath, char *lxcname, char *type,
|
||||
extern int lxc_unpriv_delete_nic(const char *lxcpath, char *lxcname,
|
||||
struct lxc_netdev *netdev, pid_t pid);
|
||||
|
||||
#endif /* __LXC_CONF_H */
|
||||
|
@@ -572,19 +572,22 @@ struct entry_line {
|
||||
bool keep;
|
||||
};
|
||||
|
||||
static bool cull_entries(int fd, char *me, char *t, char *br)
|
||||
static bool cull_entries(int fd, char *me, char *t, char *br, char *nicname,
|
||||
bool *found_nicname)
|
||||
{
|
||||
int i, n = 0;
|
||||
int i, ret;
|
||||
off_t len;
|
||||
char *buf, *p, *e, *nic;
|
||||
char *buf, *e, *nic, *p;
|
||||
struct stat sb;
|
||||
int n = 0;
|
||||
struct entry_line *entry_lines = NULL;
|
||||
|
||||
nic = alloca(100);
|
||||
if (!nic)
|
||||
return false;
|
||||
|
||||
if (fstat(fd, &sb) < 0) {
|
||||
ret = fstat(fd, &sb);
|
||||
if (ret < 0) {
|
||||
usernic_error("Failed to fstat: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@@ -593,7 +596,7 @@ static bool cull_entries(int fd, char *me, char *t, char *br)
|
||||
if (len == 0)
|
||||
return true;
|
||||
|
||||
buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
buf = lxc_strmmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (buf == MAP_FAILED) {
|
||||
usernic_error("Failed to establish shared memory mapping: %s\n",
|
||||
strerror(errno));
|
||||
@@ -622,6 +625,10 @@ static bool cull_entries(int fd, char *me, char *t, char *br)
|
||||
if (nic && !nic_exists(nic))
|
||||
entry_lines[n - 1].keep = false;
|
||||
|
||||
if (nicname)
|
||||
if (!strcmp(nic, nicname))
|
||||
*found_nicname = true;
|
||||
|
||||
p += entry_lines[n - 1].len + 1;
|
||||
if (p >= e)
|
||||
break;
|
||||
@@ -639,8 +646,9 @@ static bool cull_entries(int fd, char *me, char *t, char *br)
|
||||
}
|
||||
free(entry_lines);
|
||||
|
||||
munmap(buf, sb.st_size);
|
||||
if (ftruncate(fd, p - buf))
|
||||
lxc_strmunmap(buf, sb.st_size);
|
||||
ret = ftruncate(fd, p - buf);
|
||||
if (ret < 0)
|
||||
usernic_error("Failed to set new file size: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
@@ -676,7 +684,7 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
|
||||
char *buf = NULL;
|
||||
|
||||
for (n = names; n != NULL; n = n->next)
|
||||
cull_entries(fd, n->name, intype, br);
|
||||
cull_entries(fd, n->name, intype, br, NULL, NULL);
|
||||
|
||||
if (allowed == 0)
|
||||
return NULL;
|
||||
@@ -965,9 +973,12 @@ struct user_nic_args {
|
||||
char *veth_name;
|
||||
};
|
||||
|
||||
#define LXC_USERNIC_CREATE 0
|
||||
#define LXC_USERNIC_DELETE 1
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd, ifindex, n, pid, ret;
|
||||
int fd, ifindex, n, pid, request, ret;
|
||||
char *me, *newname;
|
||||
char *cnic = NULL, *nicname = NULL;
|
||||
struct alloted_s *alloted = NULL;
|
||||
@@ -988,6 +999,15 @@ int main(int argc, char *argv[])
|
||||
if (argc >= 8)
|
||||
args.veth_name = argv[7];
|
||||
|
||||
if (!strcmp(args.cmd, "create")) {
|
||||
request = LXC_USERNIC_CREATE;
|
||||
} else if (!strcmp(args.cmd, "delete")) {
|
||||
request = LXC_USERNIC_DELETE;
|
||||
} else {
|
||||
usage(argv[0], true);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Set a sane env, because we are setuid-root. */
|
||||
ret = clearenv();
|
||||
if (ret) {
|
||||
@@ -1029,12 +1049,36 @@ int main(int argc, char *argv[])
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!strcmp(args.cmd, "delete")) {
|
||||
close(fd);
|
||||
n = get_alloted(me, args.type, args.link, &alloted);
|
||||
|
||||
if (strcmp(args.type, "ovs")) {
|
||||
if (request == LXC_USERNIC_DELETE) {
|
||||
int ret;
|
||||
struct alloted_s *it;
|
||||
bool found_nicname = false;
|
||||
|
||||
if (!is_ovs_bridge(args.link)) {
|
||||
usernic_error("%s", "Deletion of non ovs type network "
|
||||
"devics not implemented\n");
|
||||
"devices not implemented\n");
|
||||
close(fd);
|
||||
free_alloted(&alloted);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Check whether the network device we are supposed to delete
|
||||
* exists in the db. If it doesn't we will not delete it as we
|
||||
* need to assume the network device is not under our control.
|
||||
* As a side effect we also clear any invalid entries from the
|
||||
* database.
|
||||
*/
|
||||
for (it = alloted; it; it = it->next)
|
||||
cull_entries(fd, it->name, args.type, args.link,
|
||||
args.veth_name, &found_nicname);
|
||||
close(fd);
|
||||
free_alloted(&alloted);
|
||||
|
||||
if (!found_nicname) {
|
||||
usernic_error("%s", "Caller is not allowed to delete "
|
||||
"network device\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -1045,10 +1089,9 @@ int main(int argc, char *argv[])
|
||||
args.veth_name, args.link);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
n = get_alloted(me, args.type, args.link, &alloted);
|
||||
if (n > 0)
|
||||
nicname = get_nic_if_avail(fd, alloted, pid, args.type,
|
||||
args.link, n, &cnic);
|
||||
|
Reference in New Issue
Block a user