第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

是否可以在不同的用戶下運行 goroutine 或 go 方法?

是否可以在不同的用戶下運行 goroutine 或 go 方法?

Go
HUWWW 2023-06-19 17:36:27
我在一個小型網(wǎng)絡(luò)服務(wù)器上工作,該服務(wù)器提供文件并提供對每個用戶主目錄的訪問。如果源在 CI 中,則可以選擇在不同線程下回答每個請求,并確保每個線程都以調(diào)用者的用戶作為其用戶運行。有什么方法可以實現(xiàn)與 Go 中類似的東西嗎?理想情況下,處理請求的代碼部分、goroutine 或被調(diào)用的方法應該在調(diào)用者的用戶帳戶下運行。我做了一些研究,似乎在 Go 中我們可以將單個 goroutine 粘貼到當前線程,但我看不出如何創(chuàng)建一個新線程然后將 goroutine 附加到該線程。
查看完整描述

3 回答

?
慕田峪7331174

TA貢獻1828條經(jīng)驗 獲得超13個贊

不可能以不同的用戶身份運行 goroutine 或方法,因為它們都在與父進程相同的上下文中運行。Goroutines 相當于綠色線程,甚至不一定在每個例程中產(chǎn)生適當?shù)?OS 線程。

這個答案也可能取決于操作系統(tǒng),但我認為這也不適用于 Windows。

查看完整回答
反對 回復 2023-06-19
?
千巷貓影

TA貢獻1829條經(jīng)驗 獲得超7個贊

是的,您可以使用 Linux 系統(tǒng)調(diào)用setuid(不是內(nèi)置函數(shù)setuid)來做到這一點。我剛剛發(fā)現(xiàn)了這個問題并認為它必須是可能的,因為我也在其他編程語言中使用它。所以我解決了我的問題,并想報告如何做到這一點。

但是,SJP 寫的關(guān)于線程的內(nèi)容是正確的,并且正是我的問題的答案,但由于線程問題,它不會解決您的問題。

但是回到代碼……您需要調(diào)用LockOSThread以將當前的 go 例程修復到您當前正在執(zhí)行的線程中,并且您可以使用 syscall 更改上下文setuid。

這是 Linux 的工作示例:

package main


import (

? ? ? ? "fmt"

? ? ? ? "log"

? ? ? ? "os"

? ? ? ? "runtime"

? ? ? ? "sync"

? ? ? ? "syscall"

? ? ? ? "time"


)


func printUID() {

? ? ? ? fmt.Printf("Real UID: %d\n", syscall.Getuid())

? ? ? ? fmt.Printf("Effective UID: %d\n", syscall.Geteuid())

}


func main() {

? ? ? ? printUID()

? ? ? ? var wg sync.WaitGroup

? ? ? ? wg.Add(2)


? ? ? ? go func(wg *sync.WaitGroup) {

? ? ? ? ? ? ? ? defer wg.Done()

? ? ? ? ? ? ? ? time.Sleep(2 * time.Second)

? ? ? ? ? ? ? ? printUID()

? ? ? ? }(&wg)


? ? ? ? go func(wg *sync.WaitGroup) {

? ? ? ? ? ? ? ? runtime.LockOSThread()

? ? ? ? ? ? ? ? defer runtime.UnlockOSThread()

? ? ? ? ? ? ? ? defer wg.Done()


? ? ? ? ? ? ? ? _, _, serr := syscall.Syscall(syscall.SYS_SETUID, 1, 0, 0)

? ? ? ? ? ? ? ? if serr != 0 {

? ? ? ? ? ? ? ? ? ? ? ? log.Fatal(serr)

? ? ? ? ? ? ? ? ? ? ? ? os.Exit(1)

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? printUID()


? ? ? ? }(&wg)

? ? ? ? wg.Wait()

? ? ? ? printUID()

}

operation not supported如果您使用,您將收到syscall.Setuid:


serr := syscall.Setuid(1)

代替


_, _, serr := syscall.Syscall(syscall.SYS_SETUID, 1, 0, 0)


查看完整回答
反對 回復 2023-06-19
?
侃侃無極

TA貢獻2051條經(jīng)驗 獲得超10個贊

我沒有足夠的聲譽來真正評論那個。希望這提供了更多完整的工作示例,并且重要的是,演示了保持運行時不會混淆使用不同 UID 運行的線程。]

