From: Christian Brauner Date: Sun, 3 Sep 2017 14:40:11 +0000 (+0200) Subject: lxc-user-nic: bugfixes X-Git-Tag: lxc-2.0.9~48^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3bc79785a893c5616bd9691fc049b1dc693f61e6;p=thirdparty%2Flxc.git lxc-user-nic: bugfixes Since find_line() was changed before count_entries() started counting lines wrong. It would report maximum reached before you actually reached your alloted maximum. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/lxc_user_nic.c index a2ad03080..6920c5462 100644 --- a/src/lxc/lxc_user_nic.c +++ b/src/lxc/lxc_user_nic.c @@ -357,41 +357,94 @@ static char *get_eow(char *s, char *e) return s; } -static char *find_line(char *p, char *e, char *u, char *t, char *l) +static char *find_line(char *buf_start, char *buf_end, char *name, + char *net_type, char *net_link, char *net_dev, + bool *owner, bool *found, bool *keep) { - char *p1, *p2, *ret; + char *end_of_line, *end_of_word, *line; - while ((p < e) && (p1 = get_eol(p, e)) < e) { - ret = p; - if (*p == '#') + while (buf_start < buf_end) { + size_t len; + char netdev_name[IFNAMSIZ]; + + *found = false; + *keep = true; + *owner = false; + + end_of_line = get_eol(buf_start, buf_end); + if (end_of_line >= buf_end) + return NULL; + + line = buf_start; + if (*buf_start == '#') goto next; - while ((p < e) && isblank(*p)) - p++; + while ((buf_start < buf_end) && isblank(*buf_start)) + buf_start++; + + /* Check whether the line contains the caller's name. */ + end_of_word = get_eow(buf_start, buf_end); + /* corrupt db */ + if (!end_of_word) + return NULL; + + if (strncmp(buf_start, name, strlen(name))) + *found = false; + + *owner = true; + + buf_start = end_of_word + 1; + while ((buf_start < buf_end) && isblank(*buf_start)) + buf_start++; + + /* Check whether line is of the right network type. */ + end_of_word = get_eow(buf_start, buf_end); + /* corrupt db */ + if (!end_of_word) + return NULL; + + if (strncmp(buf_start, net_type, strlen(net_type))) + *found = false; + + buf_start = end_of_word + 1; + while ((buf_start < buf_end) && isblank(*buf_start)) + buf_start++; + + /* Check whether line is contains the right link. */ + end_of_word = get_eow(buf_start, buf_end); + /* corrupt db */ + if (!end_of_word) + return NULL; - p2 = get_eow(p, e); - if (!p2 || ((size_t)(p2 - p)) != strlen(u) || strncmp(p, u, strlen(u))) - return ret; + if (strncmp(buf_start, net_link, strlen(net_link))) + *found = false; - p = p2 + 1; - while ((p < e) && isblank(*p)) - p++; + buf_start = end_of_word + 1; + while ((buf_start < buf_end) && isblank(*buf_start)) + buf_start++; - p2 = get_eow(p, e); - if (!p2 || ((size_t)(p2 - p)) != strlen(t) || strncmp(p, t, strlen(t))) - return ret; + /* Check whether line contains the right network device. */ + end_of_word = get_eow(buf_start, buf_end); + /* corrupt db */ + if (!end_of_word) + return NULL; + + len = end_of_word - buf_start; + /* corrupt db */ + if (len >= IFNAMSIZ) + return NULL; - p = p2 + 1; - while ((p < e) && isblank(*p)) - p++; + memcpy(netdev_name, buf_start, len); + netdev_name[len] = '\0'; + *keep = lxc_nic_exists(netdev_name); - p2 = get_eow(p, e); - if (!p2 || ((size_t)(p2 - p)) != strlen(l) || strncmp(p, l, strlen(l))) - return ret; + if (net_dev && !strcmp(netdev_name, net_dev)) + *found = true; + + return line; - return ret; next: - p = p1 + 1; + buf_start = end_of_line + 1; } return NULL; @@ -532,50 +585,30 @@ static char *get_new_nicname(char *br, int pid, char **cnic) return nicname; } -static bool get_nic_from_line(char *p, char **nic) -{ - int ret; - char user[100], type[100], br[100]; - - ret = sscanf(p, "%99[^ \t\n] %99[^ \t\n] %99[^ \t\n] %99[^ \t\n]", user, - type, br, *nic); - if (ret != 4) { - *nic[0] = '\0'; - return false; - } - - return true; -} - struct entry_line { char *start; int len; bool keep; }; -static bool cull_entries(int fd, char *me, char *t, char *br, char *nicname, - bool *found_nicname) +static bool cull_entries(int fd, char *name, char *net_type, char *net_link, + char *net_dev, bool *found_nicname) { int i, ret; - off_t len; - char *buf, *e, *nic, *p; + char *buf, *buf_end, *buf_start; struct stat sb; int n = 0; + bool found, keep; struct entry_line *entry_lines = NULL; - nic = alloca(100); - if (!nic) - return false; - ret = fstat(fd, &sb); if (ret < 0) { usernic_error("Failed to fstat: %s\n", strerror(errno)); return false; } - len = sb.st_size; - if (len == 0) - return true; + if (!sb.st_size) + return false; buf = lxc_strmmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { @@ -584,55 +617,48 @@ static bool cull_entries(int fd, char *me, char *t, char *br, char *nicname, return false; } - p = buf; - e = buf + len; - while ((p = find_line(p, e, me, t, br))) { + buf_start = buf; + buf_end = buf + sb.st_size; + while ((buf_start = find_line(buf_start, buf_end, name, net_type, + net_link, net_dev, &(bool){true}, &found, + &keep))) { struct entry_line *newe; - bool exists = false; newe = realloc(entry_lines, sizeof(*entry_lines) * (n + 1)); if (!newe) { free(entry_lines); + lxc_strmunmap(buf, sb.st_size); return false; } + if (found) + *found_nicname = true; + entry_lines = newe; - entry_lines[n].start = p; - entry_lines[n].len = get_eol(p, e) - entry_lines[n].start; - entry_lines[n].keep = true; + entry_lines[n].start = buf_start; + entry_lines[n].len = get_eol(buf_start, buf_end) - entry_lines[n].start; + entry_lines[n].keep = keep; n++; - if (!get_nic_from_line(p, &nic)) - continue; - - if (nic[0] != '\0') - exists = lxc_nic_exists(nic); - if (!exists) - entry_lines[n - 1].keep = false; - - if (exists && nicname) - if (!strcmp(nic, nicname)) - *found_nicname = true; - - p += entry_lines[n - 1].len + 1; - if (p >= e) + buf_start += entry_lines[n - 1].len + 1; + if (buf_start >= buf_end) break; } - p = buf; + buf_start = buf; for (i = 0; i < n; i++) { if (!entry_lines[i].keep) continue; - memcpy(p, entry_lines[i].start, entry_lines[i].len); - p += entry_lines[i].len; - *p = '\n'; - p++; + memcpy(buf_start, entry_lines[i].start, entry_lines[i].len); + buf_start += entry_lines[i].len; + *buf_start = '\n'; + buf_start++; } free(entry_lines); lxc_strmunmap(buf, sb.st_size); - ret = ftruncate(fd, p - buf); + ret = ftruncate(fd, buf_start - buf); if (ret < 0) usernic_error("Failed to set new file size: %s\n", strerror(errno)); @@ -640,16 +666,19 @@ static bool cull_entries(int fd, char *me, char *t, char *br, char *nicname, return true; } -static int count_entries(char *buf, off_t len, char *me, char *t, char *br) +static int count_entries(char *buf, off_t len, char *name, char *net_type, char *net_link) { - char *e; int count = 0; - - e = &buf[len]; - while ((buf = find_line(buf, e, me, t, br))) { - count++; - buf = get_eol(buf, e) + 1; - if (buf >= e) + bool owner = false;; + char *buf_end = &buf[len]; + + buf_end = &buf[len]; + while ((buf = find_line(buf, buf_end, name, net_type, net_link, NULL, + &owner, &(bool){true}, &(bool){true}))) { + if (owner) + count++; + buf = get_eol(buf, buf_end) + 1; + if (buf >= buf_end) break; }