mirror of
https://github.com/containers/podman.git
synced 2025-12-10 15:47:46 +08:00
rootless: correctly propagate the exit status from the container
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
@@ -27,13 +27,13 @@ func main() {
|
|||||||
debug := false
|
debug := false
|
||||||
cpuProfile := false
|
cpuProfile := false
|
||||||
|
|
||||||
became, err := rootless.BecomeRootInUserNS()
|
became, ret, err := rootless.BecomeRootInUserNS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf(err.Error())
|
logrus.Errorf(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if became {
|
if became {
|
||||||
os.Exit(0)
|
os.Exit(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
if reexec.Init() {
|
if reexec.Init() {
|
||||||
|
|||||||
@@ -105,16 +105,16 @@ reexec_in_user_namespace(int ready)
|
|||||||
ret = read (ready, &b, 1) < 0;
|
ret = read (ready, &b, 1) < 0;
|
||||||
while (ret < 0 && errno == EINTR);
|
while (ret < 0 && errno == EINTR);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
_exit (1);
|
_exit (EXIT_FAILURE);
|
||||||
close (ready);
|
close (ready);
|
||||||
|
|
||||||
if (setresgid (0, 0, 0) < 0 ||
|
if (setresgid (0, 0, 0) < 0 ||
|
||||||
setresuid (0, 0, 0) < 0)
|
setresuid (0, 0, 0) < 0)
|
||||||
_exit (1);
|
_exit (EXIT_FAILURE);
|
||||||
|
|
||||||
execvp (argv[0], argv);
|
execvp (argv[0], argv);
|
||||||
|
|
||||||
_exit (1);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
@@ -67,14 +67,16 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
|
|||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// BecomeRootInUserNS re-exec podman in a new userNS
|
// BecomeRootInUserNS re-exec podman in a new userNS. It returns whether podman was re-executed
|
||||||
func BecomeRootInUserNS() (bool, error) {
|
// into a new user namespace and the return code from the re-executed podman process.
|
||||||
|
// If podman was re-executed the caller needs to propagate the error code returned by the child
|
||||||
|
// process.
|
||||||
|
func BecomeRootInUserNS() (bool, int, error) {
|
||||||
if os.Getuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
|
if os.Getuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
|
||||||
if os.Getenv("_LIBPOD_USERNS_CONFIGURED") == "init" {
|
if os.Getenv("_LIBPOD_USERNS_CONFIGURED") == "init" {
|
||||||
return false, runInUser()
|
return false, 0, runInUser()
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
@@ -82,7 +84,7 @@ func BecomeRootInUserNS() (bool, error) {
|
|||||||
|
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, -1, err
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
defer w.Close()
|
defer w.Close()
|
||||||
@@ -90,13 +92,13 @@ func BecomeRootInUserNS() (bool, error) {
|
|||||||
pidC := C.reexec_in_user_namespace(C.int(r.Fd()))
|
pidC := C.reexec_in_user_namespace(C.int(r.Fd()))
|
||||||
pid := int(pidC)
|
pid := int(pidC)
|
||||||
if pid < 0 {
|
if pid < 0 {
|
||||||
return false, errors.Errorf("cannot re-exec process")
|
return false, -1, errors.Errorf("cannot re-exec process")
|
||||||
}
|
}
|
||||||
|
|
||||||
setgroups := fmt.Sprintf("/proc/%d/setgroups", pid)
|
setgroups := fmt.Sprintf("/proc/%d/setgroups", pid)
|
||||||
err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666)
|
err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrapf(err, "cannot write setgroups file")
|
return false, -1, errors.Wrapf(err, "cannot write setgroups file")
|
||||||
}
|
}
|
||||||
|
|
||||||
var uids, gids []idtools.IDMap
|
var uids, gids []idtools.IDMap
|
||||||
@@ -115,7 +117,7 @@ func BecomeRootInUserNS() (bool, error) {
|
|||||||
uidMap := fmt.Sprintf("/proc/%d/uid_map", pid)
|
uidMap := fmt.Sprintf("/proc/%d/uid_map", pid)
|
||||||
err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getuid())), 0666)
|
err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getuid())), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrapf(err, "cannot write uid_map")
|
return false, -1, errors.Wrapf(err, "cannot write uid_map")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,13 +129,13 @@ func BecomeRootInUserNS() (bool, error) {
|
|||||||
gidMap := fmt.Sprintf("/proc/%d/gid_map", pid)
|
gidMap := fmt.Sprintf("/proc/%d/gid_map", pid)
|
||||||
err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getgid())), 0666)
|
err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getgid())), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrapf(err, "cannot write gid_map")
|
return false, -1, errors.Wrapf(err, "cannot write gid_map")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = w.Write([]byte("1"))
|
_, err = w.Write([]byte("1"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrapf(err, "write to sync pipe")
|
return false, -1, errors.Wrapf(err, "write to sync pipe")
|
||||||
}
|
}
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
@@ -150,9 +152,10 @@ func BecomeRootInUserNS() (bool, error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if C.reexec_in_user_namespace_wait(pidC) < 0 {
|
ret := C.reexec_in_user_namespace_wait(pidC)
|
||||||
return false, errors.Wrapf(err, "error waiting for the re-exec process")
|
if ret < 0 {
|
||||||
|
return false, -1, errors.Wrapf(err, "error waiting for the re-exec process")
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, int(ret), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ func IsRootless() bool {
|
|||||||
|
|
||||||
// BecomeRootInUserNS is a stub function that always returns false and an
|
// BecomeRootInUserNS is a stub function that always returns false and an
|
||||||
// error on unsupported OS's
|
// error on unsupported OS's
|
||||||
func BecomeRootInUserNS() (bool, error) {
|
func BecomeRootInUserNS() (bool, int, error) {
|
||||||
return false, errors.New("this function is not supported on this os")
|
return false, -1, errors.New("this function is not supported on this os")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRootlessUID returns the UID of the user in the parent userNS
|
// GetRootlessUID returns the UID of the user in the parent userNS
|
||||||
|
|||||||
Reference in New Issue
Block a user