-
-
Notifications
You must be signed in to change notification settings - Fork 707
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Permissions error causing test failures #3584
Comments
Wrt my own data point:
(on current Archlinux) |
I tried this with the LTS kernel, and it still fails:
5.10 was tagged in December 2020, and I only started having problems a couple months ago, so it seems unlikely that it's as simple as a kernel regression. Drat. |
You know what comes up when I search for this? #249 |
...between the supervisor and the backup code. We should ideally pull most of what's common out into a shared module, but I was looking at this while debugging sandstorm-io#3584, and it seemed like a good start.
Did some debugging, it appears that this fails when the value of This raises a couple questions:
Thoughts? cc: @kentonv |
We shouldn't ever be setting UID 0 in a userns... I think we set UID 1000. We do actually support installing Sandstorm without root privileges, in which case the userns sandbox will be used. It's not just for tests. I don't know how many people actually do this though. |
Would Sandstorm work at:
|
@kentonv, the sequence of events I'm seeing is:
|
Ah, hmm. I forgot that that's how that worked. But it has worked for a long time and it still appears to work on my Debian Bullseye machine which is kernel 5.10. |
Hm, I am actually seeing the same error in a bullseye VM. You mentioned on IRC that you were seeing (seemingly unrelated, spurious) test failures though when putting together the release -- have you in fact seen those tests pass recently? I've been able to reproduce this on arch on older kernels, so per above I agree it's unlikely this is a kernel regression -- there must be some other system component at issue, but so far I am still scratching my head as to what that could be. |
from
And tracing through the code I can confirm the check it's failing isn't there in 5.10.
So we can't just ask the kernel devs to revert the change; we will have to work around it somehow. I'll have to think about how to do this. |
One possibility, which is more work than I'd like but I think would work: Rather than re-execing ourselves, we could instead hand the fdBundle and pid file back to a parent process outside the user namespace and exit, after which the parent process would restart us. Then, we would not need to do the first remapping. Will continue to mull this over, but would appreciate @kentonv's thoughts. |
There's actually no need to pass the bundle back, since the parent can just hold on to the bundle. I've got a version of the above fix locally that seems to get some tests to pass; I haven't pinned down if all of the other failures are unrelated. I'll open a PR soonish probably. |
Rather than having the update monitor itself exec the newly downloaded version of sandstorm, it simply exits (with status 0), and its parent process takes this as an indictation that it should re-spawn it (with the new version). This avoids the need to map ourselves to UID 0 in the user namespace, which avoids the EPERM error we were getting when later hiding the real UID from a grain. Per discussion on the issue, the old design no longer works as of Linux 5.12, after which spawning the grain we would need CAP_SETFCAP, which we do not want to have.
Opened a draft pr (#3603). |
What the hell? They just broke mapping UID 0 in a user namespace in kernel 5.12? And Linus didn't throw a tantrum? It feels like there are several ways they could have fixed the bug without outright breaking the ability for a non-privileged user to create a userns and be UID 0 inside it... |
Doing this is the source of sandstorm-io#3584, and contrary to the now-deleted comment, it doesn't seem to be necessary -- both launching the supervisor and taking backups seems to work as expected.
Doing this is the source of sandstorm-io#3584. Instead, make sure we've fully entered a new user namespace before we have to do anything that would require the capabilities that are dropped on exec(). The only marginally tricky bit here is we have to fork() for the unshare() to fully take effect.
Doing this is the source of sandstorm-io#3584. Instead, make sure we've fully entered a new user namespace before we have to do anything that would require the capabilities that are dropped on exec(). We also need to be in a new pid namespace, since we try to mount /proc so it needs to be a procfs that we own. We use clone() instead of unshare() for this so we don't have to disturb the process hierarchy. Restart/update doesn't quite work yet; when these are invoked, the server just dies with this in sandstorm.log: ** Shutting down due to signal *** Uncaught exception *** sandstorm/run-bundle.c++:2042: failed: waitpid(sandstormPid, &status, 0): No child processes stack: 61be6b 619fc5 61977c 495ea7 495a84 I still need to debug why it can't seem to find the server monitor.
Doing this is the source of sandstorm-io#3584. Instead, make sure we've fully entered a new user namespace before we have to do anything that would require the capabilities that are dropped on exec(). We also need to be in a new pid namespace, since we try to mount /proc so it needs to be a procfs that we own. We use clone() instead of unshare() for this so we don't have to disturb the process hierarchy. Restart/update doesn't quite work yet; when these are invoked, the server just dies with this in sandstorm.log: ** Shutting down due to signal *** Uncaught exception *** sandstorm/run-bundle.c++:2042: failed: waitpid(sandstormPid, &status, 0): No child processes stack: 61be6b 619fc5 61977c 495ea7 495a84 I still need to debug why it can't seem to find the server monitor.
Doing this is the source of sandstorm-io#3584. Instead, make sure we've fully entered a new user namespace before we have to do anything that would require the capabilities that are dropped on exec(). We also need to be in a new pid namespace, since we try to mount /proc so it needs to be a procfs that we own. We use clone() instead of unshare() for this so we don't have to disturb the process hierarchy.
Doing this is the source of #3584. Instead, make sure we've fully entered a new user namespace before we have to do anything that would require the capabilities that are dropped on exec(). We also need to be in a new pid namespace, since we try to mount /proc so it needs to be a procfs that we own. We use clone() instead of unshare() for this so we don't have to disturb the process hierarchy.
I finally spent a bit of time debugging the batch of new (~19) test failures we started seeing a month or two ago. For reference, I've attached a full log from
make test TESTCASE=tests/backup-restore.js
, which is one of the relevant tests; the many of the other tests fail with the same error.The interesting bit is this, error, which comes when setting up the sandbox for grains during test:
The stack trace pointed to this call:
sandstorm/src/sandstorm/supervisor.c++
Line 936 in 0d53a66
The error results in grains failing to start, and therefore causing the overall test to fail. I haven't ever seen this happen on an actual install (even a dev one), only when running the test suite.
I suspect something changed in the kernel that is affecting this (nothing changed on our end), but I don't really understand why this fails, or exactly what the relevant difference is between test & prod.
I would be interested to hear from folks wrt:
Probably the next step is to see if we can an find a system that still works, and see if we can get it to fail on a newer kernel, and if so bisect.
t1.log
The text was updated successfully, but these errors were encountered: