• Johannes Berg's avatar
    net/compat/wext: send different messages to compat tasks · 1dacc76d
    Johannes Berg authored
    Wireless extensions have the unfortunate problem that events
    are multicast netlink messages, and are not independent of
    pointer size. Thus, currently 32-bit tasks on 64-bit platforms
    cannot properly receive events and fail with all kinds of
    strange problems, for instance wpa_supplicant never notices
    disassociations, due to the way the 64-bit event looks (to a
    32-bit process), the fact that the address is all zeroes is
    lost, it thinks instead it is 00:00:00:00:01:00.
    
    The same problem existed with the ioctls, until David Miller
    fixed those some time ago in an heroic effort.
    
    A different problem caused by this is that we cannot send the
    ASSOCREQIE/ASSOCRESPIE events because sending them causes a
    32-bit wpa_supplicant on a 64-bit system to overwrite its
    internal information, which is worse than it not getting the
    information at all -- so we currently resort to sending a
    custom string event that it then parses. This, however, has a
    severe size limitation we are frequently hitting with modern
    access points; this limitation would can be lifted after this
    patch by sending the correct binary, not custom, event.
    
    A similar problem apparently happens for some other netlink
    users on x86_64 with 32-bit tasks due to the alignment for
    64-bit quantities.
    
    In order to fix these problems, I have implemented a way to
    send compat messages to tasks. When sending an event, we send
    the non-compat event data together with a compat event data in
    skb_shinfo(main_skb)->frag_list. Then, when the event is read
    from the socket, the netlink code makes sure to pass out only
    the skb that is compatible with the task. This approach was
    suggested by David Miller, my original approach required
    always sending two skbs but that had various small problems.
    
    To determine whether compat is needed or not, I have used the
    MSG_CMSG_COMPAT flag, and adjusted the call path for recv and
    recvfrom to include it, even if those calls do not have a cmsg
    parameter.
    
    I have not solved one small part of the problem, and I don't
    think it is necessary to: if a 32-bit application uses read()
    rather than any form of recvmsg() it will still get the wrong
    (64-bit) event. However, neither do applications actually do
    this, nor would it be a regression.
    Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    1dacc76d
compat.c 23.3 KB