From: ebiederm@xmission.com (Eric W. Biederman)
To: Alan Stern <stern@rowland.harvard.edu>
Cc: linux-usb@vger.kernel.org,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Oliver Neukum <oneukum@suse.com>, <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] signal/usb: Replace kill_pid_info_as_cred with kill_pid_usb_asyncio
Date: Wed, 22 May 2019 16:50:11 -0500 [thread overview]
Message-ID: <87o93ujh0s.fsf@xmission.com> (raw)
In-Reply-To: <Pine.LNX.4.44L0.1905221459170.1410-100000@iolanthe.rowland.org> (Alan Stern's message of "Wed, 22 May 2019 15:02:29 -0400 (EDT)")
Alan Stern <stern@rowland.harvard.edu> writes:
> On Tue, 21 May 2019, Eric W. Biederman wrote:
>
>> The usb support for asyncio encoded one of it's values in the wrong
>> field. It should have used si_value but instead used si_addr which is
>> not present in the _rt union member of struct siginfo.
>>
>> The practical result of this is that on a 64bit big endian kernel
>> when delivering a signal to a 32bit process the si_addr field
>> is set to NULL, instead of the expected pointer value.
>>
>> This issue can not be fixed in copy_siginfo_to_user32 as the usb
>> usage of the the _sigfault (aka si_addr) member of the siginfo
>> union when SI_ASYNCIO is set is incompatible with the POSIX and
>> glibc usage of the _rt member of the siginfo union.
>>
>> Therefore replace kill_pid_info_as_cred with kill_pid_usb_asyncio a
>> dedicated function for this one specific case. There are no other
>> users of kill_pid_info_as_cred so this specialization should have no
>> impact on the amount of code in the kernel. Have kill_pid_usb_asyncio
>> take instead of a siginfo_t which is difficult and error prone, 3
>> arguments, a signal number, an errno value, and an address enconded as
>> a sigval_t. The encoding of the address as a sigval_t allows the
>> code that reads the userspace request for a signal to handle this
>> compat issue along with all of the other compat issues.
>>
>> Add BUILD_BUG_ONs in kernel/signal.c to ensure that we can now place
>> the pointer value at the in si_pid (instead of si_addr). That is the
>> code now verifies that si_pid and si_addr always occur at the same
>> location. Further the code veries that for native structures a value
>> placed in si_pid and spilling into si_uid will appear in userspace in
>> si_addr (on a byte by byte copy of siginfo or a field by field copy of
>> siginfo). The code also verifies that for a 64bit kernel and a 32bit
>> userspace the 32bit pointer will fit in si_pid.
>
> Okay, I have gone through this. Although I still don't really
> understand the detailed issues concerning the layout of the data fields
> (probably hopeless without seeing a diagram), the USB portions of the
> patch look good and do what the patch description says.
>
> Acked-by: Alan Stern <stern@rowland.harvard.edu>
>
> Alan Stern
Thanks.
Perhaps this will work as a diagram. I don't know if there is a better
way to say it in my patch description. In struct siginfo there are 3
fields in fixed positions:
int si_signo;
int si_errno;
int si_code;
After that there is a union. The si_signo and si_code fields are
examined to see which union member is valid (see siginfo_layout).
In every other case a si_code of SI_ASYNCIO corresponds to
the the _rt union member which has the fields:
int si_pid;
int si_uid;
sigval_t si_sigval;
However when usb started using SI_ASYNCIO the _sigfault union member
that (except for special exceptions) only has the field:
void __user *si_addr;
Or in short the relevant piece of the union looks like:
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| si_pid | si_uid |
+---+---+---+---+---+---+---+---+
| si_addr | (64bit)
+---+---+---+---+---+---+---+---+
| si_addr | (32bit)
+---+---+---+---+
Which means if siginfo is copied field by field on 32bit everything
works because si_pid and si_addr are in the same location.
Similarly if siginfo is copied field by field on 64bit everything
works because there is no padding between si_pid and si_uid. So
copying both of those fields results in the entire si_addr being
copied.
It is the compat case that gets tricky. Half of the bits are
zero. If those zero bits show up in bytes 4-7 and the data
shows up in bytes 0-3 (aka little endian) everything works.
If those zero bits show in in bytes 0-3 (aka big endian) userspace sees
a NULL pointer instead of the value it passed.
Fixing this while maintaining some modicum of sanity is the tricky bit.
The interface is made to kill_pid_usb_asyncio is made a sigval_t so the
standard signal compat tricks can be used. sigval_t is a union of:
int sival_int;
void __user *sival_ptr;
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| sival_ptr | (64bit)
+---+---+---+---+---+---+---+---+
| sival_ptr | (32bit)
+---+---+---+---+
| sival_int |
+---+---+---+---+
The signal code solves the compat issues for sigval_t by storing the
32bit pointers in sival_int. So they meaningful bits are guaranteed to
be in the low 32bits, just like the 32bit sival_ptr.
After a bunch of build BUG_ONs to verify my reasonable assumptions
of but the siginfo layout are actually true, the code that generates
the siginfo just copies a sigval_t to si_pid. And assumes the code
in the usb stack placed the pointer in the proper part of the sigval_t
when it read the information from userspace.
I don't know if that helps make it easy to understand but I figured I
would give it a shot.
Eric
next prev parent reply other threads:[~2019-05-22 21:50 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-08 21:57 [CFT] signal/usb: Replace kill_pid_info_as_cred with kill_pid_usb_asyncio Alan Stern
2019-02-08 21:57 ` [CFT][PATCH] " Alan Stern
2019-05-18 1:38 ` Eric W. Biederman
2019-05-18 15:20 ` Alan Stern
2019-05-18 15:25 ` Eric W. Biederman
2019-05-21 12:40 ` [PATCH] " Eric W. Biederman
2019-05-21 14:02 ` Alan Stern
2019-05-21 14:47 ` Eric W. Biederman
2019-05-21 15:30 ` Alan Stern
2019-05-22 19:02 ` Alan Stern
2019-05-22 21:50 ` Eric W. Biederman [this message]
2019-05-23 18:12 ` Alan Stern
2019-05-23 20:54 ` Eric W. Biederman
2019-06-06 14:27 ` Greg Kroah-Hartman
-- strict thread matches above, loose matches on Subject: below --
2019-02-08 2:34 [CFT] " Eric W. Biederman
2019-02-08 2:34 ` [CFT][PATCH] " Eric W. Biederman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87o93ujh0s.fsf@xmission.com \
--to=ebiederm@xmission.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=oneukum@suse.com \
--cc=stern@rowland.harvard.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.