@@ -28,6 +28,9 @@ _dl_call_libc_early_init (struct link_map *libc_map, _Bool initial)
/* There is nothing to do if we did not actually load libc.so. */
if (libc_map == NULL)
return;
+#ifdef DLCONF
+ libc_map->l_crossvisible = true;
+#endif /* DLCONF */
const ElfW(Sym) *sym
= _dl_lookup_direct (libc_map, "__libc_early_init",
@@ -662,6 +662,15 @@ _dl_close_worker (struct link_map *map, bool force)
free ((char *) imap->l_origin);
free (imap->l_reldeps);
+#ifdef DLCONF
+ struct dep_list *depele = imap->l_crossdep;
+ while (depele)
+ {
+ struct dep_list *depele_next = depele->next;
+ free(depele);
+ depele = depele_next;
+ }
+#endif
/* Print debugging message. */
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
@@ -153,6 +153,11 @@ _dl_map_object_deps (struct link_map *map,
/* No loaded object so far. */
nlist = 0;
+#ifdef DLCONF
+ if (map->l_type == lt_executable)
+ map->l_crossvisible = true;
+#endif
+
/* First load MAP itself. */
preload (known, &nlist, map);
@@ -240,6 +245,22 @@ _dl_map_object_deps (struct link_map *map,
}
else
dep = args.aux;
+#ifdef DLCONF
+ if (dep->l_crossns != runp->map->l_crossns)
+ {
+ struct dep_list *depele
+ = malloc (sizeof (struct dep_list));
+ if (depele == NULL)
+ {
+ _dl_signal_error (
+ ENOMEM, map->l_name, NULL,
+ N_ ("cannot allocate cross dependency list"));
+ }
+ depele->map = dep;
+ depele->next = runp->map->l_crossdep;
+ runp->map->l_crossdep = depele;
+ }
+#endif /* DLCONF */
if (! dep->l_reserved)
{
@@ -1917,6 +1917,7 @@ _dl_map_object (struct link_map *loader, const char *name,
assert (nsid < GL(dl_nns));
#ifdef DLCONF
+ size_t crossns = 0;
bool try_default = true;
char full_path_buff[PATH_MAX];
const char *full_path = NULL;
@@ -1939,7 +1940,8 @@ _dl_map_object (struct link_map *loader, const char *name,
}
}
- char *cached = dlconf_get_cached_path (full_path, name, &try_default);
+ char *cached = dlconf_get_cached_path(full_path, name, &crossns, &try_default);
+ bool name_is_libc = strcmp (name, LIBC_SO) == 0 || strcmp (name, LD_SO) == 0;
#endif /* DLCONF */
@@ -1951,6 +1953,25 @@ _dl_map_object (struct link_map *loader, const char *name,
yet been opened. */
if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0))
continue;
+
+#ifdef DLCONF
+ if (cached != NULL)
+ {
+ /* ld.so and libc.so can always by found regardless of the section in
+ * which they are located. So crossns check is performed for all
+ * other libraries */
+ if (!name_is_libc)
+ {
+ if (l->l_crossns != crossns)
+ continue;
+
+ /* Here we compare the full path of the library */
+ if (strcmp (cached, l->l_name) != 0)
+ continue;
+ }
+ }
+#endif /* DLCONF */
+
if (!_dl_name_match_p (name, l))
{
const char *soname;
@@ -2232,8 +2253,13 @@ _dl_map_object (struct link_map *loader, const char *name,
}
void *stack_end = __libc_stack_end;
- return _dl_map_object_from_fd (name, origname, fd, &fb, realname, loader,
+ l = _dl_map_object_from_fd (name, origname, fd, &fb, realname, loader,
type, mode, &stack_end, nsid);
+#ifdef DLCONF
+ if (l != NULL)
+ l->l_crossns = dlconf_get_section_id(l->l_name);
+#endif
+ return l;
}
struct add_path_state
@@ -31,6 +31,9 @@
#include <atomic.h>
#include <elf_machine_sym_no_match.h>
+#ifdef DLCONF
+#include <dlconf.h>
+#endif
#include <assert.h>
#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
@@ -357,6 +360,27 @@ do_lookup_x (const char *undef_name, unsigned int new_hash,
{
const struct link_map *map = list[i]->l_real;
+#ifdef DLCONF
+ if (undef_map != NULL && !map->l_crossvisible
+ && map->l_crossns != undef_map->l_crossns)
+ {
+ bool found = false;
+ struct dep_list *dep = NULL;
+
+ for (dep = undef_map->l_crossdep; dep; dep = dep->next)
+ {
+ if (dep->map == map)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ continue;
+ }
+#endif /* DLCONF */
+
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
if (map == skip)
continue;
@@ -98,6 +98,11 @@ _dl_new_object (char *realname, const char *libname, int type,
new->l_real = new;
new->l_symbolic_searchlist.r_list = (struct link_map **) ((char *) (new + 1)
+ audit_space);
+#ifdef DLCONF
+ new->l_crossns = 0;
+ new->l_crossdep = NULL;
+ new->l_crossvisible = false;
+#endif
new->l_libname = newname
= (struct libname_list *) (new->l_symbolic_searchlist.r_list + 1);
@@ -588,6 +588,7 @@ dl_open_worker_begin (void *a)
{
_dl_signal_error (EINVAL, file, NULL, N_ ("prohibited loading path"));
}
+ new->l_crossns = dlconf_get_section_id(new->l_name);
#endif /* DLCONF */
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
@@ -176,6 +176,7 @@ static int _print_conf_dat_tree (const struct conf_dat_entry_with_children *tree
_dl_printf("%s%s%s%s\n", prefix, conn, tree->children[i]->name, addon);
_dl_printf("%s%s%sisolation: %d\n", prefix, conn2, conn3, tree->children[i]->conf_dat_entry->isolation);
_dl_printf("%s%s%sdlopen_isolation: %d\n", prefix, conn2, conn3, tree->children[i]->conf_dat_entry->dlopen_isolation);
+ _dl_printf("%s%s%ssection_id: %d\n", prefix, conn2, conn3, tree->children[i]->conf_dat_entry->section_id);
list = tree->children[i]->conf_dat_entry->caches;
_print_list(list, "caches", prefix, conn2, conn3);
@@ -193,6 +194,7 @@ static int print_conf_dat_tree (const struct conf_dat_entry_with_children *centr
_dl_printf("/\n");
_dl_printf("| isolation: %d\n", centry->conf_dat_entry->isolation);
_dl_printf("| dlopen_isolation: %d\n", centry->conf_dat_entry->dlopen_isolation);
+ _dl_printf("| section_id: %d\n", centry->conf_dat_entry->section_id);
_print_list(centry->conf_dat_entry->caches, "caches", "| ", "", "");
_print_list(centry->conf_dat_entry->dlopen_paths, "dlopen_paths", "| ", "", "");
@@ -263,3 +265,4 @@ exit:
close(fd);
}
+
@@ -15,6 +15,7 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include "ldsodefs.h"
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
@@ -52,6 +53,7 @@ struct cache_info {
struct string_list *caches;
bool isolation;
bool dlopen_isolation;
+ int32_t section_id;
struct cache_info *next;
};
@@ -64,6 +66,7 @@ struct node {
int32_t caches_idx;
int32_t isolation;
int32_t dlopen_isolation;
+ int32_t section_id;
struct node **children;
int32_t children_count;
};
@@ -123,6 +126,7 @@ struct section {
struct section_string_list *paths;
struct section_string_list *caches;
struct section_string_list *dlopen_paths;
+ int32_t id;
bool isolation;
bool dlopen_isolation;
bool processing; /* Field for cycle detection */
@@ -365,6 +369,7 @@ static void print_cinfo (struct cache_info *cinfo)
_dl_debug_printf(" isolation: %d\n", cinfo->isolation);
_dl_debug_printf(" dlopen_isolation: %d\n", cinfo->dlopen_isolation);
+ _dl_debug_printf(" section_id: %d\n", cinfo->section_id);
cinfo = cinfo->next;
}
@@ -1138,14 +1143,18 @@ static int add_new_cinfo(struct cache_info **cinfo,
struct section_string_list *caches,
struct section_string_list *dlopen_paths,
bool isolation,
- bool dlopen_isolation)
+ bool dlopen_isolation,
+ int32_t *section_id)
{
struct section_string_list *l;
const struct section_string_list *cur_path = paths;
- if (cinfo == NULL)
+ if (cinfo == NULL || section_id == NULL)
return DLCONF_ERR_INVAL;
+ if (cur_path != NULL)
+ (*section_id)++;
+
/* If more paths than one were defined in the section, we need to create more
objects because one cache_info object can store only one path (for later
optimizations). */
@@ -1179,6 +1188,7 @@ static int add_new_cinfo(struct cache_info **cinfo,
cinfo_new->dlopen_paths = dlopen_paths_new;
cinfo_new->isolation = isolation;
cinfo_new->dlopen_isolation = dlopen_isolation;
+ cinfo_new->section_id = *section_id;
cinfo_new->next = NULL;
if (*cinfo == NULL)
@@ -1231,6 +1241,7 @@ static int add_new_cinfo(struct cache_info **cinfo,
static int convert_sections_to_cache_info(struct sections *sections, struct cache_info **cache_info)
{
int result = DLCONF_ERR_OK;
+ int32_t section_id = -1;
for (size_t i = 0; i < sections->count; i++)
{
struct section *section = sections->sections[i];
@@ -1242,10 +1253,12 @@ static int convert_sections_to_cache_info(struct sections *sections, struct cach
section->caches,
section->dlopen_paths,
section->isolation,
- section->dlopen_isolation)) != DLCONF_ERR_OK)
+ section->dlopen_isolation,
+ §ion_id)) != DLCONF_ERR_OK)
{
goto exit;
}
+ section->id = section_id;
}
exit:
if (result != DLCONF_ERR_OK)
@@ -1397,6 +1410,7 @@ static int parse_paraini (const char *content, size_t content_len, struct sectio
key_len--;
key_len++;
+
if (key_len == 0)
continue;
@@ -1724,6 +1738,7 @@ static int insert_to_trie (struct node *base_node, char *token, const struct cac
new_child->dlopen_isolation = base_node->dlopen_isolation;
new_child->caches_idx = base_node->caches_idx;
new_child->dlopen_paths_idx = base_node->dlopen_paths_idx;
+ new_child->section_id = base_node->section_id;
if ((result = insert_to_trie(new_child, new_token, cinfo, saveptr)) != DLCONF_ERR_OK)
{
@@ -1744,6 +1759,7 @@ static int insert_to_trie (struct node *base_node, char *token, const struct cac
new_child->isolation = cinfo->isolation;
new_child->dlopen_isolation = cinfo->dlopen_isolation;
+ new_child->section_id = cinfo->section_id;
}
exit:
@@ -1789,6 +1805,7 @@ static struct node *convert_to_trie (const struct cache_info *cinfo)
base_node->isolation = 0;
base_node->dlopen_isolation = 0;
base_node->dlopen_paths_idx = -1;
+ base_node->section_id = -1;
base_node->caches_idx = -1;
while (cinfo != NULL)
@@ -1809,6 +1826,7 @@ static struct node *convert_to_trie (const struct cache_info *cinfo)
}
base_node->isolation = cinfo->isolation;
base_node->dlopen_isolation = cinfo->dlopen_isolation;
+ base_node->section_id = cinfo->section_id;
}
else
{
@@ -1987,6 +2005,7 @@ static int _save_trie (const struct node *node, int fd, int32_t *name_offset, in
write_or_return(fd, &node->isolation, sizeof(node->isolation));
write_or_return(fd, &node->dlopen_isolation, sizeof(node->dlopen_isolation));
+ write_or_return(fd, &node->section_id, sizeof(node->section_id));
*name_offset += strlen(node->name)+1;
@@ -2174,7 +2193,7 @@ int load_conf_dat (const char *path)
return 0;
}
-static struct conf_dat_entry *dlconf_find_proper_conf_dat_entry (const char *path)
+struct conf_dat_entry *dlconf_find_proper_conf_dat_entry (const char *path)
{
if (__glibc_unlikely(conf_data == NULL))
{
@@ -2246,6 +2265,7 @@ struct conf_dat_entry *dlconf_read_one_conf_dat_entry (void *file, int start)
node->isolation = rnode->isolation;
node->dlopen_isolation = rnode->dlopen_isolation;
+ node->section_id = rnode->section_id;
node->dlopen_paths = NULL;
node->caches = NULL;
@@ -2347,7 +2367,48 @@ bool dlconf_allowed_dlopen (const char *file, const void *caller_dlopen)
return false;
}
-char *dlconf_get_cached_path(const char *name, const char *libname, bool *try_default)
+size_t dlconf_get_section_id(const char *name)
+{
+ size_t result;
+ struct conf_dat_entry *centry;
+
+ if (name == NULL)
+ return 0;
+
+ centry = dlconf_find_proper_conf_dat_entry(name);
+
+ if (centry == NULL)
+ return 0;
+
+ result = centry->section_id;
+ dlconf_free_string_list(centry->caches, false);
+ dlconf_free_string_list(centry->dlopen_paths, false);
+ free(centry);
+ return result;
+}
+
+bool dlconf_have_access(const char *name, const char *libname)
+{
+ struct conf_dat_entry *centry = dlconf_find_proper_conf_dat_entry(name);
+ bool result = false;
+
+ if (centry)
+ {
+ char *cached = dlconf_find_cached_path (libname, centry->caches);
+ if (cached)
+ {
+ result = true;
+ free (cached);
+ }
+
+ dlconf_free_string_list (centry->caches, false);
+ dlconf_free_string_list (centry->dlopen_paths, false);
+ free (centry);
+ }
+ return result;
+}
+
+char *dlconf_get_cached_path(const char *name, const char *libname, size_t *crossns, bool *try_default)
{
struct conf_dat_entry *centry;
char *cached;
@@ -2374,6 +2435,20 @@ char *dlconf_get_cached_path(const char *name, const char *libname, bool *try_de
cached = dlconf_find_cached_path(libname, centry->caches);
+ if (cached != NULL)
+ {
+ struct conf_dat_entry *libcentry = dlconf_find_proper_conf_dat_entry (cached);
+
+ if (libcentry)
+ {
+ if (crossns != NULL)
+ *crossns = libcentry->section_id;
+
+ dlconf_free_string_list (libcentry->caches, false);
+ dlconf_free_string_list (libcentry->dlopen_paths, false);
+ free (libcentry);
+ }
+ }
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
{
if (cached != NULL)
@@ -2439,3 +2514,4 @@ int dlconf_generate_conf_dat (void)
return result;
}
+
@@ -69,6 +69,7 @@ struct conf_dat_raw_entry {
int32_t dlopen_paths_offset;
int32_t isolation;
int32_t dlopen_isolation;
+ int32_t section_id;
};
/*
@@ -85,6 +86,7 @@ struct string_list {
struct conf_dat_entry {
bool isolation;
bool dlopen_isolation;
+ int32_t section_id;
struct string_list *caches;
struct string_list *dlopen_paths;
@@ -110,7 +112,8 @@ struct conf_dat_entry {
#define DLCONF_DLPATHS_START_OFFSET offsetof(struct conf_dat_raw_entry, dlopen_paths_offset)
#define DLCONF_ISO_OFFSET offsetof(struct conf_dat_raw_entry, isolation)
#define DLCONF_DLOPEN_ISO_OFFSET offsetof(struct conf_dat_raw_entry, dlopen_isolation)
-#define DLCONF_NODE_FIELDS_COUNT 7
+#define DLCONF_SECTION_ID_OFFSET offsetof(struct conf_dat_raw_entry, section_id)
+#define DLCONF_NODE_FIELDS_COUNT 8
#define DLCONF_NODE_SIZE_IN_BYTES DLCONF_NODE_FIELDS_COUNT*sizeof(int32_t)
/*
@@ -155,7 +158,7 @@ extern bool dlconf_allowed_dlopen (const char *file, const void *caller_dlopen)
* name argument is a program name with a path, for which the library is loading.
* try_default will be set to true or false depending on whether isolation is true or false.
*/
-extern char *dlconf_get_cached_path(const char *name, const char *libname, bool *try_default) attribute_hidden;
+extern char *dlconf_get_cached_path(const char *name, const char *libname, size_t *crossns, bool *try_default) attribute_hidden;
/*
* Generate ldconfig.dat from /etc/ldconfig.conf and /etc/ldconfig.conf.d/* files
@@ -172,4 +175,8 @@ extern void dlconf_print_conf_dat (void) attribute_hidden;
*/
char *dlconf_get_executable_path (char *buff, size_t bufflen) attribute_hidden;
+struct conf_dat_entry *dlconf_find_proper_conf_dat_entry (const char *path);
+
+size_t dlconf_get_section_id(const char *name);
+bool dlconf_have_access(const char *name, const char *libname);
#endif /* _DLCONF_H */
@@ -1374,6 +1374,9 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_starting_up = 1;
#endif
+#ifdef DLCONF
+ GL(dl_rtld_map).l_crossvisible = true;
+#endif /* DLCONF */
const char *ld_so_name = _dl_argv[0];
if (*user_entry == (ElfW(Addr)) ENTRY_POINT)
{
@@ -1670,6 +1673,13 @@ dl_main (const ElfW(Phdr) *phdr,
This will be what dlopen on "" returns. */
main_map = _dl_new_object ((char *) "", "", lt_executable, NULL,
__RTLD_OPENEXEC, LM_ID_BASE);
+#ifdef DLCONF
+ char full_path_buff[PATH_MAX];
+ const char *full_path = NULL;
+ full_path = dlconf_get_executable_path(full_path_buff, sizeof(full_path_buff));
+ main_map->l_crossns = dlconf_get_section_id(full_path);
+#endif /* DLCONF */
+
assert (main_map != NULL);
main_map->l_phdr = phdr;
main_map->l_phnum = phnum;
@@ -71,6 +71,17 @@ struct r_scope_elem
unsigned int r_nlist;
};
+#ifdef DLCONF
+struct dep_list {
+ struct link_map *map;
+ struct dep_list *next;
+};
+
+struct ns_list {
+ size_t ns;
+ struct ns_list *next;
+};
+#endif // DLCONF
/* Structure to record search path and allocation mechanism. */
struct r_search_path_struct
@@ -114,6 +125,13 @@ struct link_map
/* Number of the namespace this link map belongs to. */
Lmid_t l_ns;
+#ifdef DLCONF
+ size_t l_crossns; /* Identifier of cross-namespace */
+ struct dep_list *l_crossdep; /* List of direct dependencies */
+ bool l_crossvisible; /* Flag indication whether a given object is visible
+ from all cross-namespaces */
+#endif /* DLCONF */
+
struct libname_list *l_libname;
/* Indexed pointers to dynamic section.
[0,DT_NUM) are indexed by the processor-independent tags.