@@ -1136,6 +1136,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
c->dataend = ph->p_vaddr + ph->p_filesz;
c->allocend = ph->p_vaddr + ph->p_memsz;
+ c->seal = false;
/* Remember the maximum p_align. */
if (powerof2 (ph->p_align) && ph->p_align > p_align_max)
p_align_max = ph->p_align;
@@ -1169,6 +1170,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
if (ph->p_flags & PF_X)
c->prot |= PROT_EXEC;
#endif
+
+ if (mode & RTLD_NODELETE && ((c->prot & PROT_WRITE) == 0)) {
+ c->seal = true;
+ }
+
break;
case PT_TLS:
@@ -78,6 +78,7 @@ struct loadcmd
ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign;
ElfW(Off) mapoff;
int prot; /* PROT_* bits. */
+ bool seal;
};
@@ -19,6 +19,8 @@
#include <dl-load.h>
+#define SYS_mseal 462
+
/* Map a segment and align it properly. */
static __always_inline ElfW(Addr)
@@ -143,6 +145,10 @@ _dl_map_segments (struct link_map *l, int fd,
== MAP_FAILED))
return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+ if (c->seal) {
+ syscall(SYS_mseal, (void*) mm, map_size, 0);
+ }
+
postmap:
_dl_postprocess_loadcmd (l, header, c);
@@ -636,7 +636,8 @@ dl_open_worker_begin (void *a)
/* Load that object's dependencies. */
_dl_map_object_deps (new, NULL, 0, 0,
- mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
+ mode & (__RTLD_DLOPEN | RTLD_DEEPBIND |
+ __RTLD_AUDIT | RTLD_NODELETE));
/* So far, so good. Now check the versions. */
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
@@ -79,6 +79,8 @@
# define RTLD_TIMING_SET(var, value) (var) = (value)
# define RTLD_TIMING_REF(var) &(var)
+#define SYS_mseal 462
+
static inline void
rtld_timer_start (hp_timing_t *var)
{
@@ -809,7 +811,7 @@ do_preload (const char *fname, struct link_map *main_map, const char *where)
args.str = fname;
args.loader = main_map;
- args.mode = __RTLD_SECURE;
+ args.mode = __RTLD_SECURE | RTLD_NODELETE;
unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
@@ -1214,6 +1216,10 @@ rtld_setup_main_map (struct link_map *main_map)
segment. */
expected_load_address = ((allocend + GLRO(dl_pagesize) - 1)
& ~(GLRO(dl_pagesize) - 1));
+
+ if ((ph->p_flags & PF_W) == 0) {
+ syscall(SYS_mseal, mapstart, expected_load_address - mapstart, 0);
+ }
}
break;
@@ -1636,7 +1642,7 @@ dl_main (const ElfW(Phdr) *phdr,
/* Create a link_map for the executable itself.
This will be what dlopen on "" returns. */
main_map = _dl_new_object ((char *) "", "", lt_executable, NULL,
- __RTLD_OPENEXEC, LM_ID_BASE);
+ __RTLD_OPENEXEC | RTLD_NODELETE, LM_ID_BASE);
assert (main_map != NULL);
main_map->l_phdr = phdr;
main_map->l_phnum = phnum;
@@ -1964,7 +1970,7 @@ dl_main (const ElfW(Phdr) *phdr,
RTLD_TIMING_VAR (start);
rtld_timer_start (&start);
_dl_map_object_deps (main_map, preloads, npreloads,
- state.mode == rtld_mode_trace, 0);
+ state.mode == rtld_mode_trace, RTLD_NODELETE);
rtld_timer_accum (&load_time, start);
}