Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Jul 2015 09:18:15 +1000
From:      Jan Mikkelsen <janm@transactionware.com>
To:        Konstantin Belousov <kostikbel@gmail.com>
Cc:        FreeBSD Stable Mailing List <freebsd-stable@freebsd.org>, Karl Denninger <karl@denninger.net>
Subject:   Re: amd64 kernel dynamic linking allows extern references to statics
Message-ID:  <C3196483-BFE4-4F65-A685-0FCF23693391@transactionware.com>
In-Reply-To: <20150715132744.GD2404@kib.kiev.ua>
References:  <13C52D9D-E1E6-4F83-A881-4E867C336B31@transactionware.com> <20150715132744.GD2404@kib.kiev.ua>

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

> On 15 Jul 2015, at 11:27 pm, Konstantin Belousov <kostikbel@gmail.com> =
wrote:
>=20
> On Wed, Jul 15, 2015 at 06:17:20PM +1000, Jan Mikkelsen wrote:
>> Hi,
>>=20
>> (All on 10.2-BETA1.)
>>=20
>> I noticed that the latest patch in the bug =
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D187594 =
<https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D187594>; works on =
amd64 but fails to load zfs.ko on i386 with a symbol not found error.
>>=20
>> Looking at the patch, there is one file that has ???extern int =
zio_use_uma??? to reference a variable that is declared elsewhere as =
???static int zio_use_uma???. To me this obviously should not work. =
However it does work on amd64 but fails on i386.
>>=20
>> Below is a small test case that reproduces the problem. The generated =
kernel module loads on amd64 but fails on i386. On amd64 one compilation =
unit is accessing a static in from another compilation unit by declaring =
the variable ???extern???.=20
>>=20
>> I haven???t looked further to attempt to find the bug. However, it =
looks like a Bad Thing??? to me.
>>=20
>=20
> I am not sure that this is fixable.  Issue is that amd64 modules are
> relinked object files, and they might have unresolved relocations =
against
> local symbols.  Change like the following probably fix your test case,
> but also quite possible would break legitimate local references.
>=20
> diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
> index 021381d..6fa5276 100644
> --- a/sys/kern/link_elf_obj.c
> +++ b/sys/kern/link_elf_obj.c
> @@ -1096,7 +1096,8 @@ link_elf_lookup_symbol(linker_file_t lf, const =
char *name, c_linker_sym_t *sym)
>=20
> 	for (i =3D 0, symp =3D ef->ddbsymtab; i < ef->ddbsymcnt; i++, =
symp++) {
> 		strp =3D ef->ddbstrtab + symp->st_name;
> -		if (symp->st_shndx !=3D SHN_UNDEF && strcmp(name, strp) =
=3D=3D 0) {
> +		if (symp->st_shndx !=3D SHN_UNDEF && strcmp(name, strp) =
=3D=3D 0 &&
> +		    ELF_ST_BIND(symp->st_info) !=3D STB_LOCAL) {
> 			*sym =3D (c_linker_sym_t) symp;
> 			return 0;
> 		}

I don=E2=80=99t know why there could be an unresolved relocation against =
a local symbol. My (admittedly trivial) tests with nm and static =
functions/variables have not led to a =E2=80=9CU=E2=80=9D record. Under =
what circumstances would this happen?

Separately to this is that this behaviour also defeats multiple =
definition checking at link time. Modifying my test slightly to have one =
compilation unit with =E2=80=9Cstatic int testvar=E2=80=9D, one =
compilation unit with =E2=80=9Cint testvar=E2=80=9D and one with =
=E2=80=9Cextern int testvar=E2=80=9D gives nm output like this from the =
.ko file:

00000000000000d0 d testvar
00000000000000c0 d testvar

It is unclear which instance of testvar the =E2=80=9Cextern=E2=80=9D =
declaration used for resolution. Simple testing seems to show it was the =
one with the non-static storage class. However, a piece of code =
depending on the previous resolution to local names could break by the =
addition a file with a name clash. Also, not no =E2=80=9CU=E2=80=9D =
record =E2=80=94 the =E2=80=9Cextern int testvar=E2=80=9D declaration =
has been resolved at this point.

Making both definitions static gives this:

                 U testvar
00000000000000c0 d testvar
00000000000000d0 d testvar

Which testvar will I get at load time? Who knows? Adding a file with a =
static variable with a name clash in another compilation unit can change =
the behaviour of a module.

The big question for me is: under which legitimate case is this feature =
necessary? The downsides seem significant.

Regards,

Jan.




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?C3196483-BFE4-4F65-A685-0FCF23693391>