Skip to content

Commit d8f6d09

Browse files
committed
Add Fmountat for mounting relative paths
Allow performing mounts from a given directory by performing a clone, chdir, and mount. Signed-off-by: Derek McGowan <[email protected]>
1 parent 92d147e commit d8f6d09

3 files changed

Lines changed: 157 additions & 0 deletions

File tree

sys/mount_linux.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package sys
18+
19+
import (
20+
"os"
21+
"runtime"
22+
"syscall"
23+
"unsafe"
24+
25+
"github.com/pkg/errors"
26+
)
27+
28+
// Fmountat performs the mount from the provided directory file descriptor
29+
func Fmountat(fd uintptr, source string, target string, fstype string, flags uintptr, data string) (err error) {
30+
// Do Go variable allocation before clone to prevent stack growth
31+
// after clone.
32+
var (
33+
sourceP, targetP, fstypeP *byte
34+
dataP *byte
35+
errno syscall.Errno
36+
)
37+
sourceP, err = syscall.BytePtrFromString(source)
38+
if err != nil {
39+
return
40+
}
41+
targetP, err = syscall.BytePtrFromString(target)
42+
if err != nil {
43+
return
44+
}
45+
fstypeP, err = syscall.BytePtrFromString(fstype)
46+
if err != nil {
47+
return
48+
}
49+
if data != "" {
50+
dataP, err = syscall.BytePtrFromString(data)
51+
if err != nil {
52+
return
53+
}
54+
}
55+
56+
runtime.LockOSThread()
57+
58+
beforeFork()
59+
pid, _, errno := syscall.RawSyscall6(syscall.SYS_CLONE, uintptr(syscall.SIGCHLD)|syscall.CLONE_FILES, 0, 0, 0, 0, 0)
60+
if errno != 0 {
61+
afterFork()
62+
63+
runtime.UnlockOSThread()
64+
65+
return errors.Errorf("clone failed with %d", errno)
66+
}
67+
68+
// if in the parent, wait on the child mount to finish and convert error
69+
if pid != 0 {
70+
afterFork()
71+
72+
runtime.UnlockOSThread()
73+
74+
p, err := os.FindProcess(int(pid))
75+
if err != nil {
76+
return err
77+
}
78+
79+
ps, err := p.Wait()
80+
if err != nil {
81+
return err
82+
}
83+
84+
if !ps.Success() {
85+
ws := ps.Sys().(syscall.WaitStatus)
86+
errno := ws.ExitStatus()
87+
if errno >= 0x7F {
88+
return errors.Wrap(syscall.Errno(errno-0x7F), "chdir")
89+
}
90+
return errors.Wrap(syscall.Errno(errno), "mount")
91+
92+
}
93+
94+
return nil
95+
}
96+
afterForkInChild()
97+
98+
_, _, errno = syscall.RawSyscall(syscall.SYS_FCHDIR, fd, 0, 0)
99+
if errno != 0 {
100+
if errno < 0x7F {
101+
errno += 0x7F
102+
}
103+
syscall.RawSyscall(syscall.SYS_EXIT, uintptr(errno), 0, 0)
104+
}
105+
106+
_, _, errno = syscall.Syscall6(syscall.SYS_MOUNT, uintptr(unsafe.Pointer(sourceP)), uintptr(unsafe.Pointer(targetP)), uintptr(unsafe.Pointer(fstypeP)), uintptr(flags), uintptr(unsafe.Pointer(dataP)), 0)
107+
108+
syscall.RawSyscall(syscall.SYS_CLOSE, fd, 0, 0)
109+
syscall.RawSyscall(syscall.SYS_EXIT, uintptr(errno), 0, 0)
110+
111+
panic("unreachable")
112+
}

sys/subprocess_linux.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package sys
18+
19+
import (
20+
_ "unsafe" // required for go:linkname.
21+
)
22+
23+
//go:linkname beforeFork syscall.runtime_BeforeFork
24+
func beforeFork()
25+
26+
//go:linkname afterFork syscall.runtime_AfterFork
27+
func afterFork()
28+
29+
//go:linkname afterForkInChild syscall.runtime_AfterForkInChild
30+
func afterForkInChild()

sys/subprocess_linux.s

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/

0 commit comments

Comments
 (0)