Index: g_linux_lvm.c =================================================================== --- g_linux_lvm.c (revision 194598) +++ g_linux_lvm.c (working copy) @@ -826,14 +826,6 @@ return (0); } -#define GRAB_NAME(tok, name, len) \ - len = 0; \ - while (tok[len] && (isalpha(tok[len]) || isdigit(tok[len])) && \ - len < G_LLVM_NAMELEN - 1) \ - len++; \ - bcopy(tok, name, len); \ - name[len] = '\0'; - #define GRAB_INT(key, tok1, tok2, v) \ if (tok1 && tok2 && strncmp(tok1, key, sizeof(key)) == 0) { \ v = strtol(tok2, &tok1, 10); \ @@ -865,6 +857,25 @@ } static int +llvm_validate_name(const char *name, int len) +{ + int i; + + if (name == NULL || len == 0) + return (0); + if (name[0] == '-') + return (0); + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + return (0); + for (i = 0; i < len; i++) { + if (!isalnum(name[i]) || name[i] != '.' || name[i] != '_' || + name[i] != '-' || name[i] != '+') + return (0); + } + return (1); +} + +static int llvm_textconf_decode(u_char *data, int buflen, struct g_llvm_metadata *md) { struct g_llvm_vg *vg; @@ -872,7 +883,7 @@ char *tok, *v; char name[G_LLVM_NAMELEN]; char uuid[G_LLVM_UUIDLEN]; - int len; + size_t len; if (buf == NULL || *buf == '\0') return (EINVAL); @@ -880,9 +891,11 @@ tok = strsep(&buf, "\n"); if (tok == NULL) return (EINVAL); - GRAB_NAME(tok, name, len); + len = strlcpy(name, tok, sizeof(name)); if (len == 0) return (EINVAL); + if (llvm_validate_name(name, len) == 0) + return (EINVAL); /* check too see if the vg has already been loaded off another disk */ LIST_FOREACH(vg, &vg_list, vg_next) { @@ -970,7 +983,7 @@ { struct g_llvm_pv *pv; char *v; - int len; + size_t len; if (*buf == NULL || **buf == '\0') return (EINVAL); @@ -983,9 +996,11 @@ len = 0; if (tok == NULL) goto bad; - GRAB_NAME(tok, pv->pv_name, len); + len = strlcpy(pv->pv_name, tok, sizeof(pv->pv_name)); if (len == 0) goto bad; + if (llvm_validate_name(pv->pv_name, len) == 0) + goto bad; while ((tok = strsep(buf, "\n")) != NULL) { if (strstr(tok, "{")) @@ -1024,7 +1039,7 @@ struct g_llvm_lv *lv; struct g_llvm_segment *sg; char *v; - int len; + size_t len; if (*buf == NULL || **buf == '\0') return (EINVAL); @@ -1036,12 +1051,13 @@ lv->lv_vg = vg; LIST_INIT(&lv->lv_segs); - len = 0; if (tok == NULL) goto bad; - GRAB_NAME(tok, lv->lv_name, len); + len = strlcpy(lv->lv_name, tok, sizeof(lv->lv_name)); if (len == 0) goto bad; + if (llvm_validate_name(lv->lv_name, len) == 0) + goto bad; while ((tok = strsep(buf, "\n")) != NULL) { if (strstr(tok, "{")) { @@ -1162,7 +1178,6 @@ free(sg, M_GLLVM); return (-1); } -#undef GRAB_NAME #undef GRAB_INT #undef GRAB_STR #undef SPLIT