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 }
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 }