Golang中如何增加或减少当前进程的权限?
Golang中如何增加或减少当前进程的权限?
我在Go语言中使用工具包 github.com/syndtr/gocapability 来更改当前进程的权能。通过 caps.String() 函数获取的信息显示权能已经发生了变化。
代码链接:https://play.golang.org/p/SkJYyNeFrW0
但实际上并没有。例如,我想在 /dev 文件夹中创建一个新文件(这样做没有实际意义,仅作为实验),结果我并没有获得相应的权限。从 /proc/pid/status 中的信息也可以看出,权能并未改变。在Go语言中,如何增加或减少当前进程的权能?是否有其他方法或包?
func main() {
fmt.Println("hello world")
}
更多关于Golang中如何增加或减少当前进程的权限?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中如何增加或减少当前进程的权限?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中调整进程权能,推荐使用syscall包直接调用Linux权能系统调用。以下是两种实现方式:
方法一:使用syscall包(推荐)
package main
import (
"fmt"
"syscall"
"unsafe"
)
// Linux权能相关常量
const (
CAP_NET_RAW = 13 // 示例:网络原始套接字权能
CAP_SYS_ADMIN = 21 // 系统管理权能
)
// 获取当前权能集
func getCap() (uint64, uint64, uint64) {
var hdr = [3]uint32{
_LINUX_CAPABILITY_VERSION_3,
0, 0,
}
var data [2]uint64
_, _, err := syscall.Syscall(
syscall.SYS_CAPGET,
uintptr(unsafe.Pointer(&hdr)),
uintptr(unsafe.Pointer(&data)),
0,
)
if err != 0 {
return 0, 0, 0
}
return data[0], data[1], uint64(hdr[0])
}
// 设置权能集
func setCap(effective, permitted, inheritable uint64) error {
var hdr = [3]uint32{
_LINUX_CAPABILITY_VERSION_3,
0, 0,
}
var data [2]uint64
data[0] = effective
data[1] = permitted
_, _, err := syscall.Syscall(
syscall.SYS_CAPSET,
uintptr(unsafe.Pointer(&hdr)),
uintptr(unsafe.Pointer(&data)),
0,
)
if err != 0 {
return syscall.Errno(err)
}
return nil
}
func main() {
// 获取当前权能
eff, perm, _ := getCap()
fmt.Printf("当前权能: effective=%b, permitted=%b\n", eff, perm)
// 添加CAP_SYS_ADMIN权能(需要root权限)
newEff := eff | (1 << CAP_SYS_ADMIN)
newPerm := perm | (1 << CAP_SYS_ADMIN)
if err := setCap(newEff, newPerm, 0); err != nil {
fmt.Printf("设置权能失败: %v\n", err)
return
}
fmt.Println("权能已更新")
}
方法二:使用exec.Command运行特权命令
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
// 使用setcap命令设置权能
cmd := exec.Command("setcap", "cap_net_raw+ep", os.Args[0])
if err := cmd.Run(); err != nil {
fmt.Printf("设置权能失败: %v\n", err)
return
}
fmt.Println("权能设置成功")
// 验证权能
cmd = exec.Command("getcap", os.Args[0])
output, _ := cmd.Output()
fmt.Printf("当前权能: %s", output)
}
方法三:完整示例 - 创建/dev目录文件
package main
import (
"fmt"
"os"
"syscall"
)
func enableCapSysAdmin() error {
// 需要root权限运行
if os.Geteuid() != 0 {
return fmt.Errorf("需要root权限")
}
// 使用prctl系统调用
_, _, err := syscall.Syscall(
syscall.SYS_PRCTL,
syscall.PR_CAPBSET_READ,
uintptr(syscall.CAP_SYS_ADMIN),
0,
)
if err != 0 {
return fmt.Errorf("prctl失败: %v", err)
}
return nil
}
func main() {
// 启用SYS_ADMIN权能
if err := enableCapSysAdmin(); err != nil {
fmt.Printf("启用权能失败: %v\n", err)
return
}
// 尝试在/dev创建文件
f, err := os.Create("/dev/test_go_file")
if err != nil {
fmt.Printf("创建文件失败: %v\n", err)
return
}
defer f.Close()
defer os.Remove("/dev/test_go_file")
fmt.Println("文件创建成功")
}
编译和运行注意事项
# 需要root权限编译和运行
sudo go build -o privileged_app main.go
# 或者设置文件权能
sudo setcap cap_sys_admin+ep privileged_app
# 运行程序
./privileged_app
关键点:
- 权能操作需要root权限或已授予的权能
- 使用
syscall包直接调用系统调用最可靠 - 通过
/proc/self/status验证权能状态 - 考虑使用
exec.Command调用外部工具如setcap

