|
9 | 9 | "fmt"
|
10 | 10 | "os"
|
11 | 11 | "path/filepath"
|
| 12 | + "strconv" |
12 | 13 | "strings"
|
13 | 14 | "time"
|
14 | 15 |
|
@@ -225,56 +226,50 @@ func (h *InWorkspaceHandler) Mount(req *libseccomp.ScmpNotifReq) (val uint64, er
|
225 | 226 | "fstype": filesystem,
|
226 | 227 | }).Info("handling mount syscall")
|
227 | 228 |
|
228 |
| - if filesystem == "proc" { |
| 229 | + if filesystem == "proc" || filesystem == "sysfs" { |
| 230 | + // When a process wants to mount proc relative to `/proc/self` that path has no meaning outside of the processes' context. |
| 231 | + // runc started doing this in https://github.com/opencontainers/runc/commit/0ca91f44f1664da834bc61115a849b56d22f595f |
| 232 | + // TODO(cw): there must be a better way to handle this. Find one. |
229 | 233 | target := filepath.Join(h.Ring2Rootfs, dest)
|
230 |
| - stat, err := os.Lstat(target) |
231 |
| - if os.IsNotExist(err) { |
232 |
| - err = os.MkdirAll(target, 0755) |
233 |
| - } |
234 |
| - if err != nil { |
235 |
| - log.WithField("dest", dest).WithError(err).Error("cannot stat mountpoint") |
236 |
| - return Errno(unix.EFAULT) |
237 |
| - } else if stat != nil && stat.Mode()&os.ModeDir == 0 { |
238 |
| - log.WithField("dest", dest).WithError(err).Error("proc must be mounted on an ordinary directory") |
239 |
| - return Errno(unix.EPERM) |
240 |
| - } |
241 |
| - |
242 |
| - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) |
243 |
| - defer cancel() |
244 |
| - _, err = h.Daemon.MountProc(ctx, &daemonapi.MountProcRequest{ |
245 |
| - Target: dest, |
246 |
| - Pid: int64(req.Pid), |
247 |
| - }) |
248 |
| - if err != nil { |
249 |
| - log.WithField("target", target).WithError(err).Error("cannot mount proc") |
250 |
| - return Errno(unix.EFAULT) |
| 234 | + if strings.HasPrefix(dest, "/proc/self/") { |
| 235 | + target = filepath.Join("/proc", strconv.Itoa(int(req.Pid)), strings.TrimPrefix(dest, "/proc/self/")) |
251 | 236 | }
|
252 | 237 |
|
253 |
| - return 0, 0, 0 |
254 |
| - } |
255 |
| - |
256 |
| - if filesystem == "sysfs" { |
257 |
| - target := filepath.Join(h.Ring2Rootfs, dest) |
258 | 238 | stat, err := os.Lstat(target)
|
259 | 239 | if os.IsNotExist(err) {
|
260 | 240 | err = os.MkdirAll(target, 0755)
|
261 | 241 | }
|
262 | 242 | if err != nil {
|
263 |
| - log.WithField("dest", dest).WithError(err).Error("cannot stat mountpoint") |
| 243 | + log.WithField("target", target).WithField("dest", dest).WithError(err).Error("cannot stat mountpoint") |
264 | 244 | return Errno(unix.EFAULT)
|
265 |
| - } else if stat != nil && stat.Mode()&os.ModeDir == 0 { |
266 |
| - log.WithField("dest", dest).WithError(err).Error("sysfs must be mounted on an ordinary directory") |
267 |
| - return Errno(unix.EPERM) |
| 245 | + } |
| 246 | + if stat != nil { |
| 247 | + if stat.Mode()&os.ModeSymlink != 0 { |
| 248 | + // The symlink is already expressed relative to the ring2 mount namespace, no need to faff with the rootfs paths. |
| 249 | + // In case this was a /proc relative symlink, we'll have that symlink resolved here, hence make it work in the mount namespace of ring2. |
| 250 | + dest, err = os.Readlink(target) |
| 251 | + if err != nil { |
| 252 | + log.WithField("target", target).WithField("dest", dest).WithError(err).Errorf("cannot resolve %s mount target symlink", filesystem) |
| 253 | + return Errno(unix.EFAULT) |
| 254 | + } |
| 255 | + } else if stat.Mode()&os.ModeDir == 0 { |
| 256 | + log.WithField("target", target).WithField("dest", dest).WithField("mode", stat.Mode()).WithError(err).Errorf("%s must be mounted on an ordinary directory", filesystem) |
| 257 | + return Errno(unix.EPERM) |
| 258 | + } |
268 | 259 | }
|
269 | 260 |
|
270 | 261 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
271 | 262 | defer cancel()
|
272 |
| - _, err = h.Daemon.MountSysfs(ctx, &daemonapi.MountProcRequest{ |
| 263 | + call := h.Daemon.MountProc |
| 264 | + if filesystem == "sysfs" { |
| 265 | + call = h.Daemon.MountSysfs |
| 266 | + } |
| 267 | + _, err = call(ctx, &daemonapi.MountProcRequest{ |
273 | 268 | Target: dest,
|
274 | 269 | Pid: int64(req.Pid),
|
275 | 270 | })
|
276 | 271 | if err != nil {
|
277 |
| - log.WithField("target", target).WithError(err).Error("cannot mount sysfs") |
| 272 | + log.WithField("target", dest).WithError(err).Errorf("cannot mount %s", filesystem) |
278 | 273 | return Errno(unix.EFAULT)
|
279 | 274 | }
|
280 | 275 |
|
|
0 commit comments