* hack around deficiencies in prctl() PR_SET_MM_*
This commit is contained in:
parent
ad191df836
commit
14ee72b7d8
|
@ -336,15 +336,33 @@ int rename_process(const char name[]) {
|
|||
|
||||
/* Now, let's tell the kernel about this new memory */
|
||||
if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
|
||||
log_debug_errno(errno, "PR_SET_MM_ARG_START failed, proceeding without: %m");
|
||||
(void) munmap(nn, nn_size);
|
||||
goto use_saved_argv;
|
||||
}
|
||||
/* HACK: prctl() API is kind of dumb on this point. The existing end address may already be
|
||||
* below the desired start address, in which case the kernel may have kicked this back due
|
||||
* to a range-check failure (see linux/kernel/sys.c:validate_prctl_map() to see this in
|
||||
* action). The proper solution would be to have a prctl() API that could set both start+end
|
||||
* simultaneously, or at least let us query the existing address to anticipate this condition
|
||||
* and respond accordingly. For now, we can only guess at the cause of this failure and try
|
||||
* a workaround--which will briefly expand the arg space to something potentially huge before
|
||||
* resizing it to what we want. */
|
||||
log_debug_errno(errno, "PR_SET_MM_ARG_START failed, attempting PR_SET_MM_ARG_END hack: %m");
|
||||
|
||||
/* And update the end pointer to the new end, too. If this fails, we don't really know what to do, it's
|
||||
* pretty unlikely that we can rollback, hence we'll just accept the failure, and continue. */
|
||||
if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
|
||||
log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
|
||||
if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) {
|
||||
log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m");
|
||||
(void) munmap(nn, nn_size);
|
||||
goto use_saved_argv;
|
||||
}
|
||||
|
||||
if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
|
||||
log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m");
|
||||
goto use_saved_argv;
|
||||
}
|
||||
} else {
|
||||
/* And update the end pointer to the new end, too. If this fails, we don't really know what
|
||||
* to do, it's pretty unlikely that we can rollback, hence we'll just accept the failure,
|
||||
* and continue. */
|
||||
if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
|
||||
log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
|
||||
}
|
||||
|
||||
if (mm)
|
||||
(void) munmap(mm, mm_size);
|
||||
|
|
Loading…
Reference in a new issue