Commit 43adf844 authored by peterz@infradead.org's avatar peterz@infradead.org Committed by Peter Zijlstra
Browse files

futex: FLAGS_STRICT



The current semantics for futex_wake() are a bit loose, specifically
asking for 0 futexes to be woken actually gets you 1.

Adding a !nr check to sys_futex_wake() makes that it would return 0
for unaligned futex words, because that check comes in the shared
futex_wake() function. Adding the !nr check there, would affect the
legacy sys_futex() semantics.

Hence frob a flag :-(

Suggested-by: default avatarAndré Almeida <andrealmeid@igalia.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20230921105248.048643656@noisy.programming.kicks-ass.net
parent 9f6c532f
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -17,25 +17,26 @@
 * Futex flags used to encode options to functions and preserve them across
 * restarts.
 */
#define FLAGS_SIZE_8		0x00
#define FLAGS_SIZE_16		0x01
#define FLAGS_SIZE_32		0x02
#define FLAGS_SIZE_64		0x03
#define FLAGS_SIZE_8		0x0000
#define FLAGS_SIZE_16		0x0001
#define FLAGS_SIZE_32		0x0002
#define FLAGS_SIZE_64		0x0003

#define FLAGS_SIZE_MASK		0x03
#define FLAGS_SIZE_MASK		0x0003

#ifdef CONFIG_MMU
# define FLAGS_SHARED		0x10
# define FLAGS_SHARED		0x0010
#else
/*
 * NOMMU does not have per process address space. Let the compiler optimize
 * code away.
 */
# define FLAGS_SHARED		0x00
# define FLAGS_SHARED		0x0000
#endif
#define FLAGS_CLOCKRT		0x20
#define FLAGS_HAS_TIMEOUT	0x40
#define FLAGS_NUMA		0x80
#define FLAGS_CLOCKRT		0x0020
#define FLAGS_HAS_TIMEOUT	0x0040
#define FLAGS_NUMA		0x0080
#define FLAGS_STRICT		0x0100

/* FUTEX_ to FLAGS_ */
static inline unsigned int futex_to_flags(unsigned int op)
+1 −1
Original line number Diff line number Diff line
@@ -333,7 +333,7 @@ SYSCALL_DEFINE4(futex_wake,
	if (!futex_validate_input(flags, mask))
		return -EINVAL;

	return futex_wake(uaddr, flags, nr, mask);
	return futex_wake(uaddr, FLAGS_STRICT | flags, nr, mask);
}

#ifdef CONFIG_COMPAT
+3 −0
Original line number Diff line number Diff line
@@ -155,6 +155,9 @@ int futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
	if (unlikely(ret != 0))
		return ret;

	if ((flags & FLAGS_STRICT) && !nr_wake)
		return 0;

	hb = futex_hash(&key);

	/* Make sure we really have tasks to wakeup */