Package: util-linux / 2.25.2-6

libblkid-care-about-unsafe-chars-in-cache.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
From: Karel Zak <kzak@redhat.com>
Date: Thu, 27 Nov 2014 13:39:35 +0100
Subject: libblkid: care about unsafe chars in cache

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 | 21 ++++++++++++++++++---
 libblkid/src/save.c | 22 +++++++++++++++++++++-
 misc-utils/blkid.8  |  5 ++++-
 misc-utils/blkid.c  |  4 ++--
 4 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/libblkid/src/read.c b/libblkid/src/read.c
index 0e91c9c..81ab0df 100644
--- a/libblkid/src/read.c
+++ b/libblkid/src/read.c
@@ -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) {
diff --git a/libblkid/src/save.c b/libblkid/src/save.c
index 8216f09..5e8bbee 100644
--- a/libblkid/src/save.c
+++ b/libblkid/src/save.c
@@ -26,6 +26,21 @@
 
 #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);
 
diff --git a/misc-utils/blkid.8 b/misc-utils/blkid.8
index a974b8e..7c0e176 100644
--- a/misc-utils/blkid.8
+++ b/misc-utils/blkid.8
@@ -193,7 +193,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"
diff --git a/misc-utils/blkid.c b/misc-utils/blkid.c
index a6ca660..1bd8646 100644
--- a/misc-utils/blkid.c
+++ b/misc-utils/blkid.c
@@ -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);
 	}
 }