MCPcopy
hub / github.com/google/gvisor / OpenTree

Function OpenTree

pkg/sentry/syscalls/linux/sys_mount_fd.go:295–386  ·  view source on GitHub ↗

OpenTree implements Linux syscall open_tree(2).

(t *kernel.Task, sysno uintptr, args arch.SyscallArguments)

Source from the content-addressed store, hash-verified

293
294// OpenTree implements Linux syscall open_tree(2).
295func OpenTree(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
296 dirfd := args[0].Int()
297 fromAddr := args[1].Pointer()
298 flags := args[2].Uint()
299
300 // TODO(b/270247637): gVisor does not yet support automount, so
301 // AT_NO_AUTOMOUNT flag is a no-op.
302 flags &= ^(uint32(linux.AT_NO_AUTOMOUNT))
303
304 if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW|linux.OPEN_TREE_CLOEXEC|linux.OPEN_TREE_CLONE|linux.AT_RECURSIVE) != 0 {
305 return 0, nil, linuxerr.EINVAL
306 }
307
308 recursive := flags&linux.AT_RECURSIVE == linux.AT_RECURSIVE
309 clone := flags&linux.OPEN_TREE_CLONE == linux.OPEN_TREE_CLONE
310 noFollow := flags&linux.AT_SYMLINK_NOFOLLOW == linux.AT_SYMLINK_NOFOLLOW
311 emptyPath := flags&linux.AT_EMPTY_PATH == linux.AT_EMPTY_PATH
312 closeOnExec := flags&linux.OPEN_TREE_CLOEXEC == linux.OPEN_TREE_CLOEXEC
313
314 // AT_RECURSIVE requires OPEN_TREE_CLONE
315 if recursive && !clone {
316 return 0, nil, linuxerr.EINVAL
317 }
318
319 // OPEN_TREE_CLONE: Must have CAP_SYS_ADMIN in the current mount namespace's
320 // associated user namespace.
321 creds := t.Credentials()
322 if clone && !creds.HasCapabilityIn(linux.CAP_SYS_ADMIN, t.MountNamespace().Owner) {
323 return 0, nil, linuxerr.EPERM
324 }
325
326 // Lookup the specified path
327 fromPath, err := copyInPath(t, fromAddr)
328 if err != nil {
329 return 0, nil, err
330 }
331 from, err := getTaskPathOperation(t, dirfd, fromPath, shouldAllowEmptyPath(emptyPath), shouldFollowFinalSymlink(!noFollow))
332 if err != nil {
333 return 0, nil, err
334 }
335 defer from.Release(t)
336
337 vfsObj := t.Kernel().VFS()
338
339 if clone {
340 // OPEN_TREE_CLONE: clone the mount tree into an anonymous mount ns
341
342 // Fetch the path's mount vd
343 fromVd, err := vfsObj.GetDentryAt(t, t.Credentials(), &from.pop, &vfs.GetDentryOptions{CheckSearchable: true})
344 if err != nil {
345 return 0, nil, err
346 }
347 defer fromVd.DecRef(t)
348
349 // Clone the mount (or the mount tree, depending on AT_RECURSIVE) into a new anonymous NS
350 anonNS, err := vfsObj.CloneTreeToAnonNS(t, t.MountNamespace(), fromVd, t.Kernel(), recursive)
351 if err != nil {
352 return 0, nil, err

Callers

nothing calls this directly

Calls 15

NewFunction · 0.92
copyInPathFunction · 0.85
getTaskPathOperationFunction · 0.85
shouldAllowEmptyPathFunction · 0.85
shouldFollowFinalSymlinkTypeAlias · 0.85
UintMethod · 0.80
MountNamespaceMethod · 0.80
VFSMethod · 0.80
KernelMethod · 0.80
CloneTreeToAnonNSMethod · 0.80
NewFDFromMethod · 0.80
CredentialsMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…