首先,嚴格按照您的要求進行操作需要一些技巧,而且并不是那么安全...

[Go 喜歡使用POSIX 語義進行操作,而您想做的是通過在單個進程中同時使用兩個或多個 UID 進行操作來打破 POSIX 語義。Go 需要 POSIX 語義,因為它在任何可用的線程上運行 goroutines,并且運行時需要它們都表現(xiàn)相同才能可靠地工作。由于 Linux 的setuid()系統(tǒng)調(diào)用不支持 POSIX 語義,Go 選擇不實現(xiàn) syscall.Setuid()直到最近在 go1.16 中使用POSIX 語義實現(xiàn)它成為可能。

  • 請注意,glibc如果您調(diào)用setuid(),系統(tǒng)調(diào)用本身會使用修復機制 (?glibc/nptl/setxid ) 進行包裝,并且會同時更改程序中所有線程的 UID 值。因此,即使在 C 中,您也必須進行一些修改才能解決此細節(jié)。]

話雖這么說,你可以讓 goroutines 以你想要的方式工作runtime.LockOSThread(),但不要在每次專門使用后立即丟棄鎖定的線程來混淆 Go 運行時。

像這樣的東西(稱之為uidserve.go):

// Program uidserve serves content as different uids. This is adapted

// from the https://golang.org/pkg/net/http/#ListenAndServe example.

package main


import (

? ? ? ? "fmt"

? ? ? ? "log"

? ? ? ? "net/http"

? ? ? ? "runtime"

? ? ? ? "syscall"

)


// Simple username to uid mapping.

var prefixUIDs = map[string]uintptr{

? ? ? ? "apple":? 100,

? ? ? ? "banana": 101,

? ? ? ? "cherry": 102,

}


type uidRunner struct {

? ? ? ? uid uintptr

}


func (u *uidRunner) ServeHTTP(w http.ResponseWriter, r *http.Request) {

? ? ? ? runtime.LockOSThread()

? ? ? ? // Note, we never runtime.UnlockOSThread().

? ? ? ? if _, _, e := syscall.RawSyscall(syscall.SYS_SETUID, u.uid, 0, 0); e != 0 {

? ? ? ? ? ? ? ? http.Error(w, "permission problem", http.StatusInternalServerError)

? ? ? ? ? ? ? ? return

? ? ? ? }

? ? ? ? fmt.Fprintf(w, "query %q executing as UID=%d\n", r.URL.Path, syscall.Getuid())

}


func main() {

? ? ? ? for u, uid := range prefixUIDs {

? ? ? ? ? ? ? ? h := &uidRunner{uid: uid}

? ? ? ? ? ? ? ? http.Handle(fmt.Sprint("/", u, "/"), h)

? ? ? ? }

? ? ? ? http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

? ? ? ? ? ? ? ? fmt.Fprintf(w, "general query %q executing as UID=%d\n", r.URL.Path, syscall.Getuid())

? ? ? ? })

? ? ? ? log.Fatal(http.ListenAndServe(":8080", nil))

}

像這樣構(gòu)建它:


$ go build uidserve.go

接下來,要讓它工作,您必須授予該程序一些特權(quán)。那就是做一個或另一個(是libcap 套件setcap中的一個工具):


$ sudo /sbin/setcap cap_setuid=ep ./uidserve

或者,更傳統(tǒng)的運行setuid-root的方式:


$ sudo chown root ./uidserve

$ sudo chmod +s ./uidserve

現(xiàn)在,如果您運行./uidserve并連接到您的瀏覽器,localhost:8080您可以嘗試獲取以下 URL:

  • localhost:8080/something在這里顯示類似general query "/something" executing as UID=您的 UID 的內(nèi)容。

  • localhost:8080/apple/pie這顯示了類似的東西query "/apple/pie" executing as UID=100。

  • ETC。

希望這有助于說明如何按照您的要求進行操作。[但是,由于它涉及很多技巧,所以我不建議真正這樣做……]


查看完整回答
反對 回復 2023-06-19
  • 3 回答
  • 0 關(guān)注
  • 193 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號