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, | 		ImagePath:             image, | ||||||
| 		RootfsType:            rootfsType, | 		RootfsType:            rootfsType, | ||||||
| 		FirmwarePath:          firmware, | 		FirmwarePath:          firmware, | ||||||
| 		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)), | 		KernelParams:          vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||||
| 		NumVCPUs:              h.defaultVCPUs(), | 		NumVCPUs:              h.defaultVCPUs(), | ||||||
| 		DefaultMaxVCPUs:       h.defaultMaxVCPUs(), | 		DefaultMaxVCPUs:       h.defaultMaxVCPUs(), | ||||||
| 		MemorySize:            h.defaultMemSz(), | 		MemorySize:            h.defaultMemSz(), | ||||||
| @@ -853,7 +853,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | |||||||
| 		PFlash:                  pflashes, | 		PFlash:                  pflashes, | ||||||
| 		MachineAccelerators:     machineAccelerators, | 		MachineAccelerators:     machineAccelerators, | ||||||
| 		CPUFeatures:             cpuFeatures, | 		CPUFeatures:             cpuFeatures, | ||||||
| 		KernelParams:            vc.DeserializeParams(strings.Fields(kernelParams)), | 		KernelParams:            vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||||
| 		HypervisorMachineType:   machineType, | 		HypervisorMachineType:   machineType, | ||||||
| 		NumVCPUs:                h.defaultVCPUs(), | 		NumVCPUs:                h.defaultVCPUs(), | ||||||
| 		DefaultMaxVCPUs:         h.defaultMaxVCPUs(), | 		DefaultMaxVCPUs:         h.defaultMaxVCPUs(), | ||||||
| @@ -965,7 +965,7 @@ func newAcrnHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | |||||||
| 		HypervisorCtlPath:     hypervisorctl, | 		HypervisorCtlPath:     hypervisorctl, | ||||||
| 		HypervisorCtlPathList: h.CtlPathList, | 		HypervisorCtlPathList: h.CtlPathList, | ||||||
| 		FirmwarePath:          firmware, | 		FirmwarePath:          firmware, | ||||||
| 		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)), | 		KernelParams:          vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||||
| 		NumVCPUs:              h.defaultVCPUs(), | 		NumVCPUs:              h.defaultVCPUs(), | ||||||
| 		DefaultMaxVCPUs:       h.defaultMaxVCPUs(), | 		DefaultMaxVCPUs:       h.defaultMaxVCPUs(), | ||||||
| 		MemorySize:            h.defaultMemSz(), | 		MemorySize:            h.defaultMemSz(), | ||||||
| @@ -1055,7 +1055,7 @@ func newClhHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | |||||||
| 		RootfsType:                     rootfsType, | 		RootfsType:                     rootfsType, | ||||||
| 		FirmwarePath:                   firmware, | 		FirmwarePath:                   firmware, | ||||||
| 		MachineAccelerators:            machineAccelerators, | 		MachineAccelerators:            machineAccelerators, | ||||||
| 		KernelParams:                   vc.DeserializeParams(strings.Fields(kernelParams)), | 		KernelParams:                   vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||||
| 		HypervisorMachineType:          machineType, | 		HypervisorMachineType:          machineType, | ||||||
| 		NumVCPUs:                       h.defaultVCPUs(), | 		NumVCPUs:                       h.defaultVCPUs(), | ||||||
| 		DefaultMaxVCPUs:                h.defaultMaxVCPUs(), | 		DefaultMaxVCPUs:                h.defaultMaxVCPUs(), | ||||||
| @@ -1130,7 +1130,7 @@ func newDragonballHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { | |||||||
| 		KernelPath:      kernel, | 		KernelPath:      kernel, | ||||||
| 		ImagePath:       image, | 		ImagePath:       image, | ||||||
| 		RootfsType:      rootfsType, | 		RootfsType:      rootfsType, | ||||||
| 		KernelParams:    vc.DeserializeParams(strings.Fields(kernelParams)), | 		KernelParams:    vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||||
| 		NumVCPUs:        h.defaultVCPUs(), | 		NumVCPUs:        h.defaultVCPUs(), | ||||||
| 		DefaultMaxVCPUs: h.defaultMaxVCPUs(), | 		DefaultMaxVCPUs: h.defaultMaxVCPUs(), | ||||||
| 		MemorySize:      h.defaultMemSz(), | 		MemorySize:      h.defaultMemSz(), | ||||||
|   | |||||||
| @@ -159,7 +159,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (testConfig testRuntime | |||||||
| 		KernelPath:            kernelPath, | 		KernelPath:            kernelPath, | ||||||
| 		ImagePath:             imagePath, | 		ImagePath:             imagePath, | ||||||
| 		RootfsType:            rootfsType, | 		RootfsType:            rootfsType, | ||||||
| 		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)), | 		KernelParams:          vc.DeserializeParams(vc.KernelParamFields(kernelParams)), | ||||||
| 		HypervisorMachineType: machineType, | 		HypervisorMachineType: machineType, | ||||||
| 		NumVCPUs:              defaultVCPUCount, | 		NumVCPUs:              defaultVCPUCount, | ||||||
| 		DefaultMaxVCPUs:       getCurrentCpuNum(), | 		DefaultMaxVCPUs:       getCurrentCpuNum(), | ||||||
|   | |||||||
| @@ -919,7 +919,7 @@ func CheckCmdline(kernelCmdlinePath, searchParam string, searchValues []string) | |||||||
|  |  | ||||||
| 	scanner := bufio.NewScanner(f) | 	scanner := bufio.NewScanner(f) | ||||||
| 	for scanner.Scan() { | 	for scanner.Scan() { | ||||||
| 		for _, field := range strings.Fields(scanner.Text()) { | 		for _, field := range KernelParamFields(scanner.Text()) { | ||||||
| 			if check(field, searchParam, searchValues) { | 			if check(field, searchParam, searchValues) { | ||||||
| 				return true, nil | 				return true, nil | ||||||
| 			} | 			} | ||||||
| @@ -941,7 +941,7 @@ func CPUFlags(cpuInfoPath string) (map[string]bool, error) { | |||||||
| 	scanner := bufio.NewScanner(f) | 	scanner := bufio.NewScanner(f) | ||||||
| 	for scanner.Scan() { | 	for scanner.Scan() { | ||||||
| 		// Expected format: ["flags", ":", ...] or ["flags:", ...] | 		// Expected format: ["flags", ":", ...] or ["flags:", ...] | ||||||
| 		fields := strings.Fields(scanner.Text()) | 		fields := KernelParamFields(scanner.Text()) | ||||||
| 		if len(fields) < 2 { | 		if len(fields) < 2 { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| @@ -1085,3 +1085,35 @@ type Hypervisor interface { | |||||||
| 	// check if hypervisor supports built-in rate limiter. | 	// check if hypervisor supports built-in rate limiter. | ||||||
| 	IsRateLimiterBuiltin() bool | 	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/kata-containers/kata-containers/src/runtime/virtcontainers/types" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -490,3 +491,137 @@ func TestAssetPath(t *testing.T) { | |||||||
| 		assert.Equal(expected, p, msg) | 		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