try icon indicating copy to clipboard operation
try copied to clipboard

`try explore` to launch a shell

Open mgree opened this issue 1 year ago • 12 comments

Just start the user's default login shell in the overlay.

mgree avatar May 24 '23 17:05 mgree

Exiting the innermost unshare after launching it with ./try bash seems to break the change detector, user would also have to exit twice for the two unshares.

root@pashtest:~/try2# exit
exit

Changes detected in the following files:

/tmp/tmp.NTpS2u5iF6/upperdir/etc/resolv.conf
/tmp/tmp.NTpS2u5iF6/upperdir/home/ubuntu/.bash_history

Commit these changes? [y/N]
[1]+  Stopped                 ./try bash
ubuntu@pashtest:~/try2$ exit
logout
There are stopped jobs.
ubuntu@pashtest:~/try2$

Is there a way to not break the background task?

ezrizhu avatar Jun 20 '23 01:06 ezrizhu

I'm surprised by that. Does putting an exec on line 40 (the first unshare) resolve that?

mgree avatar Jun 20 '23 19:06 mgree

Adding exec in the first(inner) unshare did not change anything, I'd either have to exit out or fg to bring it out.

ubuntu@pashtest:~/try$ ./try bash
+ NO_COMMIT=interactive
+ getopts :nD: opt
+ shift 0
+ [ 1 -eq 0 ]
+ try bash
+ START_DIR=/home/ubuntu/try
+ [  ]
+ mktemp -d
+ SANDBOX_DIR=/tmp/tmp.lWI53IWxxQ
+ mkdir -p /tmp/tmp.lWI53IWxxQ/upperdir /tmp/tmp.lWI53IWxxQ/workdir /tmp/tmp.lWI53IWxxQ/temproot
+ xargs -I {} mkdir /tmp/tmp.lWI53IWxxQ/temproot/{} /tmp/tmp.lWI53IWxxQ/workdir/{} /tmp/tmp.lWI53IWxxQ/upperdir/{}
+ ls /
+ mktemp
+ mount_and_execute=/tmp/tmp.dQdvWDVooS
+ mktemp
+ chroot_executable=/tmp/tmp.23LFG6pWzN
+ cat
+ cat
+ chmod +x /tmp/tmp.dQdvWDVooS /tmp/tmp.23LFG6pWzN
+ unshare --mount --map-root-user --user --pid --fork /tmp/tmp.dQdvWDVooS
root@pashtest:~/try# echo hi
hi
root@pashtest:~/try# exit
exit
+ summary /tmp/tmp.lWI53IWxxQ
+ [ -d /tmp/tmp.lWI53IWxxQ ]
+ [ -d /tmp/tmp.lWI53IWxxQ/upperdir ]
+ grep -v -e .rkr -e Rikerfile
+ find /tmp/tmp.lWI53IWxxQ/upperdir/ -type f -or ( -type c -size 0 )
+ changed_files=/tmp/tmp.lWI53IWxxQ/upperdir/home/ubuntu/.bash_history
+ [ /tmp/tmp.lWI53IWxxQ/upperdir/home/ubuntu/.bash_history ]
+ echo

+ echo Changes detected in the following files:
Changes detected in the following files:
+ echo

+ echo /tmp/tmp.lWI53IWxxQ/upperdir/home/ubuntu/.bash_history
/tmp/tmp.lWI53IWxxQ/upperdir/home/ubuntu/.bash_history
+ return 0
+ [ 0 -eq 0 ]
+ echo

+ read -p Commit these changes? [y/N]  DO_COMMIT
Commit these changes? [y/N]
[1]+  Stopped                 ./try bash

Adding exec in the second(outer) unshare made it not trigger the change detector and exitted normally. The same thing happens if i add exec in front of both unshares.

ubuntu@pashtest:~/try$ ./try bash
+ NO_COMMIT=interactive
+ getopts :nD: opt
+ shift 0
+ [ 1 -eq 0 ]
+ try bash
+ START_DIR=/home/ubuntu/try
+ [  ]
+ mktemp -d
+ SANDBOX_DIR=/tmp/tmp.xznynBSqVJ
+ mkdir -p /tmp/tmp.xznynBSqVJ/upperdir /tmp/tmp.xznynBSqVJ/workdir /tmp/tmp.xznynBSqVJ/temproot
+ xargs -I {} mkdir /tmp/tmp.xznynBSqVJ/temproot/{} /tmp/tmp.xznynBSqVJ/workdir/{} /tmp/tmp.xznynBSqVJ/upperdir/{}
+ ls /
+ mktemp
+ mount_and_execute=/tmp/tmp.YhVYimL5Ux
+ mktemp
+ chroot_executable=/tmp/tmp.meqxaeXsqf
+ cat
+ cat
+ chmod +x /tmp/tmp.YhVYimL5Ux /tmp/tmp.meqxaeXsqf
+ exec unshare --mount --map-root-user --user --pid --fork /tmp/tmp.YhVYimL5Ux
root@pashtest:~/try# echo hi
hi
root@pashtest:~/try# exit
exit
ubuntu@pashtest:~/try$ fg
-bash: fg: current: no such job

