mirror of https://github.com/docker/cli.git
Add mode check for device
This fixes two problems: 1. docker run --device /dev/sda:rw ubuntu bash doesn't work 2. --device /dev/zero:/dev/noro:ro doesn't show clear error message, but fail when writing to cgroup file. Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
This commit is contained in:
parent
6a31056ff6
commit
22e1ac4966
37
opts/opts.go
37
opts/opts.go
|
@ -170,11 +170,32 @@ func ValidateLink(val string) (string, error) {
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidDeviceMode checks if the mode for device is valid or not.
|
||||||
|
// Valid mode is a composition of r (read), w (write), and m (mknod).
|
||||||
|
func ValidDeviceMode(mode string) bool {
|
||||||
|
var legalDeviceMode = map[rune]bool{
|
||||||
|
'r': true,
|
||||||
|
'w': true,
|
||||||
|
'm': true,
|
||||||
|
}
|
||||||
|
if mode == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range mode {
|
||||||
|
if !legalDeviceMode[c] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
legalDeviceMode[c] = false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// ValidateDevice Validate a path for devices
|
// ValidateDevice Validate a path for devices
|
||||||
// It will make sure 'val' is in the form:
|
// It will make sure 'val' is in the form:
|
||||||
// [host-dir:]container-path[:mode]
|
// [host-dir:]container-path[:mode]
|
||||||
|
// It will also validate the device mode.
|
||||||
func ValidateDevice(val string) (string, error) {
|
func ValidateDevice(val string) (string, error) {
|
||||||
return validatePath(val, false)
|
return validatePath(val, ValidDeviceMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidatePath Validate a path for volumes
|
// ValidatePath Validate a path for volumes
|
||||||
|
@ -182,27 +203,27 @@ func ValidateDevice(val string) (string, error) {
|
||||||
// [host-dir:]container-path[:rw|ro]
|
// [host-dir:]container-path[:rw|ro]
|
||||||
// It will also validate the mount mode.
|
// It will also validate the mount mode.
|
||||||
func ValidatePath(val string) (string, error) {
|
func ValidatePath(val string) (string, error) {
|
||||||
return validatePath(val, true)
|
return validatePath(val, volume.ValidMountMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validatePath(val string, validateMountMode bool) (string, error) {
|
func validatePath(val string, validator func(string) bool) (string, error) {
|
||||||
var containerPath string
|
var containerPath string
|
||||||
var mode string
|
var mode string
|
||||||
|
|
||||||
if strings.Count(val, ":") > 2 {
|
if strings.Count(val, ":") > 2 {
|
||||||
return val, fmt.Errorf("bad format for volumes: %s", val)
|
return val, fmt.Errorf("bad format for path: %s", val)
|
||||||
}
|
}
|
||||||
|
|
||||||
splited := strings.SplitN(val, ":", 3)
|
splited := strings.SplitN(val, ":", 3)
|
||||||
if splited[0] == "" {
|
if splited[0] == "" {
|
||||||
return val, fmt.Errorf("bad format for volumes: %s", val)
|
return val, fmt.Errorf("bad format for path: %s", val)
|
||||||
}
|
}
|
||||||
switch len(splited) {
|
switch len(splited) {
|
||||||
case 1:
|
case 1:
|
||||||
containerPath = splited[0]
|
containerPath = splited[0]
|
||||||
val = path.Clean(containerPath)
|
val = path.Clean(containerPath)
|
||||||
case 2:
|
case 2:
|
||||||
if isValid := volume.ValidMountMode(splited[1]); validateMountMode && isValid {
|
if isValid := validator(splited[1]); isValid {
|
||||||
containerPath = splited[0]
|
containerPath = splited[0]
|
||||||
mode = splited[1]
|
mode = splited[1]
|
||||||
val = fmt.Sprintf("%s:%s", path.Clean(containerPath), mode)
|
val = fmt.Sprintf("%s:%s", path.Clean(containerPath), mode)
|
||||||
|
@ -213,8 +234,8 @@ func validatePath(val string, validateMountMode bool) (string, error) {
|
||||||
case 3:
|
case 3:
|
||||||
containerPath = splited[1]
|
containerPath = splited[1]
|
||||||
mode = splited[2]
|
mode = splited[2]
|
||||||
if isValid := volume.ValidMountMode(splited[2]); validateMountMode && !isValid {
|
if isValid := validator(splited[2]); !isValid {
|
||||||
return val, fmt.Errorf("bad mount mode specified : %s", mode)
|
return val, fmt.Errorf("bad mode specified: %s", mode)
|
||||||
}
|
}
|
||||||
val = fmt.Sprintf("%s:%s:%s", splited[0], containerPath, mode)
|
val = fmt.Sprintf("%s:%s:%s", splited[0], containerPath, mode)
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,24 +289,24 @@ func TestValidatePath(t *testing.T) {
|
||||||
"/rw:rw",
|
"/rw:rw",
|
||||||
}
|
}
|
||||||
invalid := map[string]string{
|
invalid := map[string]string{
|
||||||
"": "bad format for volumes: ",
|
"": "bad format for path: ",
|
||||||
"./": "./ is not an absolute path",
|
"./": "./ is not an absolute path",
|
||||||
"../": "../ is not an absolute path",
|
"../": "../ is not an absolute path",
|
||||||
"/:../": "../ is not an absolute path",
|
"/:../": "../ is not an absolute path",
|
||||||
"/:path": "path is not an absolute path",
|
"/:path": "path is not an absolute path",
|
||||||
":": "bad format for volumes: :",
|
":": "bad format for path: :",
|
||||||
"/tmp:": " is not an absolute path",
|
"/tmp:": " is not an absolute path",
|
||||||
":test": "bad format for volumes: :test",
|
":test": "bad format for path: :test",
|
||||||
":/test": "bad format for volumes: :/test",
|
":/test": "bad format for path: :/test",
|
||||||
"tmp:": " is not an absolute path",
|
"tmp:": " is not an absolute path",
|
||||||
":test:": "bad format for volumes: :test:",
|
":test:": "bad format for path: :test:",
|
||||||
"::": "bad format for volumes: ::",
|
"::": "bad format for path: ::",
|
||||||
":::": "bad format for volumes: :::",
|
":::": "bad format for path: :::",
|
||||||
"/tmp:::": "bad format for volumes: /tmp:::",
|
"/tmp:::": "bad format for path: /tmp:::",
|
||||||
":/tmp::": "bad format for volumes: :/tmp::",
|
":/tmp::": "bad format for path: :/tmp::",
|
||||||
"path:ro": "path is not an absolute path",
|
"path:ro": "path is not an absolute path",
|
||||||
"/path:/path:sw": "bad mount mode specified : sw",
|
"/path:/path:sw": "bad mode specified: sw",
|
||||||
"/path:/path:rwz": "bad mount mode specified : rwz",
|
"/path:/path:rwz": "bad mode specified: rwz",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, path := range valid {
|
for _, path := range valid {
|
||||||
|
@ -333,27 +333,30 @@ func TestValidateDevice(t *testing.T) {
|
||||||
"/with space",
|
"/with space",
|
||||||
"/home:/with space",
|
"/home:/with space",
|
||||||
"relative:/absolute-path",
|
"relative:/absolute-path",
|
||||||
"hostPath:/containerPath:ro",
|
"hostPath:/containerPath:r",
|
||||||
"/hostPath:/containerPath:rw",
|
"/hostPath:/containerPath:rw",
|
||||||
"/hostPath:/containerPath:mrw",
|
"/hostPath:/containerPath:mrw",
|
||||||
}
|
}
|
||||||
invalid := map[string]string{
|
invalid := map[string]string{
|
||||||
"": "bad format for volumes: ",
|
"": "bad format for path: ",
|
||||||
"./": "./ is not an absolute path",
|
"./": "./ is not an absolute path",
|
||||||
"../": "../ is not an absolute path",
|
"../": "../ is not an absolute path",
|
||||||
"/:../": "../ is not an absolute path",
|
"/:../": "../ is not an absolute path",
|
||||||
"/:path": "path is not an absolute path",
|
"/:path": "path is not an absolute path",
|
||||||
":": "bad format for volumes: :",
|
":": "bad format for path: :",
|
||||||
"/tmp:": " is not an absolute path",
|
"/tmp:": " is not an absolute path",
|
||||||
":test": "bad format for volumes: :test",
|
":test": "bad format for path: :test",
|
||||||
":/test": "bad format for volumes: :/test",
|
":/test": "bad format for path: :/test",
|
||||||
"tmp:": " is not an absolute path",
|
"tmp:": " is not an absolute path",
|
||||||
":test:": "bad format for volumes: :test:",
|
":test:": "bad format for path: :test:",
|
||||||
"::": "bad format for volumes: ::",
|
"::": "bad format for path: ::",
|
||||||
":::": "bad format for volumes: :::",
|
":::": "bad format for path: :::",
|
||||||
"/tmp:::": "bad format for volumes: /tmp:::",
|
"/tmp:::": "bad format for path: /tmp:::",
|
||||||
":/tmp::": "bad format for volumes: :/tmp::",
|
":/tmp::": "bad format for path: :/tmp::",
|
||||||
"path:ro": "ro is not an absolute path",
|
"path:ro": "ro is not an absolute path",
|
||||||
|
"path:rr": "rr is not an absolute path",
|
||||||
|
"a:/b:ro": "bad mode specified: ro",
|
||||||
|
"a:/b:rr": "bad mode specified: rr",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, path := range valid {
|
for _, path := range valid {
|
||||||
|
|
Loading…
Reference in New Issue