Esempio n. 1
0
// ShouldDropPrivs returns true if the application runs with sufficient
// privileges so that it should drop them
func ShouldDropPrivs() bool {
	if groups, err := syscall.Getgroups(); err == nil {
		for _, gid := range groups {
			if gid == 0 {
				return true
			}
		}
	}

	return syscall.Getuid() == 0 || syscall.Getgid() == 0

}
Esempio n. 2
0
func (k *PosixKernel) Getgroups(count int, buf co.Buf) uint64 {
	groups, err := syscall.Getgroups()
	if err != nil {
		return Errno(err)
	}
	length := uint64(len(groups))
	if count > 0 {
		if count < len(groups) {
			groups = groups[:count]
		}
		tmp := make([]uint32, len(groups))
		for i, v := range groups {
			tmp[i] = uint32(v)
		}
		if err := buf.Pack(tmp); err != nil {
			return UINT64_MAX // FIXME
		}
	}
	return length
}
Esempio n. 3
0
// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
func Getgroups() ([]int, error) {
	gids, e := syscall.Getgroups()
	return gids, NewSyscallError("getgroups", e)
}
Esempio n. 4
0
// Activates the mitigation measurements.
func Activate(uid int, gid int, path string) {
	if !CanActivate() {
		panic("Cannot activate mitigation measurements!")
	}

	// chroot directory
	err := syscall.Chroot(path)
	if err != nil {
		panic(err)
	}

	// change directory to new /
	err = syscall.Chdir("/")
	if err != nil {
		panic(err)
	}

	// drop all other groups
	err = syscall.Setgroups([]int{gid})
	if err != nil {
		panic(err)
	}

	// verify the empty group list
	gids, err := syscall.Getgroups()
	if err != nil {
		panic("Could not read groups!")
	}
	if len(gids) > 1 {
		panic("Could not drop groups!")
	} else if len(gids) == 1 {
		if gids[0] != gid {
			panic("Could not drop foreign groups!")
		}
	}

	// change group
	err = syscall.Setgid(gid)
	if err != nil {
		panic(err)
	}

	// verify the group change
	ngid := syscall.Getgid()
	if ngid != gid {
		panic("Could not change group id!")
	}

	// change user
	err = syscall.Setuid(uid)
	if err != nil {
		panic(err)
	}

	// verify the user change
	nuid := syscall.Getuid()
	if nuid != uid {
		panic("Could not change user id!")
	}

	// now drop all environment variables
	os.Clearenv()
}
Esempio n. 5
0
// The test will only work when running as root.
func TestActivate(t *testing.T) {
	// create temporary directory to test chrooting
	tmp, err := ioutil.TempDir("", "mitigationtest")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(tmp)
	err = syscall.Chmod(tmp, 0755)
	if err != nil {
		t.Fatal("Could not change temporary directory permissions!")
	}

	// improve cpu usage to test for broken os implementations of setuid()
	runtime.GOMAXPROCS(2)

	// create some go routines as root to later test them
	var sync chan bool = make(chan bool)
	for i := 0; i < TEST_ROUTINES_COUNT; i++ {
		go func() {
			// no op
			sync <- true
		}()
	}
	for i := 0; i < TEST_ROUTINES_COUNT; i++ {
		<-sync
	}

	// modify environment
	err = os.Setenv("malicous_env", "bad string")
	if err != nil {
		t.Fatal("Cannot setup environment variables!")
	}
	if len(os.Environ()) == 0 {
		t.Fatal("Environ() or Setenv() are broken!")
	}

	// do it!
	Activate(TEST_UID, TEST_GID, tmp)

	// verify uids
	uid := syscall.Getuid()
	if uid != TEST_UID {
		t.Error("Failed to change UID")
	}
	euid := syscall.Geteuid()
	if euid != TEST_UID {
		t.Error("Failed to change EUID")
	}

	// verify gid
	gid := syscall.Getgid()
	if gid != TEST_GID {
		t.Error("Failed to change GID")
	}

	// verify groups
	gids, err := syscall.Getgroups()
	if err != nil {
		t.Fatal("Could not get group list")
	}
	if len(gids) > 1 {
		t.Error("Not all groups are dropped!")
	} else if len(gids) == 1 {
		if gids[0] != TEST_GID {
			t.Error("Not all foreign groups are dropped!")
		}
	}

	// verify directory
	dh, err := os.Open("/")
	if err != nil {
		t.Fatal("Cannot open my root directory", err)
	}
	files, err := dh.Readdir(-1)
	if err != nil {
		t.Fatal("Cannot read my root directory")
	}
	if len(files) > 0 {
		t.Error("Root not changed to empty temporary directory!")
	}

	// verify environment
	if len(os.Environ()) > 0 {
		t.Error("Environment variables found!")
	}

	// test setuid() behaviour
	var results chan int = make(chan int)

	// start multiple goroutines, in a good OS, all all routines
	// should be switched to the new user
	for i := 0; i < TEST_ROUTINES_COUNT; i++ {
		go func() {
			results <- syscall.Getuid()
		}()
	}

	// check the results
	for i := 0; i < TEST_ROUTINES_COUNT; i++ {
		uid := <-results
		if uid != TEST_UID {
			t.Error("false uid: ", uid, " (you are using an unsafe os, read the package documentation!)")
			break
		}
	}
}