linux(4): Allow musl brand to use FUTEX_REQUEUE op.

Initial patch from submitter was adapted by me to prevent unconditional
FUTEX_REQUEUE use.

PR:			255947
Submitted by:		Philippe Michaud-Boudreault
Differential Revision:	https://reviews.freebsd.org/D30332
This commit is contained in:
Dmitry Chagin 2021-07-20 14:39:20 +03:00
parent 4c361d7a5a
commit cf8d74e3fe
5 changed files with 43 additions and 20 deletions

View File

@ -991,7 +991,8 @@ static Elf64_Brandinfo linux_muslbrand = {
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
.brand_note = &linux64_brandnote,
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE |
LINUX_BI_FUTEX_REQUEUE
};
Elf64_Brandinfo *linux_brandlist[] = {

View File

@ -1154,7 +1154,8 @@ static Elf32_Brandinfo linux_muslbrand = {
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
.brand_note = &linux32_brandnote,
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE |
LINUX_BI_FUTEX_REQUEUE
};
Elf32_Brandinfo *linux_brandlist[] = {

View File

@ -30,6 +30,11 @@
#include <sys/queue.h>
/*
* Private Brandinfo flags
*/
#define LINUX_BI_FUTEX_REQUEUE 0x01000000
/*
* poll()
*/

View File

@ -46,6 +46,7 @@ __KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $")
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/imgact.h>
#include <sys/imgact_elf.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/lock.h>
@ -234,6 +235,7 @@ struct linux_futex_args {
struct timespec *ts;
uint32_t *uaddr2;
uint32_t val3;
bool val3_compare;
struct timespec kts;
};
@ -648,6 +650,7 @@ static int
linux_futex(struct thread *td, struct linux_futex_args *args)
{
struct linux_pemuldata *pem;
struct proc *p;
if (args->op & LINUX_FUTEX_PRIVATE_FLAG) {
args->flags = 0;
@ -695,6 +698,33 @@ linux_futex(struct thread *td, struct linux_futex_args *args)
return (linux_futex_wake(td, args));
case LINUX_FUTEX_REQUEUE:
/*
* Glibc does not use this operation since version 2.3.3,
* as it is racy and replaced by FUTEX_CMP_REQUEUE operation.
* Glibc versions prior to 2.3.3 fall back to FUTEX_WAKE when
* FUTEX_REQUEUE returned EINVAL.
*/
pem = pem_find(td->td_proc);
if ((pem->flags & LINUX_XDEPR_REQUEUEOP) == 0) {
linux_msg(td, "unsupported FUTEX_REQUEUE");
pem->flags |= LINUX_XDEPR_REQUEUEOP;
LIN_SDT_PROBE0(futex, linux_futex,
deprecated_requeue);
}
/*
* The above is true, however musl libc does make use of the
* futex requeue operation, allow operation for brands which
* set LINUX_BI_FUTEX_REQUEUE bit of Brandinfo flags.
*/
p = td->td_proc;
Elf_Brandinfo *bi = p->p_elf_brandinfo;
if (bi == NULL || ((bi->flags & LINUX_BI_FUTEX_REQUEUE)) == 0)
return (EINVAL);
args->val3_compare = false;
/* FALLTHROUGH */
case LINUX_FUTEX_CMP_REQUEUE:
LIN_SDT_PROBE5(futex, linux_futex, debug_cmp_requeue,
args->uaddr, args->val, args->val3, args->uaddr2,
@ -749,22 +779,6 @@ linux_futex(struct thread *td, struct linux_futex_args *args)
}
return (ENOSYS);
case LINUX_FUTEX_REQUEUE:
/*
* Glibc does not use this operation since version 2.3.3,
* as it is racy and replaced by FUTEX_CMP_REQUEUE operation.
* Glibc versions prior to 2.3.3 fall back to FUTEX_WAKE when
* FUTEX_REQUEUE returned EINVAL.
*/
pem = pem_find(td->td_proc);
if ((pem->flags & LINUX_XDEPR_REQUEUEOP) == 0) {
linux_msg(td, "unsupported FUTEX_REQUEUE");
pem->flags |= LINUX_XDEPR_REQUEUEOP;
LIN_SDT_PROBE0(futex, linux_futex,
deprecated_requeue);
}
return (EINVAL);
case LINUX_FUTEX_WAIT_REQUEUE_PI:
/* not yet implemented */
pem = pem_find(td->td_proc);
@ -921,7 +935,7 @@ linux_futex_requeue(struct thread *td, struct linux_futex_args *args)
error);
return (error);
}
if (val != args->val3) {
if (args->val3_compare == true && val != args->val3) {
LIN_SDT_PROBE2(futex, linux_futex,
debug_cmp_requeue_value_neq, args->val, val);
LINUX_CTR2(sys_futex, "CMP_REQUEUE val 0x%x != uval 0x%x",
@ -1016,6 +1030,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
.ts = NULL,
.uaddr2 = args->uaddr2,
.val3 = args->val3,
.val3_compare = true,
};
struct l_timespec lts;
int error;

View File

@ -1099,7 +1099,8 @@ static Elf32_Brandinfo linux_muslbrand = {
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
.brand_note = &linux_brandnote,
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE |
LINUX_BI_FUTEX_REQUEUE
};
Elf32_Brandinfo *linux_brandlist[] = {