Страницы

Поиск по вопросам

воскресенье, 5 января 2020 г.

Не изменяется UID в рантайме golang, как изменить?

#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

Комментариев нет:

Отправить комментарий