xfuncs, bb_ funcs and "nofork/noexec" plans
Rob Landley
rob at landley.net
Fri Mar 10 19:57:50 UTC 2006
On Friday 10 March 2006 4:18 am, Denis Vlasenko wrote:
> Hi Rob,
>
> I was thinking about changes needed to implement nofork/noexec
> for some trivial applets.
>
> Conditions for applet to be eligible for it are as follows:
>
> * Do not expect your bss data to be pre-zeroed for you
> (it will be, but on first invocation only)
Actually, this is one advantage of the merging it all into the structure like
we discussed earlier. We can memset() the sucker.
> * Do not exit, ever. You must return from <applet>_main()
There's the setjmp/longjmp work mentioned earlier. Right now anything that
uses bb_xopen() or perror_msg_and_die()...
> * Do not leave malloc'ed blocks unfreed
Part of setjmp/longjmp instead of fork/exit is that our allocator can chain
'em and we can free back to the last checkpoint.
> * Do not leak file descriptors
> (did I forget something?)
mmap(), environment variables, signals...
It's not a trivial problem.
> Many simpler applets typically do not qualify just because
> of few calls to xfuncs. It would be useful if we will have
> xfunc equivalent which prints error message, just like xfunc
> does, but instead of exiting returns an error.
>
> Like this:
>
> void *bb_malloc(size_t size)
> {
> void *ptr = malloc(size);
> if (ptr == NULL && size != 0)
> bb_error_msg(bb_msg_memory_exhausted);
> return ptr;
> }
The point of these functions is so the caller doesn't have to check for
errors. If you return, anybody trying to use the returned value will
segfault.
> What do you think?
>
> Another small matter - doesn't "x" means "will yell & exit on error"
> in the name of xfunc? Do bb_ functions never exit? We'd better enforce
> this (or similar) rule in order to make checking above four-point
> list easier.
The above list isn't sufficient. We have to audit the suckers one by one and
understand what they're doing, and mark them as NOFORK in applets.h.
> Example:
>
> void bb_lookup_host(struct sockaddr_in *s_in, const char *host)
> {
> struct hostent *he;
>
> memset(s_in, 0, sizeof(struct sockaddr_in));
> s_in->sin_family = AF_INET;
> he = xgethostbyname(host);
> memcpy(&(s_in->sin_addr), he->h_addr_list[0], he->h_length);
> }
>
> This is a bb_ function, but it calls a xfunc (xgethostbyname) which
> can exit:
>
> struct hostent *xgethostbyname(const char *name)
> {
> struct hostent *retval;
>
> if ((retval = gethostbyname(name)) == NULL)
> bb_herror_msg_and_die("%s", name);
>
> return retval;
> }
I know this.
> How would one know that his program can exit here (taken from ftpgetput.c):
>
> server->s_in = &s_in;
> bb_lookup_host(&s_in, argv[optind]);
> s_in.sin_port = bb_lookup_port(port, "tcp", 21);
> if (verbose_flag) {
> printf("Connecting to %s[%s]:%d\n",
> argv[optind], inet_ntoa(s_in.sin_addr),
> ntohs(s_in.sin_port)); }
>
> It's not immediately obvious!
You have to be familiar with the code. And it's done that way to save space.
> Will you accept patches which fix such bb_ fuctions?
It's not a "fix" if it's bigger.
> What name would you
> prefer? x_lookup_host? xlookup_host?
> --
> vda
Rob
--
Never bet against the cheap plastic solution.
More information about the busybox
mailing list