mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-29 20:24:31 +00:00
runtime: optimize code for managing temp users for rootless mode
This commit does two chagnes: - move code for managing temp users to rootless.go. - use common function in qemu.go when shutdown the VM. Fixes: #2759 Signed-off-by: bin <bin@hyper.sh>
This commit is contained in:
parent
20f4c252b8
commit
bf8f582c1d
@ -10,9 +10,6 @@ package containerdshim
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
|
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless"
|
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
@ -24,6 +21,8 @@ import (
|
|||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
taskAPI "github.com/containerd/containerd/runtime/v2/task"
|
taskAPI "github.com/containerd/containerd/runtime/v2/task"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
|
"github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
|
||||||
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
@ -274,13 +273,15 @@ func doMount(mounts []*containerd_types.Mount, rootfs string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func configureNonRootHypervisor(runtimeConfig *oci.RuntimeConfig) error {
|
func configureNonRootHypervisor(runtimeConfig *oci.RuntimeConfig) error {
|
||||||
userName, err := createVmmUser()
|
userName, err := utils.CreateVmmUser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
removeVmmUser(userName)
|
if err2 := utils.RemoveVmmUser(userName); err2 != nil {
|
||||||
|
shimLog.WithField("userName", userName).WithError(err).Warn("failed to remove user")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -336,48 +337,3 @@ func configureNonRootHypervisor(runtimeConfig *oci.RuntimeConfig) error {
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("failed to get the gid of /dev/kvm")
|
return fmt.Errorf("failed to get the gid of /dev/kvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
func createVmmUser() (string, error) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
userName string
|
|
||||||
)
|
|
||||||
|
|
||||||
useraddPath, err := utils.FirstValidExecutable([]string{"/usr/sbin/useradd", "/sbin/useradd", "/bin/useradd"})
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
nologinPath, err := utils.FirstValidExecutable([]string{"/usr/sbin/nologin", "/sbin/nologin", "/bin/nologin"})
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add retries to mitigate temporary errors and race conditions. For example, the user already exists
|
|
||||||
// or another instance of the runtime is also creating a user.
|
|
||||||
maxAttempt := 5
|
|
||||||
for i := 0; i < maxAttempt; i++ {
|
|
||||||
userName = fmt.Sprintf("kata-%v", rand.Intn(100000))
|
|
||||||
_, err = utils.RunCommand([]string{useraddPath, "-M", "-s", nologinPath, userName, "-c", "\"Kata Containers temporary hypervisor user\""})
|
|
||||||
if err == nil {
|
|
||||||
return userName, nil
|
|
||||||
}
|
|
||||||
shimLog.WithField("attempt", i+1).WithField("username", userName).
|
|
||||||
WithError(err).Warn("failed to add user, will try again")
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("could not create VMM user: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeVmmUser(user string) {
|
|
||||||
userdelPath, err := utils.FirstValidExecutable([]string{"/usr/sbin/userdel", "/sbin/userdel", "/bin/userdel"})
|
|
||||||
if err != nil {
|
|
||||||
shimLog.WithField("username", user).WithError(err).Warn("failed to remove user")
|
|
||||||
}
|
|
||||||
// Add retries to mitigate temporary errors and race conditions.
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
_, err := utils.RunCommand([]string{userdelPath, "-f", user})
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
shimLog.WithField("username", user).WithField("attempt", i+1).WithError(err).Warn("failed to remove user")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -7,17 +7,22 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
acceptEncodingHeader = "Accept-Encoding"
|
acceptEncodingHeader = "Accept-Encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var utilsLog = logrus.WithFields(logrus.Fields{"source": "pkg/utils"})
|
||||||
|
|
||||||
// GzipAccepted returns whether the client will accept gzip-encoded content.
|
// GzipAccepted returns whether the client will accept gzip-encoded content.
|
||||||
func GzipAccepted(header http.Header) bool {
|
func GzipAccepted(header http.Header) bool {
|
||||||
a := header.Get(acceptEncodingHeader)
|
a := header.Get(acceptEncodingHeader)
|
||||||
@ -99,3 +104,52 @@ func FirstValidExecutable(paths []string) (string, error) {
|
|||||||
}
|
}
|
||||||
return "", fmt.Errorf("all the executables are invalid")
|
return "", fmt.Errorf("all the executables are invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateVmmUser create a temp user for running Kata Containers under rootless mode.
|
||||||
|
func CreateVmmUser() (string, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
userName string
|
||||||
|
)
|
||||||
|
|
||||||
|
useraddPath, err := FirstValidExecutable([]string{"/usr/sbin/useradd", "/sbin/useradd", "/bin/useradd"})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
nologinPath, err := FirstValidExecutable([]string{"/usr/sbin/nologin", "/sbin/nologin", "/bin/nologin"})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add retries to mitigate temporary errors and race conditions. For example, the user already exists
|
||||||
|
// or another instance of the runtime is also creating a user.
|
||||||
|
maxAttempt := 5
|
||||||
|
for i := 0; i < maxAttempt; i++ {
|
||||||
|
userName = fmt.Sprintf("kata-%v", rand.Intn(100000))
|
||||||
|
_, err = RunCommand([]string{useraddPath, "-M", "-s", nologinPath, userName, "-c", "\"Kata Containers temporary hypervisor user\""})
|
||||||
|
if err == nil {
|
||||||
|
return userName, nil
|
||||||
|
}
|
||||||
|
utilsLog.WithField("attempt", i+1).WithField("username", userName).
|
||||||
|
WithError(err).Warn("failed to add user, will try again")
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("could not create VMM user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveVmmUser delete user created by CreateVmmUser.
|
||||||
|
func RemoveVmmUser(user string) error {
|
||||||
|
userdelPath, err := FirstValidExecutable([]string{"/usr/sbin/userdel", "/sbin/userdel", "/bin/userdel"})
|
||||||
|
if err != nil {
|
||||||
|
utilsLog.WithField("username", user).WithError(err).Warn("failed to remove user")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add retries to mitigate temporary errors and race conditions.
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
if _, err = RunCommand([]string{userdelPath, "-f", user}); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
utilsLog.WithField("username", user).WithField("attempt", i+1).WithError(err).Warn("failed to remove user")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
@ -23,13 +23,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
"github.com/opencontainers/runc/libcontainer/userns"
|
"github.com/opencontainers/runc/libcontainer/userns"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
@ -24,6 +23,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless"
|
||||||
|
|
||||||
govmmQemu "github.com/kata-containers/govmm/qemu"
|
govmmQemu "github.com/kata-containers/govmm/qemu"
|
||||||
"github.com/opencontainers/selinux/go-selinux/label"
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -1026,13 +1027,8 @@ func (q *qemu) cleanupVM() error {
|
|||||||
q.Logger().WithError(err).WithField("uid", q.config.Uid).Warn("failed to find the user")
|
q.Logger().WithError(err).WithField("uid", q.config.Uid).Warn("failed to find the user")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
userdelPath, err := pkgUtils.FirstValidExecutable([]string{"/usr/sbin/userdel", "/sbin/userdel", "/bin/userdel"})
|
|
||||||
if err != nil {
|
if err := pkgUtils.RemoveVmmUser(u.Username); err != nil {
|
||||||
q.Logger().WithError(err).WithField("user", u.Username).Warn("failed to delete the user")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
_, err = pkgUtils.RunCommand([]string{userdelPath, "-f", u.Username})
|
|
||||||
if err != nil {
|
|
||||||
q.Logger().WithError(err).WithField("user", u.Username).Warn("failed to delete the user")
|
q.Logger().WithError(err).WithField("user", u.Username).Warn("failed to delete the user")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user