#linux #golang
func main() { // Выводит 0 fmt.Println(syscall.Getgid()) err := syscall.Setuid(1000) if err != nil { // Выводит operation not supported fmt.Println(err) } } Запускаю через sudo -E go run /path/...
Ответы
Ответ 1
tl;dr В Go Setuid () для Linux не реализован. Нужно использовать другие механизмы понижения привилегий. Немного деталей Дело в том, что в Linux потоки реализованы, как «облегчённые» процессы, и системный вызов setuid () устанавливает владельца только текущего потока, а соответствие поведению, описанному в POSIX обеспечивает обёртка над этим вызовом в glibc, которая посылает сигнал всем остальным потокам, вызывающий обработчик, который делает аналогичный системный вызов из каждого потока. Go в своей реализации не использует (и не хочет использовать) libc, а работает напрямую с системными вызовами, поэтому появился баг 1435, в результате которого id менялся только у вызывающего потока, а не у всего процесса. Хорошего решения пока ни кто не придумал, поэтому с Go-1.4 Setuid () заменён на заглушку, просто возвращающую ошибку.Ответ 2
Проверил, что работает на macos x и linux x64 при помощи вызова CGO. package main import ( "log" "syscall" ) /* #include#include */ import ( "C" ) func main() { myGid := 100 myUid := 100 if syscall.Getuid() == 0 { cerr, errno := C.setgid(C.gid_t(myGid)) if cerr != 0 { log.Fatalln("Error setting gid as %d, error: %d", myGid, errno) } cerr, errno = C.setuid(C.uid_t(myUid)) if cerr != 0 { log.Fatalln("Error setting UID as %d due to error:", myUid, errno) } } log.Printf("My uid is %d, my gid is %d", syscall.Getuid(), syscall.Getgid()) } Если нужен для портов, то setcap cap_net_bind_service=+ep имяexe
Комментариев нет:
Отправить комментарий