Example #1
0
func dropPrivileges(UID, GID int, chrootDir string) (chrootErr error, err error) {
	if (UID == -1) != (GID == -1) {
		return nil, errors.New("either both or neither UID and GID must be -1")
	}

	if isRoot() {
		if UID <= 0 || GID <= 0 {
			return nil, errors.New("must specify UID/GID when running as root")
		}
	}

	var gids []int
	if UID != -1 {
		gids, err = passwd.GetExtraGIDs(GID)
		if err != nil {
			return nil, err
		}
	}

	chrootErr = tryChroot(chrootDir)

	gids = append(gids, GID)

	err = tryDropPrivileges(UID, GID, gids)
	if err == errZeroUID {
		return
	} else if err != nil {
		if caps.PlatformSupportsCaps {
			// We can't setuid, so maybe we only have a few caps.
			// Drop them.
			err = caps.Drop()
			if err != nil {
				err = fmt.Errorf("cannot drop caps: %v", err)
			}
		}
	}

	return
}
Example #2
0
func (h *ihandler) DropPrivileges() error {
	if h.dropped {
		return nil
	}

	// Extras
	if !h.info.NoBanSuid {
		// Try and bansuid, but don't process errors. It may not be supported on
		// the current platform, and Linux won't allow SECUREBITS to be set unless
		// one is root (or has the right capability). This is basically a
		// best-effort thing.
		bansuid.BanSuid()
	}

	// Various fixups
	if *uidFlag != "" && *gidFlag == "" {
		gid, err := passwd.GetGIDForUID(*uidFlag)
		if err != nil {
			return err
		}
		*gidFlag = strconv.FormatInt(int64(gid), 10)
	}

	if h.info.DefaultChroot == "" {
		h.info.DefaultChroot = "/"
	}

	chrootPath := *chrootFlag
	if chrootPath == "" {
		chrootPath = h.info.DefaultChroot
	}

	uid := -1
	gid := -1
	if *uidFlag != "" {
		var err error
		uid, err = passwd.ParseUID(*uidFlag)
		if err != nil {
			return err
		}

		gid, err = passwd.ParseGID(*gidFlag)
		if err != nil {
			return err
		}
	}

	if (uid <= 0) != (gid <= 0) {
		return fmt.Errorf("Either both or neither of the UID and GID must be positive")
	}

	if uid > 0 {
		chrootErr, err := daemon.DropPrivileges(uid, gid, chrootPath)
		if err != nil {
			return fmt.Errorf("Failed to drop privileges: %v", err)
		}
		if chrootErr != nil && *chrootFlag != "" && *chrootFlag != "/" {
			return fmt.Errorf("Failed to chroot: %v", chrootErr)
		}
	} else if *chrootFlag != "" && *chrootFlag != "/" {
		return fmt.Errorf("Must use privilege dropping to use chroot; set -uid")
	}

	// If we still have any caps (maybe because we didn't setuid), try and drop them.
	err := caps.Drop()
	if err != nil {
		return fmt.Errorf("cannot drop caps: %v", err)
	}

	if !h.info.AllowRoot && daemon.IsRoot() {
		return fmt.Errorf("Daemon must not run as root or with capabilities; run as non-root user or use -uid")
	}

	h.dropped = true
	return nil
}