Skip to content
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

Import nginx code to set process title, use it for "cinit" #169

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

cgwalters
Copy link
Collaborator

When debugging things, it's really useful to be able to see from the process
output which thing is which. Here, we're using the term "cinit" for the
in-container init.

I looked around on the internets for this - I thought systemd would have a good
implementation, but they don't do the requsite trick with malloc to ensure we
have enough space. nginx does. Now, I also found
https://tycho.ws/blog/2015/02/setproctitle.html but their implementation
sounded way more complex.

So, going from the nginx code, I heavily edited it to drop Solaris/FreeBSD etc.
Also, to use xmalloc instead of their allocator, etc.

This just makes things easier to debug; there's a risk though that it's new
parsing code that is reachable in the suid case by an attacker outside; I'll do
some extra review on this if we agree to take it.

@cgwalters
Copy link
Collaborator Author

walters    188  0.0  0.0 126328  7896 pts/1    S    Jan22   0:12  |       \_ -bash
walters  17327  0.0  0.0  13324  1072 pts/1    S    12:39   0:00  |           \_ bwrap --unshare-pid --ro-bind / / sleep 1h
walters  17331  0.0  0.0  13324   144 pts/1    S    12:39   0:00  |           |   \_ bwrap: cinit
walters  17334  0.0  0.0 114540   656 pts/1    S    12:39   0:00  |           |       \_ sleep 1h


/* In upstream nginx, this is called early in main. However,
* I don't see a reason not to merge it with ngx_init_setproctitle()
*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong. The parse_args_recurse() function stores references to the argument data in various places, and if the replacing of the args is done after that then those places will point to an area we're actively modifying.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, i see you call this pretty early. Should be safe then.

@alexlarsson
Copy link
Collaborator

The failure is due to the saved argv/env leak, which i'm not sure we can fix. Can we suppress it?

@alexlarsson
Copy link
Collaborator

Anyway, this seems very useful to me.
Should we start a stable branch and commit this (and other features) to master? Or maybe this qualifies for "bugfix".

@alexlarsson
Copy link
Collaborator

Oh, and do we really need to keep the ngx_ prefix?

@cgwalters
Copy link
Collaborator Author

If you look at the logs, we have other problems because ASAN gets confused (understandably) by unsharing the PID namespace and forking. I'll look at keeping ASAN enabled, just with leak detection disabled.

@cgwalters
Copy link
Collaborator Author

Re ngx_...dunno. It's a way of giving them credit, and helping us remember that if we make any bugfixes here to send them "upstream". I don't have a really strong feeling though, if you'd prefer to drop it I can do that.

@alexlarsson
Copy link
Collaborator

I prefer to give the credits in comments and have a more logical structure in our code.

When debugging things, it's really useful to be able to see from the process
output which thing is which. Here, we're using the term "cinit" for the
in-container init.

I looked around on the internets for this - I thought systemd would have a good
implementation, but they don't do the requsite trick with malloc to ensure we
have enough space. nginx does.  Now, I also found
https://tycho.ws/blog/2015/02/setproctitle.html but their implementation
sounded way more complex.

So, going from the nginx code, I heavily edited it to drop Solaris/FreeBSD etc.
Also, to use `xmalloc` instead of their allocator, etc.

This just makes things easier to debug; there's a risk though that it's new
parsing code that is reachable in the suid case by an attacker outside; I'll do
some extra review on this if we agree to take it.
@cgwalters
Copy link
Collaborator Author

Ok, reworked, rebased. ⬆️

bwrap_os_argv = (char **) argv;
bwrap_argc = argc;

bwrap_argv = xmalloc((argc + 1) * sizeof(char *));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get this. We make this copy, but it is never used anywhere. main() still works on the original, which we will later overwrite.

@cgwalters
Copy link
Collaborator Author

OK, reading the nginx code, it looks like they were using the cached argv copy so they could later rewrite argv for the master process, e.g. on my system:

root 28007 0.0 0.0 60740 7924 ? Ss 07:10 0:00 \_ nginx: master process /usr/sbin/nginx

Where /usr/sbin/nginx is the sole original argv, but one might also see other things there.

Not sure whether it's worth it; with just what we have now it's pretty obvious that the initial /usr/bin/bwrap is the outer master.

@alexlarsson
Copy link
Collaborator

@cgwalters Well, if we're not going to do that, the a lot of the work duplicating the env and argv is completely unnecessary, all we need to do is to figure out exactly how large the area to overwrite is.

Otoh, something like that is bound to bite us in the ass eventually when we accidentally dereference an env-var in the cinit code.

@rh-atomic-bot
Copy link

☔ The latest upstream changes (presumably b6370de) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants