elf: Refine direct extern access diagnostics to protected symbol

Refine commit 349b0441dab375099b1d7f6909c1742286a67da9:

1. Copy relocations for extern protected data do not work properly,
regardless whether GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS is used.
It makes sense to produce a warning unconditionally.

2. Non-zero value of an undefined function symbol may break pointer
equality, but may be benign in many cases (many programs don't take the
address in the shared object then compare it with the address in the
executable).  Reword the diagnostic to be clearer.

3. Remove the unneeded condition !(undef_map->l_1_needed &
GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS). If the executable does
not not have GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS (can only
occur in error cases), the diagnostic should be emitted as well.

When the defining shared object has
GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS, report an error to apply
the intended enforcement.
This commit is contained in:
Fangrui Song 2022-06-14 13:07:27 -07:00
parent 876cdf517d
commit 7374c02b68
1 changed files with 27 additions and 23 deletions

View File

@ -26,29 +26,33 @@ _dl_check_protected_symbol (const char *undef_name,
const struct link_map *map, const struct link_map *map,
int type_class) int type_class)
{ {
if (undef_map != NULL if (undef_map == NULL || undef_map->l_type != lt_executable)
&& undef_map->l_type == lt_executable return;
&& !(undef_map->l_1_needed
& GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS) if (type_class & ELF_RTYPE_CLASS_COPY)
&& (map->l_1_needed /* Disallow copy relocations in executable against protected
& GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS)) data symbols in a shared object which needs indirect external
{ access. */
if ((type_class & ELF_RTYPE_CLASS_COPY)) _dl_error_printf ("warning: copy relocation against non-copyable "
/* Disallow copy relocations in executable against protected "protected symbol `%s' in `%s'\n",
data symbols in a shared object which needs indirect external undef_name, map->l_name);
access. */ else if ((type_class & ELF_RTYPE_CLASS_PLT) && ref->st_value != 0
_dl_signal_error (0, map->l_name, undef_name, && ref->st_shndx == SHN_UNDEF)
N_("copy relocation against non-copyable protected symbol")); /* Disallow non-zero symbol values of undefined symbols in
else if (ref->st_value != 0 executable, which are used as the function pointer, against
&& ref->st_shndx == SHN_UNDEF protected function symbols in a shared object with indirect
&& (type_class & ELF_RTYPE_CLASS_PLT)) external access. */
/* Disallow non-zero symbol values of undefined symbols in _dl_error_printf (
executable, which are used as the function pointer, against "warning: direct reference to "
protected function symbols in a shared object with indirect "protected function `%s' in `%s' may break pointer equality\n",
external access. */ undef_name, map->l_name);
_dl_signal_error (0, map->l_name, undef_name, else
N_("non-canonical reference to canonical protected function")); return;
}
if (map->l_1_needed & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS)
_dl_signal_error (
0, map->l_name, undef_name,
N_ ("error due to GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS"));
} }
#endif /* _DL_PROTECTED_H */ #endif /* _DL_PROTECTED_H */