2
0
mirror of git://github.com/lxc/lxc synced 2025-09-02 09:49:32 +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:
Christian Brauner
2017-08-27 09:17:10 +02:00
parent af25697056
commit 8b8e00a24d
3 changed files with 67 additions and 26 deletions

View File

@@ -3234,7 +3234,7 @@ bool lxc_delete_network(struct lxc_handler *handler)
if (am_unpriv()) { if (am_unpriv()) {
if (is_ovs_bridge(netdev->link)) { if (is_ovs_bridge(netdev->link)) {
ret = lxc_unpriv_delete_nic(handler->lxcpath, ret = lxc_unpriv_delete_nic(handler->lxcpath,
handler->name, "ovs", handler->name,
netdev, getpid()); netdev, getpid());
if (ret < 0) if (ret < 0)
WARN("Failed to remove port \"%s\" " WARN("Failed to remove port \"%s\" "
@@ -5143,12 +5143,11 @@ struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings)
return result; 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) struct lxc_netdev *netdev, pid_t pid)
{ {
pid_t child; pid_t child;
int bytes, pipefd[2]; int bytes, pipefd[2];
char netdev_link[IFNAMSIZ + 1];
char buffer[MAX_BUFFER_SIZE] = {0}; char buffer[MAX_BUFFER_SIZE] = {0};
if (netdev->type != LXC_NET_VETH) { 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); exit(EXIT_FAILURE);
} }
if (netdev->link) if (!netdev->link)
strncpy(netdev_link, netdev->link, IFNAMSIZ); SYSERROR("Network link for network device \"%s\" is "
else "missing", netdev->priv.veth_attr.pair);
strncpy(netdev_link, "none", IFNAMSIZ);
ret = snprintf(pidstr, LXC_NUMSTRLEN64, "%d", pid); ret = snprintf(pidstr, LXC_NUMSTRLEN64, "%d", pid);
if (ret < 0 || ret >= LXC_NUMSTRLEN64) if (ret < 0 || ret >= LXC_NUMSTRLEN64)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
pidstr[LXC_NUMSTRLEN64 - 1] = '\0'; pidstr[LXC_NUMSTRLEN64 - 1] = '\0';
INFO("Execing lxc-user-nic delete %s %s %s ovs %s %s", lxcpath, INFO("Execing lxc-user-nic delete %s %s %s veth %s %s", lxcpath,
lxcname, pidstr, netdev_link, netdev->priv.veth_attr.pair); lxcname, pidstr, netdev->link, netdev->priv.veth_attr.pair);
execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, "delete", lxcpath, 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); netdev->priv.veth_attr.pair, (char *)NULL);
SYSERROR("Failed to exec lxc-user-nic."); SYSERROR("Failed to exec lxc-user-nic.");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@@ -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 struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings);
extern unsigned long add_required_remount_flags(const char *s, const char *d, extern unsigned long add_required_remount_flags(const char *s, const char *d,
unsigned long flags); 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); struct lxc_netdev *netdev, pid_t pid);
#endif /* __LXC_CONF_H */ #endif /* __LXC_CONF_H */

View File

@@ -572,19 +572,22 @@ struct entry_line {
bool keep; 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; off_t len;
char *buf, *p, *e, *nic; char *buf, *e, *nic, *p;
struct stat sb; struct stat sb;
int n = 0;
struct entry_line *entry_lines = NULL; struct entry_line *entry_lines = NULL;
nic = alloca(100); nic = alloca(100);
if (!nic) if (!nic)
return false; return false;
if (fstat(fd, &sb) < 0) { ret = fstat(fd, &sb);
if (ret < 0) {
usernic_error("Failed to fstat: %s\n", strerror(errno)); usernic_error("Failed to fstat: %s\n", strerror(errno));
return false; return false;
} }
@@ -593,7 +596,7 @@ static bool cull_entries(int fd, char *me, char *t, char *br)
if (len == 0) if (len == 0)
return true; 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) { if (buf == MAP_FAILED) {
usernic_error("Failed to establish shared memory mapping: %s\n", usernic_error("Failed to establish shared memory mapping: %s\n",
strerror(errno)); strerror(errno));
@@ -622,6 +625,10 @@ static bool cull_entries(int fd, char *me, char *t, char *br)
if (nic && !nic_exists(nic)) if (nic && !nic_exists(nic))
entry_lines[n - 1].keep = false; entry_lines[n - 1].keep = false;
if (nicname)
if (!strcmp(nic, nicname))
*found_nicname = true;
p += entry_lines[n - 1].len + 1; p += entry_lines[n - 1].len + 1;
if (p >= e) if (p >= e)
break; break;
@@ -639,8 +646,9 @@ static bool cull_entries(int fd, char *me, char *t, char *br)
} }
free(entry_lines); free(entry_lines);
munmap(buf, sb.st_size); lxc_strmunmap(buf, sb.st_size);
if (ftruncate(fd, p - buf)) ret = ftruncate(fd, p - buf);
if (ret < 0)
usernic_error("Failed to set new file size: %s\n", usernic_error("Failed to set new file size: %s\n",
strerror(errno)); strerror(errno));
@@ -676,7 +684,7 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
char *buf = NULL; char *buf = NULL;
for (n = names; n != NULL; n = n->next) 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) if (allowed == 0)
return NULL; return NULL;
@@ -965,9 +973,12 @@ struct user_nic_args {
char *veth_name; char *veth_name;
}; };
#define LXC_USERNIC_CREATE 0
#define LXC_USERNIC_DELETE 1
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int fd, ifindex, n, pid, ret; int fd, ifindex, n, pid, request, ret;
char *me, *newname; char *me, *newname;
char *cnic = NULL, *nicname = NULL; char *cnic = NULL, *nicname = NULL;
struct alloted_s *alloted = NULL; struct alloted_s *alloted = NULL;
@@ -988,6 +999,15 @@ int main(int argc, char *argv[])
if (argc >= 8) if (argc >= 8)
args.veth_name = argv[7]; 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. */ /* Set a sane env, because we are setuid-root. */
ret = clearenv(); ret = clearenv();
if (ret) { if (ret) {
@@ -1029,12 +1049,36 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!strcmp(args.cmd, "delete")) { n = get_alloted(me, args.type, args.link, &alloted);
close(fd);
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 " 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); exit(EXIT_FAILURE);
} }
@@ -1045,10 +1089,9 @@ int main(int argc, char *argv[])
args.veth_name, args.link); args.veth_name, args.link);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
n = get_alloted(me, args.type, args.link, &alloted);
if (n > 0) if (n > 0)
nicname = get_nic_if_avail(fd, alloted, pid, args.type, nicname = get_nic_if_avail(fd, alloted, pid, args.type,
args.link, n, &cnic); args.link, n, &cnic);