Thread (1 message) 1 message, 1 author, 2018-01-24

[PATCH 07/11] signal/arm64: Document conflicts with SI_USER and SIGFPE, SIGTRAP, SIGBUS

From: Eric W. Biederman <hidden>
Date: 2018-01-24 21:30:00
Also in: linux-arch, lkml

Possibly related (same subject, not in this thread)

Russell King - ARM Linux [off-list ref] writes:
On Wed, Jan 17, 2018 at 10:45:10AM -0600, Eric W. Biederman wrote:
quoted
Russell King - ARM Linux [off-list ref] writes:
quoted
From your description there still seems to be an association with an
instruction so I don't know if I would really call the signal
asynchronous.  It sounds like the exception is delayed and not
asynchronous.
Traps can only be passed from ARM coprocessors by a coprocessor refusing
to execute an instruction.  That's what happens in this case - the VFP
gets offered an instruction to execute.  It accepts it, and the CPU
continues, leaving the VFP to execute its instruction independently.  If
this instruction generates an error, then nothing happens at this point.

That error remains pending until the CPU offers the coprocessor the next
VFP instruction, which it refuses.  That causes an undefined instruction
exception, and we trap into the kernel VFP code which reads the VFP
status and works out what needs to be done.

What this means is that if you execute a VFP instruction, wait 10 minutes
and then execute another VFP instruction, if the first VFP instruction
raised an exception, you'll get to hear about it 10 minutes later.

You can use whatever weasel words you want to describe that situation,
my choice is "asynchronous", your choice is "delayed".  However, it is
clearly not "synchronous", and arguing that we should report something
synchronously that is not reported to _us_ synchronously (where
synchronous means "at the same time") is IMHO daft.

So, let's take an example:

	installs SIGFPE handler
	..fp instructions.. one of which raises an exception
	returns to main loop
	main loop blocks all signals while it sets stuff up
	calls ppoll()

In the synchronous SIGFPE delivery case, the SIGFPE handler will be
called when the exception is generated in the FP code, and delivered
at that time.  The fact that the main loop blocks all signals happens
later, so the users handler gets called as one expects.

In the VFP case, however, the FP instructions towards the end may not
end up causing the exception to be signalled until sometime later,
and as I've already explained, that may be the result of a C library
function accessing the VFP registers.  This could well end up trying
to deliver the SIGFPE while signals are blocked, and we get
drastically different behaviour if force_sig_info() is used.

In the VFP case, if force_sig_info() is used, the program gets killed
at this point.  In the non-VFP case, the program's signal handler was
called.

Using send_sig_info() results in the already delayed or asynchronous
signal being held off until ppoll() drops the blocking, at which point
the signal is delivered, the program handles it in its handler, and
the program continues to run.

So
1. non-VFP case, program doesn't get killed but gets the opportunity
   to handle the signal.
2. VFP case with send_sig_info, program doesn't get killed but gets
   the opportunity to handle the signal.
3. VFP case with force_sig_info, the program gets killed and dumps
   core.

Which one of these results in a big change of behaviour in your
opinion?
I want to apologize for the disagreement.  In part of my due diligence
for cleaning up the signal handling I am introducing some helpers for
generating siginfo.  I decided to ask which kind of helpers should I
introduce.

Very basic generic helpers that just wrap the current functionality
today.  Or some slightly smarter helpers that solve some other problems
as well.  After consideration I am shelving the smarter helpers for now,
as the need to introduce the helpers universally is strong, so that I
can guarantee struct siginfo is always fully initialized before being
passed to userspace.

Given the choice between force_sig_info and send_sig_info I agree that
send_sig_info is the right choice for signals that can be ignored.

The problem I was focusing on is the problem where force_sig_info and
send_sig_info can be tricked into causing the instruction pointer to
point to the wrong instruction (even when the signal is not blocked),
due to the delivery of another signal.

So I was wondering if in practice we could introduce a singal delivery
function that would operation synchronously and would solve the
instruction pointer problem.

It looks to me like this location on arm where we are using
send_sig_info is a clear candidate for such a function as long as it has
a mode where you can say deliverly the signal like send_sig_info if the
signal is blocked.

Still like I said such a smarter helper is not the priority and I don't
intend any semantic changes when I introduce helpers into the signal
deliver path.  Just fewer places initializing struct siginfo.

Eric
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help