예제 #1
0
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
}
예제 #2
0
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)
}
예제 #3
0
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
}
예제 #4
0
파일: netinfo.go 프로젝트: sinfomicien/rkt
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
}
예제 #5
0
파일: pods.go 프로젝트: yanghongkjxy/rkt
// 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
}
예제 #6
0
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
}
예제 #7
0
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
}