summaryrefslogtreecommitdiffstats
path: root/sys/dev/nmdm
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2014-09-10 05:44:15 +0000
committergrehan <grehan@FreeBSD.org>2014-09-10 05:44:15 +0000
commitf30a88f9b17b9fd38bb1ff60cad41cac5ddd6ee6 (patch)
treef62f1337b5017f15464461573953901763dc4570 /sys/dev/nmdm
parentcbe58136b8e340b2c06f79bac588ba077f59fa3c (diff)
downloadFreeBSD-src-f30a88f9b17b9fd38bb1ff60cad41cac5ddd6ee6.zip
FreeBSD-src-f30a88f9b17b9fd38bb1ff60cad41cac5ddd6ee6.tar.gz
Fix issue with nmdm and leading zeros in device name.
The nmdm code enforces a number between the 'nmdm' and 'A|B' portions of the device name. This is then used as a unit number, and sprintf'd back into the tty name. If leading zeros were used in the name, the created device name is different than the string used for the clone-open (e.g. /dev/nmdm0001A will result in /dev/nmdm1A). Since unit numbers are no longer required with the updated tty code, there seems to be no reason to force the string to be a number. The fix is to allow an arbitrary string between 'nmdm' and 'A|B', within the constraints of devfs names. This allows all existing user of numeric strings to continue to work, and also allows more meaningful names to be used, such as bhyve VM names. Tested on amd64, i386 and ppc64. Reported by: Dave Smith PR: 192281 Reviewed by: neel, glebius Phabric: D729 MFC after: 3 days
Diffstat (limited to 'sys/dev/nmdm')
-rw-r--r--sys/dev/nmdm/nmdm.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/sys/dev/nmdm/nmdm.c b/sys/dev/nmdm/nmdm.c
index 04a0b16..dbe24cb 100644
--- a/sys/dev/nmdm/nmdm.c
+++ b/sys/dev/nmdm/nmdm.c
@@ -157,21 +157,21 @@ nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen,
{
struct nmdmsoftc *ns;
struct tty *tp;
- unsigned long unit;
char *end;
int error;
+ char endc;
if (*dev != NULL)
return;
if (strncmp(name, "nmdm", 4) != 0)
return;
-
- /* Device name must be "nmdm%lu%c", where %c is 'A' or 'B'. */
- name += 4;
- unit = strtoul(name, &end, 10);
- if (unit == ULONG_MAX || name == end)
+ if (strlen(name) <= strlen("nmdmX"))
return;
- if ((end[0] != 'A' && end[0] != 'B') || end[1] != '\0')
+
+ /* Device name must be "nmdm%s%c", where %c is 'A' or 'B'. */
+ end = name + strlen(name) - 1;
+ endc = *end;
+ if (endc != 'A' && endc != 'B')
return;
ns = malloc(sizeof(*ns), M_NMDM, M_WAITOK | M_ZERO);
@@ -191,9 +191,11 @@ nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen,
/* Create device nodes. */
tp = ns->ns_part1.np_tty = tty_alloc_mutex(&nmdm_class, &ns->ns_part1,
&ns->ns_mtx);
- error = tty_makedevf(tp, NULL, end[0] == 'A' ? TTYMK_CLONING : 0,
- "nmdm%luA", unit);
+ *end = 'A';
+ error = tty_makedevf(tp, NULL, endc == 'A' ? TTYMK_CLONING : 0,
+ "%s", name);
if (error) {
+ *end = endc;
mtx_destroy(&ns->ns_mtx);
free(ns, M_NMDM);
return;
@@ -201,9 +203,11 @@ nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen,
tp = ns->ns_part2.np_tty = tty_alloc_mutex(&nmdm_class, &ns->ns_part2,
&ns->ns_mtx);
- error = tty_makedevf(tp, NULL, end[0] == 'B' ? TTYMK_CLONING : 0,
- "nmdm%luB", unit);
+ *end = 'B';
+ error = tty_makedevf(tp, NULL, endc == 'B' ? TTYMK_CLONING : 0,
+ "%s", name);
if (error) {
+ *end = endc;
mtx_lock(&ns->ns_mtx);
/* see nmdm_free() */
ns->ns_part1.np_other = NULL;
@@ -212,11 +216,12 @@ nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen,
return;
}
- if (end[0] == 'A')
+ if (endc == 'A')
*dev = ns->ns_part1.np_tty->t_dev;
else
*dev = ns->ns_part2.np_tty->t_dev;
+ *end = endc;
atomic_add_int(&nmdm_count, 1);
}
OpenPOWER on IntegriCloud