Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 9 Jun 2019 01:49:42 -0700
From:      Mark Millard <marklmi@yahoo.com>
To:        FreeBSD Hackers <freebsd-hackers@freebsd.org>, FreeBSD PowerPC ML <freebsd-ppc@freebsd.org>
Subject:   Re: crash of 32-bit powerpc -r347549 kernel built via system-clang-8,  _init_tls is where the initial DIAGNOSTICS-reported SIGSEGV happens
Message-ID:  <35F598E5-2400-4768-8B39-BC5F9B051443@yahoo.com>
In-Reply-To: <8F272F27-0BC3-402A-810A-4608162F9EEE@yahoo.com>
References:  <8F272F27-0BC3-402A-810A-4608162F9EEE@yahoo.com>

next in thread | previous in thread | raw e-mail | index | archive | help

So far I've not been able to find the code that is supposed
to establish the value of environ in /sbin/init as matching
the value of arginfo->ps_envstr from the exec_copyout_strings
use by do_execve in the kernel.

Anyone know where to point me to for what I seem to have
missed?

The issue driving the question is having the *sp++ in
_init_tls code below get SIGSEGV on 32-bit FreeBSD when
built via system-clang-8 and devel/powerpc64-binutils:

       sp =3D (Elf_Addr *) environ;
       while (*sp++ !=3D 0)
               ;


The below is relevant detail that I've found.

_start in /sbin/init 's instance of lib/csu/powerpc/crt1.c
calls _init_tls that is from lib/libc/gen/tls.c but first
might assign to environ :

. . .
#include "ignore_init.c"
. . .
void
_start(int argc, char **argv, char **env,
    const struct Struct_Obj_Entry *obj __unused, void (*cleanup)(void),
    struct ps_strings *ps_strings)
{


        handle_argv(argc, argv, env);

        if (ps_strings !=3D (struct ps_strings *)0)
                __ps_strings =3D ps_strings;

        if (&_DYNAMIC !=3D NULL)
                atexit(cleanup);
        else
                _init_tls();

#ifdef GCRT
        atexit(_mcleanup);
        monstartup(&eprol, &etext);
#endif

        handle_static_init(argc, argv, env);
        exit(main(argc, argv, env));
}

lib/csu/common/ignore_init.c has:

char **environ;
. . .
static inline void
handle_argv(int argc, char *argv[], char **env)
{
        const char *s;

        if (environ =3D=3D NULL)
                environ =3D env;
        if (argc > 0 && argv[0] !=3D NULL) {
                __progname =3D argv[0];
                for (s =3D __progname; *s !=3D '\0'; s++) {
                        if (*s =3D=3D '/')
                                __progname =3D s + 1;
                }
        }
}

So _start's char**env argument might be used to assign
environ. But either way I've not managed to find the
binding to the kernel exec_copyout_strings operation.

_init_tls has the *sp++ loop that I referenced earlier:

extern char **environ;

void
_init_tls(void)
{
#ifndef PIC
       Elf_Addr *sp;
       Elf_Auxinfo *aux, *auxp;
       Elf_Phdr *phdr;
       size_t phent, phnum;
       int i;
       void *tls;

       sp =3D (Elf_Addr *) environ;
       while (*sp++ !=3D 0)
               ;
. . .


On the kernel side for invoking /sbin/init is . . .

=46rom /usr/src/sys/sys/imgact.h :

struct image_args {
        char *buf;              /* pointer to string buffer */
        void *bufkva;           /* cookie for string buffer KVA */
        char *begin_argv;       /* beginning of argv in buf */
        char *begin_envv;       /* (interal use only) beginning of envv =
in buf,
                                 * access with =
exec_args_get_begin_envv(). */
        char *endp;             /* current `end' pointer of arg & env =
strings */
        char *fname;            /* pointer to filename of executable =
(system space) */
        char *fname_buf;        /* pointer to optional malloc(M_TEMP) =
buffer */
        int stringspace;        /* space left in arg & env buffer */
        int argc;               /* count of argument strings */
        int envc;               /* count of environment strings */
        int fd;                 /* file descriptor of the executable */
        struct filedesc *fdp;   /* new file descriptor table */
};

do_execve from sys/kern/kern_exec.c has use, including envc
but avoiding begin_envv (via starting from begin_argv):

static int
do_execve(struct thread *td, struct image_args *args, struct mac *mac_p)
{
. . .
        /*
         * Copy out strings (args and env) and initialize stack base.
         */
        stack_base =3D (*p->p_sysent->sv_copyout_strings)(imgp);
               =20

The exec_copyout_strings code (accessed via ->sv_copyout_strings)
does

        stack_base =3D (register_t *)vectp;
               =20
        stringp =3D imgp->args->begin_argv;
        argc =3D imgp->args->argc;
        envc =3D imgp->args->envc;
. . .

        /* a null vector table pointer separates the argp's from the =
envp's */
        suword(vectp++, 0);

        suword(&arginfo->ps_envstr, (long)(intptr_t)vectp);
        suword32(&arginfo->ps_nenvstr, envc);

        /*
         * Fill in environment portion of vector table.
         */
        for (; envc > 0; --envc) {
                suword(vectp++, (long)(intptr_t)destp);
                while (*stringp++ !=3D 0)
                        destp++;
                destp++;
        }

        /* end of vector table is a null pointer */
        suword(vectp, 0);
. . .

(=46rom what I've seen for /sbin/init being invoked, envc=3D=3D0 .)

The use involves struct ps_strings from /usr/src/sys/sys/exec.h :

struct ps_strings {
        char    **ps_argvstr;   /* first of 0 or more argument strings =
*/
        unsigned int ps_nargvstr; /* the number of argument strings */
        char    **ps_envstr;    /* first of 0 or more environment =
strings */
        unsigned int ps_nenvstr; /* the number of environment strings */
};


The initialization of the begin_envv and envc for much of
the code seems to trace back to:

static void
start_init(void *dummy)
{
        struct image_args args;
. . .
        while ((path =3D strsep(&tmp_init_path, ":")) !=3D NULL) {
                if (bootverbose)
                        printf("start_init: trying %s\n", path);

                memset(&args, 0, sizeof(args));
. . .


=3D=3D=3D
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?35F598E5-2400-4768-8B39-BC5F9B051443>