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