mirror of
				https://github.com/kata-containers/kata-containers.git
				synced 2025-10-31 17:37:20 +00:00 
			
		
		
		
	runtime: support kernel params including spaces
Support quoted kernel command line parameters that include space characters. Example: dm-mod.create="dm-verity,,,ro,0 736328 verity 1 /dev/vda1 /dev/vda2 4096 4096 92041 0 sha256 f211b9f1921ef726d57a72bf82be23a510076639fa8549ade10f85e214e0ddb4 065c13dfb5b4e0af034685aa5442bddda47b17c182ee44ba55a373835d18a038" Fixes: #8003 Signed-off-by: Dan Mihai <dmihai@microsoft.com>
This commit is contained in:
		| @@ -720,7 +720,7 @@ func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | ||||
| 		ImagePath:             image, | ||||
| 		RootfsType:            rootfsType, | ||||
| 		FirmwarePath:          firmware, | ||||
| 		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)), | ||||
| 		KernelParams:          vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||
| 		NumVCPUs:              h.defaultVCPUs(), | ||||
| 		DefaultMaxVCPUs:       h.defaultMaxVCPUs(), | ||||
| 		MemorySize:            h.defaultMemSz(), | ||||
| @@ -853,7 +853,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | ||||
| 		PFlash:                  pflashes, | ||||
| 		MachineAccelerators:     machineAccelerators, | ||||
| 		CPUFeatures:             cpuFeatures, | ||||
| 		KernelParams:            vc.DeserializeParams(strings.Fields(kernelParams)), | ||||
| 		KernelParams:            vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||
| 		HypervisorMachineType:   machineType, | ||||
| 		NumVCPUs:                h.defaultVCPUs(), | ||||
| 		DefaultMaxVCPUs:         h.defaultMaxVCPUs(), | ||||
| @@ -965,7 +965,7 @@ func newAcrnHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | ||||
| 		HypervisorCtlPath:     hypervisorctl, | ||||
| 		HypervisorCtlPathList: h.CtlPathList, | ||||
| 		FirmwarePath:          firmware, | ||||
| 		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)), | ||||
| 		KernelParams:          vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||
| 		NumVCPUs:              h.defaultVCPUs(), | ||||
| 		DefaultMaxVCPUs:       h.defaultMaxVCPUs(), | ||||
| 		MemorySize:            h.defaultMemSz(), | ||||
| @@ -1055,7 +1055,7 @@ func newClhHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | ||||
| 		RootfsType:                     rootfsType, | ||||
| 		FirmwarePath:                   firmware, | ||||
| 		MachineAccelerators:            machineAccelerators, | ||||
| 		KernelParams:                   vc.DeserializeParams(strings.Fields(kernelParams)), | ||||
| 		KernelParams:                   vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||
| 		HypervisorMachineType:          machineType, | ||||
| 		NumVCPUs:                       h.defaultVCPUs(), | ||||
| 		DefaultMaxVCPUs:                h.defaultMaxVCPUs(), | ||||
| @@ -1130,7 +1130,7 @@ func newDragonballHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | ||||
| 		KernelPath:      kernel, | ||||
| 		ImagePath:       image, | ||||
| 		RootfsType:      rootfsType, | ||||
| 		KernelParams:    vc.DeserializeParams(strings.Fields(kernelParams)), | ||||
| 		KernelParams:    vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||
| 		NumVCPUs:        h.defaultVCPUs(), | ||||
| 		DefaultMaxVCPUs: h.defaultMaxVCPUs(), | ||||
| 		MemorySize:      h.defaultMemSz(), | ||||
|   | ||||
| @@ -159,7 +159,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (testConfig testRuntime | ||||
| 		KernelPath:            kernelPath, | ||||
| 		ImagePath:             imagePath, | ||||
| 		RootfsType:            rootfsType, | ||||
| 		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)), | ||||
| 		KernelParams:          vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||
| 		HypervisorMachineType: machineType, | ||||
| 		NumVCPUs:              defaultVCPUCount, | ||||
| 		DefaultMaxVCPUs:       getCurrentCpuNum(), | ||||
|   | ||||
| @@ -919,7 +919,7 @@ func CheckCmdline(kernelCmdlinePath, searchParam string, searchValues []string) | ||||
|  | ||||
| 	scanner := bufio.NewScanner(f) | ||||
| 	for scanner.Scan() { | ||||
| 		for _, field := range strings.Fields(scanner.Text()) { | ||||
| 		for _, field := range KernelParamFields(scanner.Text()) { | ||||
| 			if check(field, searchParam, searchValues) { | ||||
| 				return true, nil | ||||
| 			} | ||||
| @@ -941,7 +941,7 @@ func CPUFlags(cpuInfoPath string) (map[string]bool, error) { | ||||
| 	scanner := bufio.NewScanner(f) | ||||
| 	for scanner.Scan() { | ||||
| 		// Expected format: ["flags", ":", ...] or ["flags:", ...] | ||||
| 		fields := strings.Fields(scanner.Text()) | ||||
| 		fields := KernelParamFields(scanner.Text()) | ||||
| 		if len(fields) < 2 { | ||||
| 			continue | ||||
| 		} | ||||
| @@ -1085,3 +1085,35 @@ type Hypervisor interface { | ||||
| 	// check if hypervisor supports built-in rate limiter. | ||||
| 	IsRateLimiterBuiltin() bool | ||||
| } | ||||
|  | ||||
| // KernelParamFields is similar to strings.Fields(), but doesn't split | ||||
| // based on space characters that are part of a quoted substring. Example | ||||
| // of quoted kernel command line parameter value: | ||||
| // dm-mod.create="dm-verity,,,ro,0 736328 verity 1 | ||||
| // /dev/vda1 /dev/vda2 4096 4096 92041 0 sha256 | ||||
| // f211b9f1921ef726d57a72bf82be23a510076639fa8549ade10f85e214e0ddb4 | ||||
| // 065c13dfb5b4e0af034685aa5442bddda47b17c182ee44ba55a373835d18a038" | ||||
| func KernelParamFields(s string) []string { | ||||
| 	var params []string | ||||
|  | ||||
| 	start := 0 | ||||
| 	inQuote := false | ||||
| 	for current, c := range s { | ||||
| 		if c == '"' { | ||||
| 			inQuote = !inQuote | ||||
| 		} else if c == ' ' && !inQuote { | ||||
| 			newParam := strings.TrimSpace(s[start:current]) | ||||
| 			if newParam != "" { | ||||
| 				params = append(params, newParam) | ||||
| 			} | ||||
| 			start = current + 1 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	newParam := strings.TrimSpace(s[start:]) | ||||
| 	if newParam != "" { | ||||
| 		params = append(params, newParam) | ||||
| 	} | ||||
|  | ||||
| 	return params | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| @@ -490,3 +491,137 @@ func TestAssetPath(t *testing.T) { | ||||
| 		assert.Equal(expected, p, msg) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestKernelParamFields(t *testing.T) { | ||||
| 	assert := assert.New(t) | ||||
| 	tests := []struct { | ||||
| 		cmdLine                         string | ||||
| 		expectedFieldsResult            []string | ||||
| 		expectedKernelParamFieldsResult []string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			cmdLine: "a=b x=y", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x=y", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x=y", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "a=b x=y  foo=bar", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x=y", | ||||
| 				"foo=bar", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x=y", | ||||
| 				"foo=bar", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "a x=y  foo=bar", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"a", | ||||
| 				"x=y", | ||||
| 				"foo=bar", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"a", | ||||
| 				"x=y", | ||||
| 				"foo=bar", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "a=b      x foo=bar", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x", | ||||
| 				"foo=bar", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x", | ||||
| 				"foo=bar", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "a=b      x foo     ", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x", | ||||
| 				"foo", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x", | ||||
| 				"foo", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "a=b x=\"y z\"", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x=\"y", | ||||
| 				"z\"", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"a=b", | ||||
| 				"x=\"y z\"", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "foo=\"bar baz\"", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"foo=\"bar", | ||||
| 				"baz\"", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"foo=\"bar baz\"", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "foo=\"bar baz\"           abc=\"123\"", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"foo=\"bar", | ||||
| 				"baz\"", | ||||
| 				"abc=\"123\"", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"foo=\"bar baz\"", | ||||
| 				"abc=\"123\"", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "\"a=b", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"\"a=b", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"\"a=b", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			cmdLine: "\"a=b    x=y", | ||||
| 			expectedFieldsResult: []string{ | ||||
| 				"\"a=b", | ||||
| 				"x=y", | ||||
| 			}, | ||||
| 			expectedKernelParamFieldsResult: []string{ | ||||
| 				"\"a=b    x=y", | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, t := range tests { | ||||
| 		params := strings.Fields(t.cmdLine) | ||||
| 		assert.Equal(params, t.expectedFieldsResult, "Unexpected strings.Fields behavior") | ||||
|  | ||||
| 		params = KernelParamFields(t.cmdLine) | ||||
| 		assert.Equal(params, t.expectedKernelParamFieldsResult, "Unexpected KernelParamFields behavior") | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user