sendto_kdc: prevent poll from accidently wait indefinitely

We encountered a poll deadlock in an application using the krb5 library.

After some analysis, it was due to the fact that the poll() was called with a negative timeout.

The proposed patch ensures that no negative timeout can be used in poll when the wait deadline is already reached.

The following extract of analysis notes details the issue :   

    [root@compute1143 krb5-1.9]# gstack 30651
    Thread 2 (Thread 0x2b45e84fb700 (LWP 30652)):
    #0 0x00002b45e6450613 in poll () from /lib64/libc.so.6
    0000001 0x0000000000432135 in eio_handle_mainloop ()
    0000002 0x0000000000430d94 in _msg_thr_internal ()
    0000003 0x00002b45e615f7f1 in start_thread () from /lib64/libpthread.so.0
    0000004 0x00002b45e6459ccd in clone () from /lib64/libc.so.6
    Thread 1 (Thread 0x2b45e7bd1cc0 (LWP 30651)):
    #0 0x00002b45e6450613 in poll () from /lib64/libc.so.6
    0000001 0x00002b45f3f791ba in ?? () from /lib64/libkrb5.so.3
    0000002 0x00002b45f3f79d04 in ?? () from /lib64/libkrb5.so.3
    0000003 0x00002b45f3f7a433 in krb5_sendto_kdc () from /lib64/libkrb5.so.3
    0000004 0x00002b45f3f49f75 in krb5_tkt_creds_get () from /lib64/libkrb5.so.3
    0000005 0x00002b45f3f4a0fd in krb5_get_credentials () from /lib64/libkrb5.so.3
    0000006 0x00002b45f3f61c52 in krb5_sendauth () from /lib64/libkrb5.so.3
    0000007 0x00002b45f3cc4d71 in auks_krb5_stream_clnt_auth () from /usr/lib64/libauksapi.so.0
    0000008 0x00002b45f3cc4e35 in auks_krb5_stream_authenticate () from /usr/lib64/libauksapi.so.0
    0000009 0x00002b45f3cccc45 in auks_api_request () from /usr/lib64/libauksapi.so.0
    0000010 0x00002b45f3ccd04e in auks_api_get_auks_cred () from /usr/lib64/libauksapi.so.0
    0000011 0x00002b45f3ccd3f1 in auks_api_get_cred () from /usr/lib64/libauksapi.so.0
    0000012 0x00002b45e8d1acde in spank_auks_remote_init () from /usr/lib64/slurm/auks.so
    0000013 0x0000000000436247 in _do_call_stack ()
    0000014 0x000000000043675b in spank_init ()
    0000015 0x0000000000425cfa in job_manager ()
    0000016 0x000000000042290d in main ()
    [root@compute1143 krb5-1.9]#
    
    [root@compute1143]# lsof -p 30651
    ...
    slurmstep 30651 root mem REG 8,1 912944 784985 /lib64/libkrb5.so.3.3
    slurmstep 30651 root mem REG 8,1 90784 784983 /lib64/libgcc_s-4.4.5-20110214.so.1
    slurmstep 30651 root mem REG 8,1 178952 784924 /lib64/libk5crypto.so.3.1
    slurmstep 30651 root mem REG 8,1 12400 784929 /lib64/libcom_err.so.2.1
    slurmstep 30651 root mem REG 8,1 43696 784903 /lib64/libkrb5support.so.0.1
    ...
    slurmstep 30651 root 11u IPv4 149991 0t0 UDP compute1143:37630->kerberos-master:kerberos
    slurmstep 30651 root 12u IPv4 149992 0t0 UDP compute1143:51242->kerberos-slave:kerberos
    ...
    [root@compute1143]#
    
    
    [root@compute1143 krb5-1.9]# gdb /tmp/slurmstepd -p 30651
    ..
    0x00002b45e6450613 in ?? ()
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.47.bl6_2.9.x86_64
    (gdb) bt
    #0 0x00002b45e6450613 in ?? ()
    0000001 0x00000000047867a0 in ?? ()
    0000002 0x00002b45fffffffa in ?? ()
    0000003 0x0000000000000002 in ?? ()
    0000004 0x0000000004789038 in ?? ()
    0000005 0x0000000004789038 in ?? ()
    0000006 0x00002b45f3f791ba in ?? ()
    0000007 0x00002b45f3fb1f2d in ?? ()
    0000008 0x00002b45e54f1fb0 in _dl_fixup () from /lib64/ld-linux-x86-64.so.2
    0000009 0x0000000000038a96 in ?? ()
    0000010 0x0000000004786820 in ?? ()
    0000011 0x786045a65bcb741c in ?? ()
    0000012 0x0000000000000004 in ?? ()
    0000013 0x0000000004786820 in ?? ()
    0000014 0x0000000000000004 in ?? ()
    0000015 0x0000000004785dc0 in ?? ()
    0000016 0x0000000004787020 in ?? ()
    0000017 0x0000000000000040 in ?? ()
    0000018 0x0000000000000000 in ?? ()
    (gdb) select 0
    (gdb) print $rdi
    $1 = 75010104
    (gdb) print (struct pollfd *) $rdi
    $2 = (struct pollfd *) 0x4789038
    (gdb) print *(struct pollfd *) $rdi
    $3 = {fd = 11, events = 1, revents = 0}
    (gdb) print *(((struct pollfd *) $rdi)+1)
    $4 = {fd = 12, events = 1, revents = 0}
    
    (gdb) print $rsi
    $7 = 2
    (gdb)
    (gdb) print $rdx
    $8 = -6