syscalls/recvmsg03.c: add new testcase
PATCH 1/1 syscalls/recvmsg03.c: add new testcase
If the size of address for receiving data is set larger than actaul size, recvmsg() will set msg_namelen incorrectly and destroy sock_fd.
This bug has been fixed by the following kernel commit:
06b6a1cf6e776426766298d055bb3991957d90a7(rds: set correct msg_namelen)
--- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/recvmsg/recvmsg03.c | 195 ++++++++++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 testcases/kernel/syscalls/recvmsg/recvmsg03.c
runtest/syscalls +1 -0
@@ -869,6 +869,7 @@ recvfrom01 recvfrom01 recvmsg01 recvmsg01 recvmsg02 recvmsg02 +recvmsg03 recvmsg03 remap_file_pages01 remap_file_pages01 remap_file_pages02 remap_file_pages02
testcases/kernel/syscalls/.gitignore +1 -0
@@ -725,6 +725,7 @@ /recvfrom/recvfrom01 /recvmsg/recvmsg01 /recvmsg/recvmsg02 +/recvmsg/recvmsg03 /remap_file_pages/remap_file_pages01 /remap_file_pages/remap_file_pages02 /removexattr/removexattr01
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +195 -0
195 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 1/1 syscalls/recvmsg03.c: add new testcase
Hi!
Quoted 4 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +4
-0+static void setup (void ) +{ +int acc_res, load_res; +const char *cmd[] = {"modprobe" ,"-i" ,"rds" ,NULL };
testcases/kernel/syscalls/recvmsg/recvmsg03.c line 55
Quoted 10 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +10
-0+ + acc_res =access ("/proc/sys/net/rds" ,F_OK ); +if (acc_res ==-1 && errno ==ENOENT ) { + load_res =tst_run_cmd (cmd,NULL ,NULL ,1 ); +if (load_res) { +tst_brk (TCONF ,"failed to loaded rds module, " +"so rds modeule was not support by system" ); + }else { +tst_res (TINFO ,"succeeded to load rds module" ); + rds_flag =1 ;
No need for the else branch here, the tst_brk() will exit test if it's reached.
Also if you just do return; here then you can just later do:
tst_brk(TFAIL | TERRNO, "failed to check rds module");
testcases/kernel/syscalls/recvmsg/recvmsg03.c line 60
Quoted 5 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +5
-0+ } + } + +if (acc_res ==-1 && errno !=ENOENT ) +tst_brk (TFAIL |TERRNO ,"failed to check rds module" );
Once you get here the errno may be changed several times by library functions called from tst_run_cmd() and tst_res().
The errno is per thread global variable used by most of the glibc functions. Once you call something that may change its value is undefined.
Quoted 13 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +13
-0+tst_res (TINFO ,"rds module was supported by system" ); +} + +static void cleanup (void ) +{ +int unload_res; +const char *cmd[] = {"modprobe" ,"-r" ,"rds" ,NULL }; + +if (rds_flag ==1 ) { + unload_res =tst_run_cmd (cmd,NULL ,NULL ,1 ); +if (unload_res) +tst_res (TWARN |TERRNO ,"failed to unload rds module" ); +else
testcases/kernel/syscalls/recvmsg/recvmsg03.c line 84
Quoted 10 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +10
-0+tst_res (TINFO ,"succeeded to unload rds modules" ); + } +} + +static void client (void ) +{ +int sock_fd1; +char sendBuffer[128 ] ="hello world" ; +struct sockaddr_in serverAddr; +struct sockaddr_in toAddr;
Mixed case is frowned upon in LKML coding style. So these should rather be send_buf, server_addr, etc...
Quoted 33 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +33
-0+struct msghdr msg; +struct iovec iov; + + sock_fd1 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + +memset (&serverAddr,0 ,sizeof (serverAddr)); + serverAddr.sin_family =AF_INET ; + serverAddr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + serverAddr.sin_port =htons (4001 ); + +SAFE_BIND (sock_fd1, (struct sockaddr *) &serverAddr,sizeof (serverAddr)); + +memset (&toAddr,0 ,sizeof (toAddr)); + + toAddr.sin_family =AF_INET ; + toAddr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + toAddr.sin_port =htons (4000 ); + msg.msg_name = &toAddr; + msg.msg_namelen =sizeof (toAddr); + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = sendBuffer; + msg.msg_iov->iov_len =strlen (sendBuffer) +1 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +if (sendmsg (sock_fd1, &msg,0 ) ==-1 ) { +tst_brk (TFAIL |TERRNO , +"sendmsg() failed to send data to server" ); + } + +SAFE_CLOSE (sock_fd1);
testcases/kernel/syscalls/recvmsg/recvmsg03.c line 127
Quoted 10 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +10
-0+} + +static void server (void ) +{ +int sock_fd, sock_fd2; +static char recvBuffer[128 ]; +struct sockaddr_in serverAddr; +struct sockaddr_in fromAddr; +struct msghdr msg; +struct iovec iov;
Here as well.
Quoted 75 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +67
-0+ sock_fd2 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + sock_fd = sock_fd2; + +memset (&serverAddr,0 ,sizeof (serverAddr)); + serverAddr.sin_family =AF_INET ; + serverAddr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + serverAddr.sin_port =htons (4000 ); + +SAFE_BIND (sock_fd2, (struct sockaddr *) &serverAddr,sizeof (serverAddr)); + + msg.msg_name = &fromAddr; + msg.msg_namelen =sizeof (fromAddr) +16 ; + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = recvBuffer; + msg.msg_iov->iov_len =128 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +TST_CHECKPOINT_WAKE (0 ); + +TEST (recvmsg (sock_fd2, &msg,0 )); +if (TEST_RETURN ==-1 ) { +tst_res (TFAIL |TERRNO , +"recvmsg() failed to recvice data from client" ); +return ; + } + +if (msg.msg_namelen !=sizeof (fromAddr)) { +tst_res (TFAIL ,"msg_namelen was set to %u incorrectly, " +"expected %lu" , msg.msg_namelen,sizeof (fromAddr)); +return ; + } + +if (sock_fd2 != sock_fd) { +tst_res (TFAIL ,"sock_fd was destroyed" ); +return ; + } + +tst_res (TPASS ,"msg_namelen was set to %u correctly and sock_fd was " +"not destroyed" , msg.msg_namelen); + +SAFE_CLOSE (sock_fd2); +} + +static void verify_recvmsg (void ) +{ +pid_t pid; + + pid =SAFE_FORK (); +if (pid ==0 ) { +TST_CHECKPOINT_WAIT (0 ); +client (); + }else { +server (); + } +} + +static struct tst_test test = { + .tid ="recvmsg03" , + .forks_child =1 , + .needs_checkpoints =1 , + .setup = setup, + .cleanup = cleanup, + .test_all = verify_recvmsg +};Signature · 7 lines
1.8.3.1 -- Mailing list info: https://lists.linux.it/listinfo/ltp
Signature · 2 lines
Cyril Hrubis [email protected]
PATCH v2 1/1 syscalls/recvmsg03.c: add new testcase
If the size of address for receiving data is set larger than actaul size, recvmsg() will set msg_namelen incorrectly and destroy sock_fd.
This bug has been fixed by the following kernel patch:
'commit 06b6a1cf6e77 ("rds: set correct msg_namelen")'
--- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/recvmsg/recvmsg03.c | 196 ++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 testcases/kernel/syscalls/recvmsg/recvmsg03.c
runtest/syscalls +1 -0
@@ -869,6 +869,7 @@ recvfrom01 recvfrom01 recvmsg01 recvmsg01 recvmsg02 recvmsg02 +recvmsg03 recvmsg03 remap_file_pages01 remap_file_pages01 remap_file_pages02 remap_file_pages02
testcases/kernel/syscalls/.gitignore +1 -0
@@ -725,6 +725,7 @@ /recvfrom/recvfrom01 /recvmsg/recvmsg01 /recvmsg/recvmsg02 +/recvmsg/recvmsg03 /remap_file_pages/remap_file_pages01 /remap_file_pages/remap_file_pages02 /removexattr/removexattr01
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +196 -0
196 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH v2 1/1 syscalls/recvmsg03.c: add new testcase
Hi Cyril
Please ignore the v2 patch,i will resend it.
Thanks,
Xiao Yang
Quoted 240 lines · Xiao Yang
If the size of address for receiving data is set larger than actaul size,
recvmsg()will setmsg_namelenincorrectly and destroysock_fd.This bug has been fixed by the following kernel patch:
'commit06b6a1cf6e77("rds: set correctmsg_namelen")'Signed-off-by Xiao Yang <[email protected]>--- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/recvmsg/recvmsg03.c | 196 ++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 testcases/kernel/syscalls/recvmsg/recvmsg03.cruntest/syscalls +1
-0@@ -869,6 +869,7 @@ recvfrom01 recvfrom01 recvmsg01 recvmsg01 recvmsg02 recvmsg02 +recvmsg03 recvmsg03 remap_file_pages01 remap_file_pages01 remap_file_pages02 remap_file_pages02testcases/kernel/syscalls/.gitignore +1
-0@@ -725,6 +725,7 @@ /recvfrom/recvfrom01 /recvmsg/recvmsg01 /recvmsg/recvmsg02 +/recvmsg/recvmsg03 /remap_file_pages/remap_file_pages01 /remap_file_pages/remap_file_pages02 /removexattr/removexattr01testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +196
-0@@ -0,0 +1,196 @@ +/* +* Copyright(c) 2016 Fujitsu Ltd. +* Author: Xiao Yang <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it would be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* +* You should have received a copy of the GNU General Public License +* alone with this program. +*/ + +/* +* Test Name: recvmsg03 +* +* This test needs that rds socket is supported by system. +* If the size of address for receiving data is set larger than actaul size, +* recvmsg() will set msg_namelen incorrectly and destroy sock_fd. +* +* Description: +* This is a regression test and has been fixed by kernel commit: +* 06b6a1cf6e776426766298d055bb3991957d90a7 (rds: set correct msg_namelen) +*/ + +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <stdio.h> + +#include "tst_test.h" + +#ifndef AF_RDS +# define AF_RDS 21 +#endif + +static int rds_flag; + +static void setup (void ) +{ +int acc_res, load_res; +const char *cmd[] = {"modprobe" ,"-i" ,"rds" ,NULL }; + + acc_res =access ("/proc/sys/net/rds" ,F_OK ); +if (acc_res ==-1 && errno !=ENOENT ) +tst_brk (TFAIL |TERRNO ,"failed to check rds module" ); + +if (acc_res ==-1 && errno ==ENOENT ) { + load_res =tst_run_cmd (cmd,NULL ,NULL ,1 ); +if (load_res) { +tst_brk (TCONF ,"failed to loaded rds module, " +"so rds modeule was not support by system" ); + } + +tst_res (TINFO ,"succeeded to load rds module" ); + rds_flag =1 ; + } + +tst_res (TINFO ,"rds module was supported by system" ); +} + +static void cleanup (void ) +{ +int unload_res; +const char *cmd[] = {"modprobe" ,"-r" ,"rds" ,NULL }; + +if (rds_flag ==1 ) { + unload_res =tst_run_cmd (cmd,NULL ,NULL ,1 ); +if (unload_res) +tst_res (TWARN |TERRNO ,"failed to unload rds module" ); +else +tst_res (TINFO ,"succeeded to unload rds modules" ); + } +} + +static void client (void ) +{ +int sock_fd1; +char send_buf[128 ] ="hello world" ; +struct sockaddr_in server_addr; +struct sockaddr_in to_addr; +struct msghdr msg; +struct iovec iov; + + sock_fd1 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + +memset (&server_addr,0 ,sizeof (server_addr)); + server_addr.sin_family =AF_INET ; + server_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + server_addr.sin_port =htons (4001 ); + +SAFE_BIND (sock_fd1, (struct sockaddr *) &server_addr,sizeof (server_addr)); + +memset (&to_addr,0 ,sizeof (to_addr)); + + to_addr.sin_family =AF_INET ; + to_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + to_addr.sin_port =htons (4000 ); + msg.msg_name = &to_addr; + msg.msg_namelen =sizeof (to_addr); + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = send_buf; + msg.msg_iov->iov_len =strlen (send_buf) +1 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +if (sendmsg (sock_fd1, &msg,0 ) ==-1 ) { +tst_brk (TFAIL |TERRNO , +"sendmsg() failed to send data to server" ); + } + +SAFE_CLOSE (sock_fd1); +} + +static void server (void ) +{ +int sock_fd, sock_fd2; +static char recv_buf[128 ]; +struct sockaddr_in server_addr; +struct sockaddr_in from_addr; +struct msghdr msg; +struct iovec iov; + + sock_fd2 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + sock_fd = sock_fd2; + +memset (&server_addr,0 ,sizeof (server_addr)); + server_addr.sin_family =AF_INET ; + server_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + server_addr.sin_port =htons (4000 ); + +SAFE_BIND (sock_fd2, (struct sockaddr *) &server_addr,sizeof (server_addr)); + + msg.msg_name = &from_addr; + msg.msg_namelen =sizeof (from_addr) +16 ; + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = recv_buf; + msg.msg_iov->iov_len =128 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +TST_CHECKPOINT_WAKE (0 ); + +TEST (recvmsg (sock_fd2, &msg,0 )); +if (TEST_RETURN ==-1 ) { +tst_res (TFAIL |TERRNO , +"recvmsg() failed to recvice data from client" ); + goto end; + } + +if (msg.msg_namelen !=sizeof (from_addr)) { +tst_res (TFAIL ,"msg_namelen was set to %u incorrectly, " +"expected %lu" , msg.msg_namelen,sizeof (from_addr)); + goto end; + } + +if (sock_fd2 != sock_fd) { +tst_res (TFAIL ,"sock_fd was destroyed" ); + goto end; + } + +tst_res (TPASS ,"msg_namelen was set to %u correctly and sock_fd was " +"not destroyed" , msg.msg_namelen); + +end: +SAFE_CLOSE (sock_fd2); +} + +static void verify_recvmsg (void ) +{ +pid_t pid; + + pid =SAFE_FORK (); +if (pid ==0 ) { +TST_CHECKPOINT_WAIT (0 ); +client (); + }else { +server (); + } +} + +static struct tst_test test = { + .tid ="recvmsg03" , + .forks_child =1 , + .needs_checkpoints =1 , + .setup = setup, + .cleanup = cleanup, + .test_all = verify_recvmsg +};
PATCH v2 1/1 syscalls/recvmsg03.c: add new testcase
In reply to Cyril HrubisIf the size of address for receiving data is set larger than actaul size, recvmsg() will set msg_namelen incorrectly and destroy sock_fd.
This bug has been fixed by the following kernel commit:
06b6a1cf6e776426766298d055bb3991957d90a7(rds: set correct msg_namelen)
--- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/recvmsg/recvmsg03.c | 172 ++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 testcases/kernel/syscalls/recvmsg/recvmsg03.c
runtest/syscalls +1 -0
@@ -870,6 +870,7 @@ recvfrom01 recvfrom01 recvmsg01 recvmsg01 recvmsg02 recvmsg02 +recvmsg03 recvmsg03 remap_file_pages01 remap_file_pages01 remap_file_pages02 remap_file_pages02
testcases/kernel/syscalls/.gitignore +1 -0
@@ -725,6 +725,7 @@ /recvfrom/recvfrom01 /recvmsg/recvmsg01 /recvmsg/recvmsg02 +/recvmsg/recvmsg03 /remap_file_pages/remap_file_pages01 /remap_file_pages/remap_file_pages02 /removexattr/removexattr01
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +172 -0
172 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH v2 1/1 syscalls/recvmsg03.c: add new testcase
Hi!
Quoted 44 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +44
-0+static void server (void ) +{ +int sock_fd, sock_fd2; +static char recv_buf[128 ]; +struct sockaddr_in server_addr; +struct sockaddr_in from_addr; +struct msghdr msg; +struct iovec iov; + + sock_fd2 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + sock_fd = sock_fd2; + +memset (&server_addr,0 ,sizeof (server_addr)); + server_addr.sin_family =AF_INET ; + server_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + server_addr.sin_port =htons (4000 ); + +SAFE_BIND (sock_fd2, (struct sockaddr *) &server_addr,sizeof (server_addr)); + + msg.msg_name = &from_addr; + msg.msg_namelen =sizeof (from_addr) +16 ; + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = recv_buf; + msg.msg_iov->iov_len =128 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +TST_CHECKPOINT_WAKE (0 ); + +TEST (recvmsg (sock_fd2, &msg,0 )); +if (TEST_RETURN ==-1 ) { +tst_res (TFAIL |TERRNO , +"recvmsg() failed to recvice data from client" ); + goto end; + } + +if (msg.msg_namelen !=sizeof (from_addr)) { +tst_res (TFAIL ,"msg_namelen was set to %u incorrectly, " +"expected %lu" , msg.msg_namelen,sizeof (from_addr)); + goto end; + } +
testcases/kernel/syscalls/recvmsg/recvmsg03.c line 149
Quoted 10 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +10
-0+if (sock_fd2 != sock_fd) { +tst_res (TFAIL ,"sock_fd was destroyed" ); + goto end; + } + +tst_res (TPASS ,"msg_namelen was set to %u correctly and sock_fd was " +"not destroyed" , msg.msg_namelen); + +end: +SAFE_CLOSE (sock_fd2);
I'm a bit confused here, which one of the sock_fd/sock_fd2 is destroyed?
Looking at the original code in the kernel commit the sock_fd there is stored on the stack directly after the sockaddr_in from_addr so I guess that the kernel will actually write a few bytes after the end of from_addr structure in this case, which will rewrite the msghrd msg in your code. Does the test actually fail on kernel without the fix?
testcases/kernel/syscalls/recvmsg/recvmsg03.c line 162
Quoted 13 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +13
-0+} + +static void verify_recvmsg (void ) +{ +pid_t pid; + + pid =SAFE_FORK (); +if (pid ==0 ) { +TST_CHECKPOINT_WAIT (0 ); +client (); + }else { +server (); +SAFE_WAIT (NULL );
We should rather call tst_reap_children() in this case instead of the WAIT since otherwise TBROK from the client() function will not get propagated.
Quoted 15 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +10
-0+ } +} + +static struct tst_test test = { + .tid ="recvmsg03" , + .forks_child =1 , + .needs_checkpoints =1 , + .setup = setup, + .test_all = verify_recvmsg +};Signature · 1 line
1.8.3.1
Signature · 2 lines
Cyril Hrubis [email protected]
PATCH v3 1/1 syscalls/recvmsg03.c: add new testcase
If the size of address for receiving data is set larger than actaul size, recvmsg() will set msg_namelen incorrectly.
This bug has been fixed by the following kernel patch:
'commit 06b6a1cf6e77 ("rds: set correct msg_namelen")'
--- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/recvmsg/recvmsg03.c | 163 ++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 testcases/kernel/syscalls/recvmsg/recvmsg03.c
runtest/syscalls +1 -0
@@ -870,6 +870,7 @@ recvfrom01 recvfrom01 recvmsg01 recvmsg01 recvmsg02 recvmsg02 +recvmsg03 recvmsg03 remap_file_pages01 remap_file_pages01 remap_file_pages02 remap_file_pages02
testcases/kernel/syscalls/.gitignore +1 -0
@@ -725,6 +725,7 @@ /recvfrom/recvfrom01 /recvmsg/recvmsg01 /recvmsg/recvmsg02 +/recvmsg/recvmsg03 /remap_file_pages/remap_file_pages01 /remap_file_pages/remap_file_pages02 /removexattr/removexattr01
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +163 -0
163 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH v3 1/1 syscalls/recvmsg03.c: add new testcase
Hi Cyril!
Ping :-)
Thanks,
Xiao Yang
Quoted 207 lines · Xiao Yang
If the size of address for receiving data is set larger than actaul size,
recvmsg()will setmsg_namelenincorrectly.This bug has been fixed by the following kernel patch:
'commit06b6a1cf6e77("rds: set correctmsg_namelen")'Signed-off-by Xiao Yang <[email protected]>--- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/recvmsg/recvmsg03.c | 163 ++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 testcases/kernel/syscalls/recvmsg/recvmsg03.cruntest/syscalls +1
-0@@ -870,6 +870,7 @@ recvfrom01 recvfrom01 recvmsg01 recvmsg01 recvmsg02 recvmsg02 +recvmsg03 recvmsg03 remap_file_pages01 remap_file_pages01 remap_file_pages02 remap_file_pages02testcases/kernel/syscalls/.gitignore +1
-0@@ -725,6 +725,7 @@ /recvfrom/recvfrom01 /recvmsg/recvmsg01 /recvmsg/recvmsg02 +/recvmsg/recvmsg03 /remap_file_pages/remap_file_pages01 /remap_file_pages/remap_file_pages02 /removexattr/removexattr01testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +163
-0@@ -0,0 +1,163 @@ +/* +* Copyright(c) 2016 Fujitsu Ltd. +* Author: Xiao Yang <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it would be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* +* You should have received a copy of the GNU General Public License +* alone with this program. +*/ + +/* +* Test Name: recvmsg03 +* +* This test needs that rds socket is supported by system. +* If the size of address for receiving data is set larger than +* actaul size, recvmsg() will set msg_namelen incorrectly. +* +* Description: +* This is a regression test and has been fixed by kernel commit: +* 06b6a1cf6e776426766298d055bb3991957d90a7 (rds: set correct msg_namelen) +*/ + +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "tst_test.h" + +#ifndef AF_RDS +# define AF_RDS 21 +#endif + +static void setup (void ) +{ +int res; + + res =socket (AF_RDS ,SOCK_SEQPACKET ,0 ); +if (res ==-1 ) { +if (errno ==EAFNOSUPPORT ) +tst_brk (TCONF ,"rds was not supported" ); +else +tst_brk (TBROK |TERRNO ,"socket() failed with rds" ); + } + +SAFE_CLOSE (res); +} + +static void client (void ) +{ +int sock_fd1; +char send_buf[128 ] ="hello world" ; +struct sockaddr_in server_addr; +struct sockaddr_in to_addr; +struct msghdr msg; +struct iovec iov; + + sock_fd1 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + +memset (&server_addr,0 ,sizeof (server_addr)); + server_addr.sin_family =AF_INET ; + server_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + server_addr.sin_port =htons (4001 ); + +SAFE_BIND (sock_fd1, (struct sockaddr *) &server_addr,sizeof (server_addr)); + +memset (&to_addr,0 ,sizeof (to_addr)); + + to_addr.sin_family =AF_INET ; + to_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + to_addr.sin_port =htons (4000 ); + msg.msg_name = &to_addr; + msg.msg_namelen =sizeof (to_addr); + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = send_buf; + msg.msg_iov->iov_len =strlen (send_buf) +1 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +if (sendmsg (sock_fd1, &msg,0 ) ==-1 ) { +tst_brk (TBROK |TERRNO , +"sendmsg() failed to send data to server" ); + } + +SAFE_CLOSE (sock_fd1); +} + +static void server (void ) +{ +int sock_fd2; +static char recv_buf[128 ]; +struct sockaddr_in server_addr; +struct sockaddr_in from_addr; +struct msghdr msg; +struct iovec iov; + + sock_fd2 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + +memset (&server_addr,0 ,sizeof (server_addr)); + server_addr.sin_family =AF_INET ; + server_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + server_addr.sin_port =htons (4000 ); + +SAFE_BIND (sock_fd2, (struct sockaddr *) &server_addr,sizeof (server_addr)); + + msg.msg_name = &from_addr; + msg.msg_namelen =sizeof (from_addr) +16 ; + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = recv_buf; + msg.msg_iov->iov_len =128 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +TST_CHECKPOINT_WAKE (0 ); + +TEST (recvmsg (sock_fd2, &msg,0 )); +if (TEST_RETURN ==-1 ) { +tst_brk (TBROK |TTERRNO , +"recvmsg() failed to recvice data from client" ); + } + +if (msg.msg_namelen !=sizeof (from_addr)) { +tst_res (TFAIL ,"msg_namelen was set to %u incorrectly, " +"expected %lu" , msg.msg_namelen,sizeof (from_addr)); + }else { +tst_res (TPASS ,"msg_namelen was set to %u correctly" , + msg.msg_namelen); + } + +SAFE_CLOSE (sock_fd2); +} + +static void verify_recvmsg (void ) +{ +pid_t pid; + + pid =SAFE_FORK (); +if (pid ==0 ) { +TST_CHECKPOINT_WAIT (0 ); +client (); + }else { +server (); +tst_reap_children (); + } +} + +static struct tst_test test = { + .tid ="recvmsg03" , + .forks_child =1 , + .needs_checkpoints =1 , + .setup = setup, + .test_all = verify_recvmsg +};
PATCH v3 1/1 syscalls/recvmsg03.c: add new testcase
Hi!
Quoted 3 lines
Hi Cyril!
Ping :-)
Any hints on what distribution is this bug reproducible? I've looked around my collection of virtual machines and everything is either too old or too new.
Signature · 2 lines
Cyril Hrubis [email protected]
PATCH v3 1/1 syscalls/recvmsg03.c: add new testcase
Quoted 8 lines · Cyril Hrubis
Hi!
Quoted 3 lines
Hi Cyril!
Ping :-)
Any hints on what distribution is this bug reproducible? I've looked around my collection of virtual machines and everything is either too old or too new.
Hi cyril
When I built kernel with CONFIG_RDS enabled, I have tested it and reproduced this bug on
v3.5 kernel without the fix patch.
I will resend the v3 patch because we need to make sure that recvmsg() can succeed to get data.
Thanks,
Xiao Yang
PATCH v3 1/1 syscalls/recvmsg03.c: add new testcase
In reply to Cyril HrubisIf the size of address for receiving data is set larger than actaul size, recvmsg() will set msg_namelen incorrectly.
This bug has been fixed by the following kernel patch:
'commit 06b6a1cf6e77 ("rds: set correct msg_namelen")'
--- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/recvmsg/recvmsg03.c | 170 ++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 testcases/kernel/syscalls/recvmsg/recvmsg03.c
runtest/syscalls +1 -0
@@ -869,6 +869,7 @@ recvfrom01 recvfrom01 recvmsg01 recvmsg01 recvmsg02 recvmsg02 +recvmsg03 recvmsg03 remap_file_pages01 remap_file_pages01 remap_file_pages02 remap_file_pages02
testcases/kernel/syscalls/.gitignore +1 -0
@@ -724,6 +724,7 @@ /recvfrom/recvfrom01 /recvmsg/recvmsg01 /recvmsg/recvmsg02 +/recvmsg/recvmsg03 /remap_file_pages/remap_file_pages01 /remap_file_pages/remap_file_pages02 /removexattr/removexattr01
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +170 -0
170 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH v3 1/1 syscalls/recvmsg03.c: add new testcase
Hi Cyril
ping:-)
When I built kernel with CONFIG_RDS enabled, I have tested it and reproduced this bug on
v3.5 kernel without the fix patch.
Thanks,
Xiao Yang
Quoted 214 lines · Xiao Yang
If the size of address for receiving data is set larger than actaul size,
recvmsg()will setmsg_namelenincorrectly.This bug has been fixed by the following kernel patch:
'commit06b6a1cf6e77("rds: set correctmsg_namelen")'Signed-off-by Xiao Yang <[email protected]>--- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/recvmsg/recvmsg03.c | 170 ++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 testcases/kernel/syscalls/recvmsg/recvmsg03.cruntest/syscalls +1
-0@@ -869,6 +869,7 @@ recvfrom01 recvfrom01 recvmsg01 recvmsg01 recvmsg02 recvmsg02 +recvmsg03 recvmsg03 remap_file_pages01 remap_file_pages01 remap_file_pages02 remap_file_pages02testcases/kernel/syscalls/.gitignore +1
-0@@ -724,6 +724,7 @@ /recvfrom/recvfrom01 /recvmsg/recvmsg01 /recvmsg/recvmsg02 +/recvmsg/recvmsg03 /remap_file_pages/remap_file_pages01 /remap_file_pages/remap_file_pages02 /removexattr/removexattr01testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +170
-0@@ -0,0 +1,170 @@ +/* +* Copyright(c) 2016 Fujitsu Ltd. +* Author: Xiao Yang <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it would be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* +* You should have received a copy of the GNU General Public License +* alone with this program. +*/ + +/* +* Test Name: recvmsg03 +* +* This test needs that rds socket is supported by system. +* If the size of address for receiving data is set larger than +* actaul size, recvmsg() will set msg_namelen incorrectly. +* +* Description: +* This is a regression test and has been fixed by kernel commit: +* 06b6a1cf6e776426766298d055bb3991957d90a7 (rds: set correct msg_namelen) +*/ + +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "tst_test.h" + +#ifndef AF_RDS +# define AF_RDS 21 +#endif + +static void setup (void ) +{ +int res; + + res =socket (AF_RDS ,SOCK_SEQPACKET ,0 ); +if (res ==-1 ) { +if (errno ==EAFNOSUPPORT ) +tst_brk (TCONF ,"rds was not supported" ); +else +tst_brk (TBROK |TERRNO ,"socket() failed with rds" ); + } + +SAFE_CLOSE (res); +} + +static void client (void ) +{ +TST_CHECKPOINT_WAIT (0 ); + +int sock_fd1, count; +char send_buf[128 ] ="hello world" ; +struct sockaddr_in server_addr; +struct sockaddr_in to_addr; +struct msghdr msg; +struct iovec iov; + + sock_fd1 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + +memset (&server_addr,0 ,sizeof (server_addr)); + server_addr.sin_family =AF_INET ; + server_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + server_addr.sin_port =htons (4001 ); + +SAFE_BIND (sock_fd1, (struct sockaddr *) &server_addr,sizeof (server_addr)); + +memset (&to_addr,0 ,sizeof (to_addr)); + + to_addr.sin_family =AF_INET ; + to_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + to_addr.sin_port =htons (4000 ); + msg.msg_name = &to_addr; + msg.msg_namelen =sizeof (to_addr); + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = send_buf; + msg.msg_iov->iov_len =strlen (send_buf) +1 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +/* make sure that recvmsg() can succeed to get data. +* we may not send data successfully when loading rds +* module for the first time. +*/ +for (count =1 ; count <5000 ; count++) { +if (sendmsg (sock_fd1, &msg,0 ) ==-1 ) { +tst_brk (TBROK |TERRNO , +"sendmsg() failed to send data to server" ); + } + } + +SAFE_CLOSE (sock_fd1); +} + +static void server (void ) +{ +int sock_fd2; +static char recv_buf[128 ]; +struct sockaddr_in server_addr; +struct sockaddr_in from_addr; +struct msghdr msg; +struct iovec iov; + + sock_fd2 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + +memset (&server_addr,0 ,sizeof (server_addr)); + server_addr.sin_family =AF_INET ; + server_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + server_addr.sin_port =htons (4000 ); + +SAFE_BIND (sock_fd2, (struct sockaddr *) &server_addr,sizeof (server_addr)); + + msg.msg_name = &from_addr; + msg.msg_namelen =sizeof (from_addr) +16 ; + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = recv_buf; + msg.msg_iov->iov_len =128 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +TST_CHECKPOINT_WAKE (0 ); + +TEST (recvmsg (sock_fd2, &msg,0 )); +if (TEST_RETURN ==-1 ) { +tst_brk (TBROK |TTERRNO , +"recvmsg() failed to recvice data from client" ); + } + +if (msg.msg_namelen !=sizeof (from_addr)) { +tst_res (TFAIL ,"msg_namelen was set to %u incorrectly, " +"expected %lu" , msg.msg_namelen,sizeof (from_addr)); + }else { +tst_res (TPASS ,"msg_namelen was set to %u correctly" , + msg.msg_namelen); + } + +SAFE_CLOSE (sock_fd2); +} + +static void verify_recvmsg (void ) +{ +pid_t pid; + + pid =SAFE_FORK (); +if (pid ==0 ) { +client (); + }else { +server (); +tst_reap_children (); + } +} + +static struct tst_test test = { + .tid ="recvmsg03" , + .forks_child =1 , + .needs_checkpoints =1 , + .setup = setup, + .test_all = verify_recvmsg +};
PATCH v3 1/1 syscalls/recvmsg03.c: add new testcase
Hi!
Quoted 5 lines
ping:-)
When I built kernel with
CONFIG_RDSenabled, I have tested it and reproduced this bug on
v3.5 kernel without the fix patch.
Pushed, thanks.
Signature · 2 lines
Cyril Hrubis [email protected]
PATCH v2 1/1 syscalls/recvmsg03.c: add new testcase
In reply to Cyril HrubisQuoted 57 lines · Cyril Hrubis
Hi!
Quoted 44 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +44
-0+static void server (void ) +{ +int sock_fd, sock_fd2; +static char recv_buf[128 ]; +struct sockaddr_in server_addr; +struct sockaddr_in from_addr; +struct msghdr msg; +struct iovec iov; + + sock_fd2 =SAFE_SOCKET (AF_RDS ,SOCK_SEQPACKET ,0 ); + sock_fd = sock_fd2; + +memset (&server_addr,0 ,sizeof (server_addr)); + server_addr.sin_family =AF_INET ; + server_addr.sin_addr.s_addr =inet_addr ("127.0.0.1" ); + server_addr.sin_port =htons (4000 ); + +SAFE_BIND (sock_fd2, (struct sockaddr *)&server_addr,sizeof (server_addr)); + + msg.msg_name =&from_addr; + msg.msg_namelen =sizeof (from_addr) +16 ; + msg.msg_iov =&iov; + msg.msg_iovlen =1 ; + msg.msg_iov->iov_base = recv_buf; + msg.msg_iov->iov_len =128 ; + msg.msg_control =0 ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + +TST_CHECKPOINT_WAKE (0 ); + +TEST (recvmsg (sock_fd2,&msg,0 )); +if (TEST_RETURN ==-1 ) { +tst_res (TFAIL |TERRNO , +"recvmsg() failed to recvice data from client" ); + goto end; + } + +if (msg.msg_namelen !=sizeof (from_addr)) { +tst_res (TFAIL ,"msg_namelen was set to %u incorrectly, " +"expected %lu" , msg.msg_namelen,sizeof (from_addr)); + goto end; + } +testcases/kernel/syscalls/recvmsg/recvmsg03.c line 149
Quoted 10 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +10
-0+if (sock_fd2 != sock_fd) { +tst_res (TFAIL ,"sock_fd was destroyed" ); + goto end; + } + +tst_res (TPASS ,"msg_namelen was set to %u correctly and sock_fd was " +"not destroyed" , msg.msg_namelen); + +end: +SAFE_CLOSE (sock_fd2);I'm a bit confused here, which one of the sock_fd/sock_fd2 is destroyed?
Quoted 6 lines
Looking at the original code in the kernel commit the
sock_fdthere is stored on the stack directly after thesockaddr_infrom_addrso I guess that the kernel will actually write a few bytes after the end offrom_addrstructure in this case, which will rewrite the msghrd msg in your code. Does the test actually fail on kernel without the fix?
Hi Cyril
I am sorry for the late response. the msghrd msg was rewritten but sock_fd2 was not destroyed
on v3.5 kernel without the fix patch, so i will remove the code about checking sock_fd.
Thanks,
Xiao Yang
Quoted 32 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c line 162
Quoted 13 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +13
-0+} + +static void verify_recvmsg (void ) +{ +pid_t pid; + + pid =SAFE_FORK (); +if (pid ==0 ) { +TST_CHECKPOINT_WAIT (0 ); +client (); + }else { +server (); +SAFE_WAIT (NULL );We should rather call
tst_reap_children()in this case instead of the WAIT since otherwise TBROK from theclient()function will not get propagated.Quoted 15 lines
testcases/kernel/syscalls/recvmsg/recvmsg03.c new file +10
-0+ } +} + +static struct tst_test test = { + .tid ="recvmsg03" , + .forks_child =1 , + .needs_checkpoints =1 , + .setup = setup, + .test_all = verify_recvmsg +};Signature · 1 line
1.8.3.1