func RestrictedChown(cwdFd int, file string, origStat os.FileInfo, uid, gid, reqUid, reqGid int) RCHStatus { status := RCOK openflags := syscall.O_NONBLOCK | syscall.O_NOCTTY if reqUid == -1 && reqGid == 1 { return RCDoOrdinaryChown } if !origStat.Mode().IsRegular() { if !origStat.Mode().IsDir() { return RCDoOrdinaryChown } openflags |= syscall.O_DIRECTORY } fd, err := syscall.Openat(cwdFd, file, syscall.O_RDONLY|openflags, 0) if !(0 <= fd || err == syscall.EACCES && origStat.Mode().IsRegular()) { if fd, err = syscall.Openat(cwdFd, file, syscall.O_WRONLY|openflags, 0); 0 > fd { if err == syscall.EACCES { return RCDoOrdinaryChown } return RCError } } var stat syscall.Stat_t if err := syscall.Fstat(fd, &stat); err != nil { status = RCError } else if !sameFile(origStat.Sys().(*syscall.Stat_t), &stat) { status = RCInodeChanged } else if reqUid == -1 || uint32(reqUid) == stat.Uid && (reqGid == -1 || uint32(reqGid) == stat.Gid) { if syscall.Fchown(fd, uid, gid) == nil { if syscall.Close(fd) == nil { return RCOK } return RCError } else { status = RCError } } return status }
func openat_native(dirfd int, path string, flags int, mode uint32) uint64 { fd, err := syscall.Openat(dirfd, path, flags, mode) if err != nil { return Errno(err) } return uint64(fd) }
func openChild(dir *os.File, name string, flags int, mode uint32) (*os.File, error) { dirFd := int(dir.Fd()) childFd, err := syscall.Openat(dirFd, name, flags, mode) if err != nil { return nil, err } return os.NewFile(uintptr(childFd), name), nil }
func LoadAt(cdirfd int) ([]NetInfo, error) { fd, err := syscall.Openat(cdirfd, filename, syscall.O_RDONLY, 0) if err != nil { return nil, err } f := os.NewFile(uintptr(fd), filename) var info []NetInfo err = json.NewDecoder(f).Decode(&info) return info, err }
// openFile opens a file from a pod's directory returning a file descriptor. func (p *pod) openFile(path string, flags int) (*os.File, error) { cdirfd, err := p.Fd() if err != nil { return nil, err } fd, err := syscall.Openat(cdirfd, path, flags, 0) if err != nil { return nil, err } return os.NewFile(uintptr(fd), path), nil }
func (l *linuxStandardInit) Init() error { if !l.config.Config.NoNewKeyring { ringname, keepperms, newperms := l.getSessionRingParams() // do not inherit the parent's session keyring sessKeyId, err := keys.JoinSessionKeyring(ringname) if err != nil { return err } // make session keyring searcheable if err := keys.ModKeyringPerm(sessKeyId, keepperms, newperms); err != nil { return err } } if err := setupNetwork(l.config); err != nil { return err } if err := setupRoute(l.config.Config); err != nil { return err } label.Init() // prepareRootfs() can be executed only for a new mount namespace. if l.config.Config.Namespaces.Contains(configs.NEWNS) { if err := prepareRootfs(l.pipe, l.config.Config); err != nil { return err } } // Set up the console. This has to be done *before* we finalize the rootfs, // but *after* we've given the user the chance to set up all of the mounts // they wanted. if l.config.CreateConsole { if err := setupConsole(l.pipe, l.config, true); err != nil { return err } if err := system.Setctty(); err != nil { return err } } // Finish the rootfs setup. if l.config.Config.Namespaces.Contains(configs.NEWNS) { if err := finalizeRootfs(l.config.Config); err != nil { return err } } if hostname := l.config.Config.Hostname; hostname != "" { if err := syscall.Sethostname([]byte(hostname)); err != nil { return err } } if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { return err } if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { return err } for key, value := range l.config.Config.Sysctl { if err := writeSystemProperty(key, value); err != nil { return err } } for _, path := range l.config.Config.ReadonlyPaths { if err := remountReadonly(path); err != nil { return err } } for _, path := range l.config.Config.MaskPaths { if err := maskPath(path); err != nil { return err } } pdeath, err := system.GetParentDeathSignal() if err != nil { return err } if l.config.NoNewPrivileges { if err := system.Prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { return err } } // Tell our parent that we're ready to Execv. This must be done before the // Seccomp rules have been applied, because we need to be able to read and // write to a socket. if err := syncParentReady(l.pipe); err != nil { return err } // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible. if l.config.Config.Seccomp != nil && !l.config.NoNewPrivileges { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return err } } if err := finalizeNamespace(l.config); err != nil { return err } // finalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := pdeath.Restore(); err != nil { return err } // compare the parent from the initial start of the init process and make sure that it did not change. // if the parent changes that means it died and we were reparented to something else so we should // just kill ourself and not cause problems for someone else. if syscall.Getppid() != l.parentPid { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } // check for the arg before waiting to make sure it exists and it is returned // as a create time error. name, err := exec.LookPath(l.config.Args[0]) if err != nil { return err } // close the pipe to signal that we have completed our init. l.pipe.Close() // wait for the fifo to be opened on the other side before // exec'ing the users process. fd, err := syscall.Openat(l.stateDirFD, execFifoFilename, os.O_WRONLY|syscall.O_CLOEXEC, 0) if err != nil { return newSystemErrorWithCause(err, "openat exec fifo") } if _, err := syscall.Write(fd, []byte("0")); err != nil { return newSystemErrorWithCause(err, "write 0 exec fifo") } if l.config.Config.Seccomp != nil && l.config.NoNewPrivileges { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return newSystemErrorWithCause(err, "init seccomp") } } if err := syscall.Exec(name, l.config.Args[0:], os.Environ()); err != nil { return newSystemErrorWithCause(err, "exec user process") } return nil }
func open(_relative *cursor, _relativePath string) (*cursor, Error) { var _path string if _relative != nil { _path = path.Join(_relative.entity.Path, _relativePath) } else { _path = _relativePath } var _descriptor, _errno int var _stat syscall.Stat_t var _link string _descriptor = -1 _errno = syscall.Lstat(_path, &_stat) if _errno == 0 { var _flags int = syscall.O_NOCTTY | syscall.O_NOFOLLOW | syscall.O_CLOEXEC | syscall.O_LARGEFILE | syscall.O_NOATIME var _mode uint32 = syscall.O_RDONLY for { if ((_stat.Mode & syscall.S_IFMT) != syscall.S_IFREG) && ((_stat.Mode & syscall.S_IFMT) != syscall.S_IFDIR) { break } if _relative != nil { _descriptor, _errno = syscall.Openat(_relative.entity.Descriptor, _relativePath, _flags, _mode) } else { _descriptor, _errno = syscall.Open(_relativePath, _flags, _mode) } if (_errno == syscall.EPERM) && ((_flags & syscall.O_NOATIME) == syscall.O_NOATIME) { _flags &= ^syscall.O_NOATIME continue } else { break } } switch { case _errno == 0: _errno = syscall.Fstat(_descriptor, &_stat) case _errno == syscall.EACCES: _descriptor = -1 case _errno == syscall.ELOOP: _descriptor = -1 case _errno == syscall.ENOENT: return nil, newError("open", _path, -1, _errno) case _errno != 0: _descriptor = -1 } if (_errno == 0) && ((_stat.Mode & syscall.S_IFMT) == syscall.S_IFLNK) { var _linkBuffer [syscall.PathMax + 1]byte var _linkLimit int _linkLimit, _errno = syscall.Readlink(_path, _linkBuffer[:]) if _errno == 0 { _link = string(_linkBuffer[:_linkLimit]) } } if (_errno != 0) && (_descriptor >= 0) { syscall.Close(_descriptor) _descriptor = -1 } } _entity := new(Entity) _entity.Name = path.Base(_path) _entity.Path = _path _entity.Errno = _errno _entity.Stat = _stat _entity.Link = _link _entity.Descriptor = _descriptor _cursor := new(cursor) _cursor.parent = _relative _cursor.entity = _entity return _cursor, nil }