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.
This commit is contained in:
Дмитрий Левин 2017-07-08 14:57:44 +00:00
parent 2ccd886706
commit 4c14d39332
2 changed files with 31 additions and 4 deletions

1
NEWS
View File

@ -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)
===============================================

34
net.c
View File

@ -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;