]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: care about unsafe chars in cache
authorKarel Zak <kzak@redhat.com>
Thu, 27 Nov 2014 12:39:35 +0000 (13:39 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 27 Nov 2014 12:39:35 +0000 (13:39 +0100)
The high-level libblkid API uses /run/blkid/blkid.tab cache to
store probing results. The cache format is

   <device NAME="value" ...>devname</device>

and unfortunately the cache code does not escape quotation marks:

   # mkfs.ext4 -L 'AAA"BBB'

   # cat /run/blkid/blkid.tab
   ...
   <device ... LABEL="AAA"BBB" ...>/dev/sdb1</device>

such string is later incorrectly parsed and blkid(8) returns
nonsenses. And for use-cases like

   # eval $(blkid -o export /dev/sdb1)

it's also insecure.

Note that mount, udevd and blkid -p are based on low-level libblkid
API, it bypass the cache and directly read data from the devices.

The current udevd upstream does not depend on blkid(8) output at all,
it's directly linked with the library and all unsafe chars are encoded by
\x<hex> notation.

   # mkfs.ext4 -L 'X"`/tmp/foo` "' /dev/sdb1
   # udevadm info --export-db | grep LABEL
   ...
   E: ID_FS_LABEL=X__/tmp/foo___
   E: ID_FS_LABEL_ENC=X\x22\x60\x2ftmp\x2ffoo\x60\x20\x22

Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/src/read.c
libblkid/src/save.c
misc-utils/blkid.8
misc-utils/blkid.c

index 0e91c9c22e99bd6bacb29c845bbaadcedc1ffabf..81ab0dfd67679505cee3f9e1fa37a2be5cb30338 100644 (file)
@@ -252,15 +252,30 @@ static int parse_token(char **name, char **value, char **cp)
        *value = skip_over_blank(*value + 1);
 
        if (**value == '"') {
-               end = strchr(*value + 1, '"');
-               if (!end) {
+               char *p = end = *value + 1;
+
+               /* convert 'foo\"bar'  to 'foo"bar' */
+               while (*p) {
+                       if (*p == '\\') {
+                               p++;
+                               *end = *p;
+                       } else {
+                               *end = *p;
+                               if (*p == '"')
+                                       break;
+                       }
+                       p++;
+                       end++;
+               }
+
+               if (*end != '"') {
                        DBG(READ, ul_debug("unbalanced quotes at: %s", *value));
                        *cp = *value;
                        return -BLKID_ERR_CACHE;
                }
                (*value)++;
                *end = '\0';
-               end++;
+               end = ++p;
        } else {
                end = skip_over_word(*value);
                if (*end) {
index 8216f0917e3e625efe262cebaa9fd6279d279089..5e8bbee8f96c475e0c9a330cb22e73820a1aabac 100644 (file)
 
 #include "blkidP.h"
 
+
+static void save_quoted(const char *data, FILE *file)
+{
+       const char *p;
+
+       fputc('"', file);
+       for (p = data; p && *p; p++) {
+               if ((unsigned char) *p == 0x22 ||               /* " */
+                   (unsigned char) *p == 0x5c)                 /* \ */
+                       fputc('\\', file);
+
+               fputc(*p, file);
+       }
+       fputc('"', file);
+}
 static int save_dev(blkid_dev dev, FILE *file)
 {
        struct list_head *p;
@@ -43,9 +58,14 @@ static int save_dev(blkid_dev dev, FILE *file)
 
        if (dev->bid_pri)
                fprintf(file, " PRI=\"%d\"", dev->bid_pri);
+
        list_for_each(p, &dev->bid_tags) {
                blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
-               fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
+
+               fputc(' ', file);                       /* space between tags */
+               fputs(tag->bit_name, file);             /* tag NAME */
+               fputc('=', file);                       /* separator between NAME and VALUE */
+               save_quoted(tag->bit_val, file);        /* tag "VALUE" */
        }
        fprintf(file, ">%s</device>\n", dev->bid_name);
 
index 156a14b6ac69c2a754d3c92baa68a9657f2b6960..c95b833dfc410aaf6b4b69e27d12508b533cc180 100644 (file)
@@ -200,7 +200,10 @@ partitions.  This output format is \fBDEPRECATED\fR.
 .TP
 .B export
 print key=value pairs for easy import into the environment; this output format
-is automatically enabled when I/O Limits (\fB-i\fR option) are requested
+is automatically enabled when I/O Limits (\fB-i\fR option) are requested.
+
+The non-printing characters are encoded by ^ and M- notation and all
+potentially unsafe characters are escaped.
 .RE
 .TP
 .BI \-O " offset"
index a6ca660c6573c7fb6471b2cd16b3e6efc3a1edfa..1bd86465676013031fce7d9fcb5794c394f3210d 100644 (file)
@@ -306,7 +306,7 @@ static void print_value(int output, int num, const char *devname,
                        printf("DEVNAME=%s\n", devname);
                fputs(name, stdout);
                fputs("=", stdout);
-               safe_print(value, valsz, NULL);
+               safe_print(value, valsz, " \\\"'$`<>");
                fputs("\n", stdout);
 
        } else {
@@ -315,7 +315,7 @@ static void print_value(int output, int num, const char *devname,
                fputs(" ", stdout);
                fputs(name, stdout);
                fputs("=\"", stdout);
-               safe_print(value, valsz, "\"");
+               safe_print(value, valsz, "\"\\");
                fputs("\"", stdout);
        }
 }