kern/149762: volume labels with rogue characters
Walter C. Pelissero
walter.pelissero at iesy.net
Wed Aug 18 10:20:09 UTC 2010
>Number: 149762
>Category: kern
>Synopsis: volume labels with rogue characters
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Wed Aug 18 10:20:08 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator: Walter C. Pelissero
>Release: FreeBSD 8.1-STABLE i386
>Organization:
>Environment:
System: FreeBSD zaphod.home.lan 8.1-STABLE FreeBSD 8.1-STABLE #1: Wed Aug 18 10:09:27 CEST 2010 root at zaphod.home.lan:/usr/src/sys/i386/compile/TIGER-MP i386
>Description:
Labels from external volumes may contain characters that make
the label difficult to use for practical purposes. An example
is a MSDOS filesystem with whitespace in its label; an fstab
entry can't be written for this volume as /etc/fstab has a
strict and simple syntax that allows for space only between
fields.
>How-To-Repeat:
Plug a USB dongle with a volume that contains whitespace in
the name, such as "foo bar". Now try to write an entry in
/etc/fstab for it.
>Fix:
Although there have been already several proposals, in the
past decade, to enhance fstab's syntax (see conf/37569,
bin/55539 and bin/117687, conf/149424), this one takes a novel
approach: labels are sanitised before creating the entry in
/dev/, thus removing the requirement for a new syntax in
/etc/fstab
In the following patch, the function sanitise_name (controlled
by kern.geom.label.sanitation sysctl) replaces characters
deemed invalid according to three levels:
0 - replace only '/'s with '#'s
1 - like 0, but also replace whitespace and all the ASCII control
characters (anything below 0x20) with '_'
2 - like 1, but also replace anything above 0x7E with '#'
Note that the replacement of '/'s is done in any case. I
don't know whether that might be redundant or even bad in the
context of the other geom_label stuff. It just made sense,
but I don't have enough familiarity with that code.
===================================================================
RCS file: /repos/src/sys/geom/label/g_label.c,v
retrieving revision 1.24.2.4
diff -c -r1.24.2.4 g_label.c
*** g_label.c 22 Jun 2010 08:17:20 -0000 1.24.2.4
--- g_label.c 18 Aug 2010 09:48:41 -0000
***************
*** 136,141 ****
--- 136,162 ----
return (1);
}
+ static int sanitation_level = 1;
+ SYSCTL_INT(_kern_geom_label, OID_AUTO, sanitation, CTLFLAG_RW,
+ &sanitation_level, 0,
+ "Correction applied to labels: 0 = replace '/'s only, 1 = '/' + whitespace and ctrls, 2 = '/' + anything but ASCII printables");
+
+ static void
+ sanitise_name (char *dst, const char *src)
+ {
+ for (; *src; ++src, ++dst) {
+ if (*src == '/')
+ *dst = '#';
+ else if (sanitation_level > 0 && *src <= ' ')
+ *dst = '_';
+ else if (sanitation_level > 1 && *src > '~')
+ *dst = '#';
+ else
+ *dst = *src;
+ }
+ *dst = '\0';
+ }
+
static struct g_geom *
g_label_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
const char *label, const char *dir, off_t mediasize)
***************
*** 155,161 ****
}
gp = NULL;
cp = NULL;
! snprintf(name, sizeof(name), "%s/%s", dir, label);
LIST_FOREACH(gp, &mp->geom, geom) {
pp2 = LIST_FIRST(&gp->provider);
if (pp2 == NULL)
--- 176,185 ----
}
gp = NULL;
cp = NULL;
! {
! int n = snprintf(name, sizeof(name), "%s/", dir);
! sanitise_name(name + n, label);
! }
LIST_FOREACH(gp, &mp->geom, geom) {
pp2 = LIST_FIRST(&gp->provider);
if (pp2 == NULL)
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list