|
1 | | -// Copyright (c) 2018-2022, Sylabs Inc. All rights reserved. |
| 1 | +// Copyright (c) 2018-2024, Sylabs Inc. All rights reserved. |
2 | 2 | // This software is licensed under a 3-clause BSD license. Please consult the |
3 | 3 | // LICENSE.md file distributed with the sources of this project regarding your |
4 | 4 | // rights to use or distribute this software. |
5 | 5 |
|
6 | 6 | package priv |
7 | 7 |
|
8 | 8 | import ( |
9 | | - "os" |
10 | 9 | "runtime" |
11 | | - "syscall" |
| 10 | + |
| 11 | + "github.com/sylabs/singularity/v4/pkg/sylog" |
| 12 | + "golang.org/x/sys/unix" |
12 | 13 | ) |
13 | 14 |
|
14 | | -// Escalate escalates privileges of the thread or process. |
15 | | -// Since Go 1.16 syscall.Setresuid is an all-thread operation. |
16 | | -// A runtime.LockOSThread operation remains for older versions of Go. |
17 | | -func Escalate() error { |
| 15 | +type DropPrivsFunc func() error |
| 16 | + |
| 17 | +// EscalateRealEffective locks the current goroutine to execute on the current |
| 18 | +// OS thread, and then escalates the real and effective uid of the current OS |
| 19 | +// thread to root (uid 0). The previous real uid is set as the saved |
| 20 | +// set-user-ID. A dropPrivsFunc is returned, which must be called to drop |
| 21 | +// privileges and unlock the goroutine at the earliest suitable point. |
| 22 | +func EscalateRealEffective() (DropPrivsFunc, error) { |
18 | 23 | runtime.LockOSThread() |
19 | | - uid := os.Getuid() |
20 | | - return syscall.Setresuid(uid, 0, uid) |
21 | | -} |
| 24 | + uid, _, _ := unix.Getresuid() |
| 25 | + |
| 26 | + dropPrivsFunc := func() error { |
| 27 | + defer runtime.UnlockOSThread() |
| 28 | + sylog.Debugf("Drop r/e/s: %d/%d/%d", uid, uid, 0) |
| 29 | + return unix.Setresuid(uid, uid, 0) |
| 30 | + } |
22 | 31 |
|
23 | | -// Drop drops privileges of the thread or process. |
24 | | -// Since Go 1.16 syscall.Setresuid is an all-thread operation. |
25 | | -// A runtime.LockOSThread operation remains for older versions of Go. |
26 | | -func Drop() error { |
27 | | - defer runtime.UnlockOSThread() |
28 | | - uid := os.Getuid() |
29 | | - return syscall.Setresuid(uid, uid, 0) |
| 32 | + sylog.Debugf("Escalate r/e/s: %d/%d/%d", 0, 0, uid) |
| 33 | + // Note - unix.Setresuid makes a direct syscall which performs a single |
| 34 | + // thread escalation. Since Go 1.16, syscall.Setresuid is all-thread. |
| 35 | + return dropPrivsFunc, unix.Setresuid(0, 0, uid) |
30 | 36 | } |
0 commit comments