mirror of
https://github.com/containers/podman.git
synced 2025-06-17 23:20:59 +08:00
Fix machine volumes with long path and paths with dashes
AppleHV accepts a max 36 bytes for mount tags. Instead of using the fully qualified path for the mount tag, SHA256 the path, and truncate the shasum to 36 bytes. Also correctly escape dashes in mounted paths. Signed-off-by: Ashley Cui <acui@redhat.com>
This commit is contained in:
@ -96,19 +96,19 @@ func GenerateSystemDFilesForVirtiofsMounts(mounts []machine.VirtIoFs) ([]ignitio
|
|||||||
|
|
||||||
virtiofsAutomount := ignition.Unit{
|
virtiofsAutomount := ignition.Unit{
|
||||||
Enabled: ignition.BoolToPtr(true),
|
Enabled: ignition.BoolToPtr(true),
|
||||||
Name: fmt.Sprintf("%s.automount", mnt.Tag),
|
Name: fmt.Sprintf("%s.automount", parser.PathEscape(mnt.Target)),
|
||||||
Contents: ignition.StrToPtr(fmt.Sprintf(autoMountUnitFile, mnt.Target, mnt.Target)),
|
Contents: ignition.StrToPtr(fmt.Sprintf(autoMountUnitFile, mnt.Tag, mnt.Target)),
|
||||||
}
|
}
|
||||||
virtiofsMount := ignition.Unit{
|
virtiofsMount := ignition.Unit{
|
||||||
Enabled: ignition.BoolToPtr(true),
|
Enabled: ignition.BoolToPtr(true),
|
||||||
Name: fmt.Sprintf("%s.mount", mnt.Tag),
|
Name: fmt.Sprintf("%s.mount", parser.PathEscape(mnt.Target)),
|
||||||
Contents: ignition.StrToPtr(fmt.Sprintf(mountUnitFile, mnt.Tag, mnt.Target)),
|
Contents: ignition.StrToPtr(fmt.Sprintf(mountUnitFile, mnt.Tag, mnt.Target)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// This "unit" simulates something like systemctl enable virtiofs-mount-prepare@
|
// This "unit" simulates something like systemctl enable virtiofs-mount-prepare@
|
||||||
enablePrep := ignition.Unit{
|
enablePrep := ignition.Unit{
|
||||||
Enabled: ignition.BoolToPtr(true),
|
Enabled: ignition.BoolToPtr(true),
|
||||||
Name: fmt.Sprintf("virtiofs-mount-prepare@%s.service", mnt.Tag),
|
Name: fmt.Sprintf("virtiofs-mount-prepare@%s.service", parser.PathEscape(mnt.Target)),
|
||||||
}
|
}
|
||||||
|
|
||||||
unitFiles = append(unitFiles, virtiofsAutomount, virtiofsMount, enablePrep)
|
unitFiles = append(unitFiles, virtiofsAutomount, virtiofsMount, enablePrep)
|
||||||
|
@ -207,7 +207,8 @@ var _ = Describe("podman machine init", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = os.CreateTemp(tmpDir, "example")
|
_, err = os.CreateTemp(tmpDir, "example")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
mount := tmpDir + ":/testmountdir"
|
// Test long target path, see https://github.com/containers/podman/issues/22226
|
||||||
|
mount := tmpDir + ":/very-long-test-mount-dir-path-more-than-thirty-six-bytes"
|
||||||
defer func() { _ = utils.GuardedRemoveAll(tmpDir) }()
|
defer func() { _ = utils.GuardedRemoveAll(tmpDir) }()
|
||||||
|
|
||||||
name := randomString()
|
name := randomString()
|
||||||
@ -217,7 +218,7 @@ var _ = Describe("podman machine init", func() {
|
|||||||
Expect(session).To(Exit(0))
|
Expect(session).To(Exit(0))
|
||||||
|
|
||||||
ssh := sshMachine{}
|
ssh := sshMachine{}
|
||||||
sshSession, err := mb.setName(name).setCmd(ssh.withSSHCommand([]string{"ls /testmountdir"})).run()
|
sshSession, err := mb.setName(name).setCmd(ssh.withSSHCommand([]string{"ls /very-long-test-mount-dir-path-more-than-thirty-six-bytes"})).run()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(sshSession).To(Exit(0))
|
Expect(sshSession).To(Exit(0))
|
||||||
Expect(sshSession.outputToString()).To(ContainSubstring("example"))
|
Expect(sshSession.outputToString()).To(ContainSubstring("example"))
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
|
||||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
)
|
)
|
||||||
@ -29,14 +30,13 @@ func (v VirtIoFs) Kind() string {
|
|||||||
return string(VirtIOFsVk)
|
return string(VirtIOFsVk)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unitName is the fq path where /'s are replaced with -'s
|
// generateTag generates a tag for VirtIOFs mounts.
|
||||||
func (v VirtIoFs) unitName() string {
|
// AppleHV requires tags to be 36 bytes or fewer.
|
||||||
// delete the leading -
|
// SHA256 the path, then truncate to 36 bytes
|
||||||
unit := strings.ReplaceAll(v.Target, "/", "-")
|
func (v VirtIoFs) generateTag() string {
|
||||||
if strings.HasPrefix(unit, "-") {
|
sum := sha256.Sum256([]byte(v.Target))
|
||||||
return unit[1:]
|
stringSum := hex.EncodeToString(sum[:])
|
||||||
}
|
return stringSum[:36]
|
||||||
return unit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v VirtIoFs) ToMount() vmconfigs.Mount {
|
func (v VirtIoFs) ToMount() vmconfigs.Mount {
|
||||||
@ -58,7 +58,7 @@ func NewVirtIoFsMount(src, target string, readOnly bool) VirtIoFs {
|
|||||||
Source: src,
|
Source: src,
|
||||||
Target: target,
|
Target: target,
|
||||||
}
|
}
|
||||||
vfs.Tag = vfs.unitName()
|
vfs.Tag = vfs.generateTag()
|
||||||
return vfs
|
return vfs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,13 +428,17 @@ func splitString(s string, separators string, flags SplitFlags) ([]string, error
|
|||||||
return splitStringAppend(make([]string, 0), s, separators, flags)
|
return splitStringAppend(make([]string, 0), s, separators, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func charNeedEscape(c rune) bool {
|
func charNeedEscape(c rune, isPath bool) bool {
|
||||||
if c > 128 {
|
if c > 128 {
|
||||||
return false /* unicode is ok */
|
return false /* unicode is ok */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pathRune := (isPath && c == '-') ||
|
||||||
|
(isPath && c == '/')
|
||||||
|
|
||||||
return unicode.IsSpace(c) ||
|
return unicode.IsSpace(c) ||
|
||||||
unicode.IsControl(c) ||
|
unicode.IsControl(c) ||
|
||||||
|
pathRune ||
|
||||||
c == '"' ||
|
c == '"' ||
|
||||||
c == '\'' ||
|
c == '\'' ||
|
||||||
c == '\\'
|
c == '\\'
|
||||||
@ -442,18 +446,22 @@ func charNeedEscape(c rune) bool {
|
|||||||
|
|
||||||
func wordNeedEscape(word string) bool {
|
func wordNeedEscape(word string) bool {
|
||||||
for _, c := range word {
|
for _, c := range word {
|
||||||
if charNeedEscape(c) {
|
if charNeedEscape(c, false) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendEscapeWord(escaped *strings.Builder, word string) {
|
func appendEscapeWord(escaped *strings.Builder, word string) {
|
||||||
escaped.WriteRune('"')
|
escaped.WriteRune('"')
|
||||||
for _, c := range word {
|
escapeString(escaped, word, false)
|
||||||
if charNeedEscape(c) {
|
escaped.WriteRune('"')
|
||||||
|
}
|
||||||
|
|
||||||
|
func escapeString(escaped *strings.Builder, word string, isPath bool) {
|
||||||
|
for i, c := range word {
|
||||||
|
if charNeedEscape(c, isPath) {
|
||||||
switch c {
|
switch c {
|
||||||
case '\a':
|
case '\a':
|
||||||
escaped.WriteString("\\a")
|
escaped.WriteString("\\a")
|
||||||
@ -477,6 +485,10 @@ func appendEscapeWord(escaped *strings.Builder, word string) {
|
|||||||
escaped.WriteString("\\\"")
|
escaped.WriteString("\\\"")
|
||||||
case '\'':
|
case '\'':
|
||||||
escaped.WriteString("'")
|
escaped.WriteString("'")
|
||||||
|
case '/':
|
||||||
|
if isPath && i != 0 {
|
||||||
|
escaped.WriteString("-")
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
escaped.WriteString(fmt.Sprintf("\\x%.2x", c))
|
escaped.WriteString(fmt.Sprintf("\\x%.2x", c))
|
||||||
}
|
}
|
||||||
@ -484,7 +496,6 @@ func appendEscapeWord(escaped *strings.Builder, word string) {
|
|||||||
escaped.WriteRune(c)
|
escaped.WriteRune(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
escaped.WriteRune('"')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func escapeWords(words []string) string {
|
func escapeWords(words []string) string {
|
||||||
@ -500,6 +511,5 @@ func escapeWords(words []string) string {
|
|||||||
escaped.WriteString(word)
|
escaped.WriteString(word)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return escaped.String()
|
return escaped.String()
|
||||||
}
|
}
|
||||||
|
@ -932,3 +932,9 @@ func (f *UnitFile) GetTemplateParts() (string, string) {
|
|||||||
}
|
}
|
||||||
return parts[0] + "@" + ext, parts[1]
|
return parts[0] + "@" + ext, parts[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PathEscape(path string) string {
|
||||||
|
var escaped strings.Builder
|
||||||
|
escapeString(&escaped, path, true)
|
||||||
|
return escaped.String()
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user