ezrizhu avatar Jun 20 '23 20:06 ezrizhu

Huh... something weird is going on (with process groups?) if the shell is going into the background. I wonder: does invoking the try explore shell as bash -i change anything?

mgree avatar Jun 20 '23 20:06 mgree

Running ./try bash -i did not seem to change it, with or without the exec on the first unshare. Adding a wait under the outer unshare also did not seem to fix it.

ezrizhu avatar Jun 20 '23 21:06 ezrizhu

Okay, weird. We can try to debug this in person.

mgree avatar Jun 21 '23 18:06 mgree

This happens because the shell takes control over the terminal try runs in. After that process exits try tries to read from stdin again which appears as one backgrounded process reading from stdin after the terminal has used it. The solution is allocating a PTY to run the outer unshare process in so there aren't multiple interactive processes trying to use the same TTY.

MartijnBraam avatar Jun 26 '23 14:06 MartijnBraam

That mostly makes sense... but I would expect try to be the process group in charge again after the inner shell exits. 🤔

Before we go down the rabbit hole of managing a pty ourselves, we should see if trap '' TTIN TTOU in the try script is enough to fix this, since there's no real race on STDIN between the inner shell and the outer script.

EDIT: fixed trap to ignore (empty string), not set default (dash).

mgree avatar Jun 26 '23 16:06 mgree

Before we go down the rabbit hole of managing a pty ourselves, we should see if trap - TTIN TTOU in the try script is enough to fix this, since there's no real race on STDIN between the inner shell and the outer script.

Do we add trap - TTIN TTOU on top of the try script, or before/after the unshare invocation?

ezrizhu avatar Jun 26 '23 17:06 ezrizhu

We want:

# do the actual unshare, etc

trap '' TTIN TTOU

# prompt the user about committing

NB that I wrote trap - but meant trap ''. The former restores the default signal disposition; we want to ignore the signal.

mgree avatar Jun 26 '23 17:06 mgree

trap '' TTIN TTOU That did something, instead of sending try to the background, unshare choose "Not committing" and exited.

+ echo /tmp/tmp.tsWxX0YiTL/upperdir/home/ubuntu/.bash_history (modified/added)
/tmp/tmp.tsWxX0YiTL/upperdir/home/ubuntu/.bash_history (modified/added)
+ IFS= read -r changed_file
+ return 0
+ [ 0 -eq 0 ]
+ echo

+ read -p Commit these changes? [y/N]  DO_COMMIT
Commit these changes? [y/N] + printf Not commiting.\n
Not commiting.
+ echo /tmp/tmp.tsWxX0YiTL
/tmp/tmp.tsWxX0YiTL
+ exit 0

ezrizhu avatar Jun 26 '23 17:06 ezrizhu

However, if the reading process is ignoring or blocking this signal, then read fails with an EIO error instead. (GNU libc docs)

Well, joke's on me: that's not going to work then. @MartijnBraam, do you know of a nice POSIXly correct way to manage this little pty dance?

mgree avatar Jun 26 '23 17:06 mgree

I have no idea at all how to fix this in shell scripts. I've got inspired by this tool and wrote some python stuff to mess with unshared and overlays and ran into this exact issue. In python I just used the pty module to wrap the call to the first unshared.

Definitely sounds like a utility that should exist though...

MartijnBraam avatar Jun 26 '23 19:06 MartijnBraam

setting -m in try fixes the issue for me, tho im not sure why— Eric ZhuOn Jun 26, 2023, at 15:46, Martijn Braam @.***> wrote: I have no idea at all how to fix this in shell scripts. I've got inspired by this tool and wrote some python stuff to mess with unshared and overlays and ran into this exact issue. In python I just used the pty module to wrap the call to the first unshared. Definitely sounds like a utility that should exist though...

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were assigned.Message ID: @.***>

ezrizhu avatar Jun 26 '23 19:06 ezrizhu

Oh: set -m works because it will launch the user's command in a separate process group, which means they'll coordinate properly (and get the behavior I expected). We should set -m right before we call the user's executable, but not before (so we don't get job control noise when we run background commands).

Can we coordinate the set -m with @angelhof's PR #68 that uses source/exec`? It should still work there, but good to confirm.

mgree avatar Jun 26 '23 19:06 mgree

Should we still add in a try explore command (may conflict if user has a binary named explore), or just mention in the readme that they can also run try bash to launch a shell and play with the sandbox.

ezrizhu avatar Jun 26 '23 22:06 ezrizhu

The user can always run try -- explore if they have an explore command.

mgree avatar Jun 27 '23 11:06 mgree