From: Dmitry V. Levin Date: Sat, 8 Jul 2017 14:57:44 +0000 (+0000) Subject: net: accept arbitrary option length for getsockopt's SO_LINGER X-Git-Tag: v4.19~317 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4c14d39332f8e56909f8bf5527b355a40cbf13fb;p=strace net: accept arbitrary option length for getsockopt's SO_LINGER * net.c (print_linger): Rename to print_set_linger. (print_setsockopt): Replace print_linger with print_set_linger. (print_get_linger): New function that accepts arbitrary option length to match the kernel behaviour. (print_getsockopt): Replace print_linger with print_get_linger. * NEWS: Mention this. --- diff --git a/NEWS b/NEWS index 70f9fa2f..4cb22a3f 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ Noteworthy changes in release ?.?? (????-??-??) * Improvements * Enhanced decoding of optlen argument of getsockopt syscall. + * Enhanced decoding of SO_LINGER option of getsockopt and setsockopt syscalls. Noteworthy changes in release 4.18 (2017-07-05) =============================================== diff --git a/net.c b/net.c index 5e20abc6..58a1bbf3 100644 --- a/net.c +++ b/net.c @@ -489,8 +489,8 @@ print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level, } static void -print_linger(struct tcb *const tcp, const kernel_ulong_t addr, - const unsigned int len) +print_set_linger(struct tcb *const tcp, const kernel_ulong_t addr, + const unsigned int len) { struct linger linger; @@ -505,6 +505,32 @@ print_linger(struct tcb *const tcp, const kernel_ulong_t addr, tprints("}"); } +static void +print_get_linger(struct tcb *const tcp, const kernel_ulong_t addr, + unsigned int len) +{ + struct linger linger; + + if (len < sizeof(linger)) { + if (len != sizeof(linger.l_onoff)) { + printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); + return; + } + } else { + len = sizeof(linger); + } + + if (umoven(tcp, addr, len, &linger) < 0) { + printaddr(addr); + return; + } + + PRINT_FIELD_D("{", linger, l_onoff); + if (len == sizeof(linger)) + PRINT_FIELD_D(", ", linger, l_linger); + tprints("}"); +} + #ifdef SO_PEERCRED static void print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, const int len) @@ -573,7 +599,7 @@ print_getsockopt(struct tcb *const tcp, const unsigned int level, case SOL_SOCKET: switch (name) { case SO_LINGER: - print_linger(tcp, addr, len); + print_get_linger(tcp, addr, len); return; #ifdef SO_PEERCRED case SO_PEERCRED: @@ -771,7 +797,7 @@ print_setsockopt(struct tcb *const tcp, const unsigned int level, case SOL_SOCKET: switch (name) { case SO_LINGER: - print_linger(tcp, addr, len); + print_set_linger(tcp, addr, len); return; } break;