• Eric W. Biederman's avatar
    signal: Remove kernel interal si_code magic · cc731525
    Eric W. Biederman authored
    struct siginfo is a union and the kernel since 2.4 has been hiding a union
    tag in the high 16bits of si_code using the values:
    __SI_KILL
    __SI_TIMER
    __SI_POLL
    __SI_FAULT
    __SI_CHLD
    __SI_RT
    __SI_MESGQ
    __SI_SYS
    
    While this looks plausible on the surface, in practice this situation has
    not worked well.
    
    - Injected positive signals are not copied to user space properly
      unless they have these magic high bits set.
    
    - Injected positive signals are not reported properly by signalfd
      unless they have these magic high bits set.
    
    - These kernel internal values leaked to userspace via ptrace_peek_siginfo
    
    - It was possible to inject these kernel internal values and cause the
      the kernel to misbehave.
    
    - Kernel developers got confused and expected these kernel internal values
      in userspace in kernel self tests.
    
    - Kernel developers got confused and set si_code to __SI_FAULT which
      is SI_USER in userspace which causes userspace to think an ordinary user
      sent the signal and that it was not kernel generated.
    
    - The values make it impossible to reorganize the code to transform
      siginfo_copy_to_user into a plain copy_to_user.  As si_code must
      be massaged before being passed to userspace.
    
    So remove these kernel internal si codes and make the kernel code simpler
    and more maintainable.
    
    To replace these kernel internal magic si_codes introduce the helper
    function siginfo_layout, that takes a signal number and an si_code and
    computes which union member of siginfo is being used.  Have
    siginfo_layout return an enumeration so that gcc will have enough
    information to warn if a switch statement does not handle all of union
    members.
    
    A couple of architectures have a messed up ABI that defines signal
    specific duplications of SI_USER which causes more special cases in
    siginfo_layout than I would like.  The good news is only problem
    architectures pay the cost.
    
    Update all of the code that used the previous magic __SI_ values to
    use the new SIL_ values and to call siginfo_layout to get those
    values.  Escept where not all of the cases are handled remove the
    defaults in the switch statements so that if a new case is missed in
    the future the lack will show up at compile time.
    
    Modify the code that copies siginfo si_code to userspace to just copy
    the value and not cast si_code to a short first.  The high bits are no
    longer used to hold a magic union member.
    
    Fixup the siginfo header files to stop including the __SI_ values in
    their constants and for the headers that were missing it to properly
    update the number of si_codes for each signal type.
    
    The fixes to copy_siginfo_from_user32 implementations has the
    interesting property that several of them perviously should never have
    worked as the __SI_ values they depended up where kernel internal.
    With that dependency gone those implementations should work much
    better.
    
    The idea of not passing the __SI_ values out to userspace and then
    not reinserting them has been tested with criu and criu worked without
    changes.
    
    Ref: 2.4.0-test1
    Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
    cc731525
signalfd.c 8.86 KB