Skip to content

Commit def20c9

Browse files
committed
Fixing kernel commandline parameter validation
According to linux kernel document, the value of command line parameter can contains spaces (with double quotes) or equals. Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
1 parent ef542d4 commit def20c9

File tree

1 file changed

+41
-9
lines changed

1 file changed

+41
-9
lines changed

src/cmdline/mod.rs

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub enum Error {
3737
MmioSize,
3838
/// Operation would have made the command line too large.
3939
TooLarge,
40+
/// Double-quotes can be used to protect spaces in values
41+
NoQuoteSpace,
4042
}
4143

4244
impl fmt::Display for Error {
@@ -56,6 +58,10 @@ impl fmt::Display for Error {
5658
"0-sized virtio MMIO device passed to the kernel command line builder."
5759
),
5860
Error::TooLarge => write!(f, "Inserting string would make command line too long."),
61+
Error::NoQuoteSpace => write!(
62+
f,
63+
"Value that contains spaces need to be surrounded by quotes"
64+
),
5965
}
6066
}
6167
}
@@ -79,7 +85,16 @@ fn valid_str(s: &str) -> Result<()> {
7985
}
8086
}
8187

82-
fn valid_element(s: &str) -> Result<()> {
88+
fn is_quoted(s: &str) -> bool {
89+
if let Some(first_char) = s.chars().next() {
90+
if let Some(last_char) = s.chars().last() {
91+
return first_char == '"' && last_char == '"';
92+
}
93+
}
94+
false
95+
}
96+
97+
fn valid_key(s: &str) -> Result<()> {
8398
if !s.chars().all(valid_char) {
8499
Err(Error::InvalidAscii)
85100
} else if s.contains(' ') {
@@ -91,6 +106,16 @@ fn valid_element(s: &str) -> Result<()> {
91106
}
92107
}
93108

109+
fn valid_value(s: &str) -> Result<()> {
110+
if !s.chars().all(valid_char) {
111+
Err(Error::InvalidAscii)
112+
} else if s.contains(' ') && !is_quoted(s) {
113+
Err(Error::NoQuoteSpace)
114+
} else {
115+
Ok(())
116+
}
117+
}
118+
94119
/// A builder for a kernel command line string that validates the string as it's being built.
95120
///
96121
/// # Examples
@@ -155,8 +180,8 @@ impl Cmdline {
155180
let k = key.as_ref();
156181
let v = val.as_ref();
157182

158-
valid_element(k)?;
159-
valid_element(v)?;
183+
valid_key(k)?;
184+
valid_value(v)?;
160185

161186
let kv_str = format!("{}={}", k, v);
162187

@@ -186,7 +211,7 @@ impl Cmdline {
186211
pub fn insert_multiple<T: AsRef<str>>(&mut self, key: T, vals: &[T]) -> Result<()> {
187212
let k = key.as_ref();
188213

189-
valid_element(k)?;
214+
valid_key(k)?;
190215
if vals.is_empty() {
191216
return Err(Error::MissingVal(k.to_string()));
192217
}
@@ -196,7 +221,7 @@ impl Cmdline {
196221
k,
197222
vals.iter()
198223
.map(|v| -> Result<&str> {
199-
valid_element(v.as_ref())?;
224+
valid_value(v.as_ref())?;
200225
Ok(v.as_ref())
201226
})
202227
.collect::<Result<Vec<&str>>>()?
@@ -565,20 +590,24 @@ mod tests {
565590
fn test_insert_space() {
566591
let mut cl = Cmdline::new(100).unwrap();
567592
assert_eq!(cl.insert("a ", "b"), Err(Error::HasSpace));
568-
assert_eq!(cl.insert("a", "b "), Err(Error::HasSpace));
593+
assert_eq!(cl.insert("a", "b "), Err(Error::NoQuoteSpace));
569594
assert_eq!(cl.insert("a ", "b "), Err(Error::HasSpace));
570595
assert_eq!(cl.insert(" a", "b"), Err(Error::HasSpace));
571596
assert_eq!(cl.as_cstring().unwrap().as_bytes_with_nul(), b"\0");
597+
assert!(cl.insert("a", "\"b b\"").is_ok());
598+
assert!(cl.insert("c", "\" d\"").is_ok());
599+
assert_eq!(
600+
cl.as_cstring().unwrap().as_bytes_with_nul(),
601+
b"a=\"b b\" c=\" d\"\0"
602+
);
572603
}
573604

574605
#[test]
575606
fn test_insert_equals() {
576607
let mut cl = Cmdline::new(100).unwrap();
577608
assert_eq!(cl.insert("a=", "b"), Err(Error::HasEquals));
578-
assert_eq!(cl.insert("a", "b="), Err(Error::HasEquals));
579609
assert_eq!(cl.insert("a=", "b "), Err(Error::HasEquals));
580610
assert_eq!(cl.insert("=a", "b"), Err(Error::HasEquals));
581-
assert_eq!(cl.insert("a", "=b"), Err(Error::HasEquals));
582611
assert_eq!(cl.as_cstring().unwrap().as_bytes_with_nul(), b"\0");
583612
}
584613

@@ -700,7 +729,10 @@ mod tests {
700729
cl.insert_multiple("foo", &no_vals),
701730
Err(Error::MissingVal("foo".to_string()))
702731
);
703-
assert_eq!(cl.insert_multiple("foo", &["bar "]), Err(Error::HasSpace));
732+
assert_eq!(
733+
cl.insert_multiple("foo", &["bar "]),
734+
Err(Error::NoQuoteSpace)
735+
);
704736
assert_eq!(
705737
cl.insert_multiple("foo", &["bar", "baz"]),
706738
Err(Error::TooLarge)

0 commit comments

Comments
 (0)