2016-07-14 00:56:40 +03:00
/*
* Check decoding of struct msghdr . msg_name * arguments of recvmsg syscall .
*
* Copyright ( c ) 2016 Dmitry V . Levin < ldv @ altlinux . org >
2017-05-22 20:14:52 +03:00
* Copyright ( c ) 2016 - 2017 The strace developers .
2016-07-14 00:56:40 +03:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "tests.h"
# include <stddef.h>
# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include <sys/socket.h>
# include <sys/un.h>
static int
send_recv ( const int send_fd , const int recv_fd ,
struct msghdr * const msg , const int flags )
{
if ( send ( send_fd , " A " , 1 , 0 ) ! = 1 )
perror_msg_and_skip ( " send " ) ;
return recvmsg ( recv_fd , msg , flags ) ;
}
static void
test_msg_name ( const int send_fd , const int recv_fd )
{
2017-03-16 16:46:36 +03:00
TAIL_ALLOC_OBJECT_CONST_PTR ( char , recv_buf ) ;
TAIL_ALLOC_OBJECT_CONST_PTR ( struct iovec , iov ) ;
2016-07-14 00:56:40 +03:00
iov - > iov_base = recv_buf ;
iov - > iov_len = sizeof ( * recv_buf ) ;
2017-03-16 16:46:36 +03:00
TAIL_ALLOC_OBJECT_CONST_PTR ( struct sockaddr_un , addr ) ;
TAIL_ALLOC_OBJECT_CONST_PTR ( struct msghdr , msg ) ;
2016-07-14 00:56:40 +03:00
msg - > msg_name = addr ;
msg - > msg_namelen = sizeof ( * addr ) ;
msg - > msg_iov = iov ;
msg - > msg_iovlen = 1 ;
msg - > msg_control = 0 ;
msg - > msg_controllen = 0 ;
msg - > msg_flags = 0 ;
int rc = send_recv ( send_fd , recv_fd , msg , MSG_DONTWAIT ) ;
if ( rc < 0 )
perror_msg_and_skip ( " recvmsg " ) ;
printf ( " recvmsg(%d, {msg_name={sa_family=AF_UNIX, sun_path= \" %s \" } "
2016-07-14 01:54:55 +03:00
" , msg_namelen=%d->%d, msg_iov=[{iov_base= \" A \" , iov_len=1}] "
" , msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT) "
" = %d \n " ,
2016-07-14 00:56:40 +03:00
recv_fd , addr - > sun_path , ( int ) sizeof ( struct sockaddr_un ) ,
( int ) msg - > msg_namelen , rc ) ;
memset ( addr , 0 , sizeof ( * addr ) ) ;
rc = send_recv ( send_fd , recv_fd , msg , MSG_DONTWAIT ) ;
printf ( " recvmsg(%d, {msg_name={sa_family=AF_UNIX, sun_path= \" %s \" } "
2016-07-14 01:54:55 +03:00
" , msg_namelen=%d, msg_iov=[{iov_base= \" A \" , iov_len=1}] "
" , msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT) "
" = %d \n " ,
2016-07-14 00:56:40 +03:00
recv_fd , addr - > sun_path , ( int ) msg - > msg_namelen , rc ) ;
msg - > msg_name = 0 ;
rc = send_recv ( send_fd , recv_fd , msg , MSG_DONTWAIT ) ;
2016-07-14 01:54:55 +03:00
printf ( " recvmsg(%d, {msg_name=NULL, msg_namelen=%d "
" , msg_iov=[{iov_base= \" A \" , iov_len=1}], msg_iovlen=1 "
2016-07-14 00:56:40 +03:00
" , msg_controllen=0, msg_flags=0}, MSG_DONTWAIT) = %d \n " ,
recv_fd , ( int ) msg - > msg_namelen , rc ) ;
const size_t offsetof_sun_path = offsetof ( struct sockaddr_un , sun_path ) ;
msg - > msg_name = addr ;
msg - > msg_namelen = offsetof_sun_path ;
memset ( addr - > sun_path , ' A ' , sizeof ( addr - > sun_path ) ) ;
rc = send_recv ( send_fd , recv_fd , msg , MSG_DONTWAIT ) ;
2016-07-14 01:54:55 +03:00
printf ( " recvmsg(%d, {msg_name={sa_family=AF_UNIX}, msg_namelen=%d->%d "
" , msg_iov=[{iov_base= \" A \" , iov_len=1}], msg_iovlen=1 "
2016-07-14 00:56:40 +03:00
" , msg_controllen=0, msg_flags=0}, MSG_DONTWAIT) = %d \n " ,
recv_fd , ( int ) offsetof_sun_path , ( int ) msg - > msg_namelen , rc ) ;
msg - > msg_namelen = sizeof ( struct sockaddr ) ;
msg - > msg_name = ( ( void * ) ( addr + 1 ) ) - msg - > msg_namelen ;
rc = send_recv ( send_fd , recv_fd , msg , MSG_DONTWAIT ) ;
printf ( " recvmsg(%d, {msg_name={sa_family=AF_UNIX, sun_path= \" %.*s \" } "
2016-07-14 01:54:55 +03:00
" , msg_namelen=%d->%d, msg_iov=[{iov_base= \" A \" , iov_len=1}] "
" , msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT) "
" = %d \n " ,
2016-07-14 00:56:40 +03:00
recv_fd , ( int ) ( sizeof ( struct sockaddr ) - offsetof_sun_path ) ,
( ( struct sockaddr_un * ) msg - > msg_name ) - > sun_path ,
( int ) sizeof ( struct sockaddr ) , ( int ) msg - > msg_namelen , rc ) ;
rc = send_recv ( send_fd , recv_fd , msg , MSG_DONTWAIT ) ;
printf ( " recvmsg(%d, {msg_namelen=%d}, MSG_DONTWAIT) = %d %s (%m) \n " ,
recv_fd , ( int ) msg - > msg_namelen , rc , errno2name ( ) ) ;
/*
* When recvmsg is called with a valid descriptor
* but inaccessible memory , it causes segfaults on some architectures .
* As in these cases we test decoding of failed recvmsg calls ,
* it ' s ok to fail recvmsg with any reason as long as
* it doesn ' t read that inaccessible memory .
*/
2016-07-14 12:37:09 +03:00
/*
* Sadly , musl recvmsg wrapper blindly dereferences 2 nd argument ,
* so limit this test to glibc that doesn ' t .
*/
# ifdef __GLIBC__
2016-07-14 00:56:40 +03:00
rc = send_recv ( send_fd , - 1 , msg + 1 , 0 ) ;
printf ( " recvmsg(-1, %p, 0) = %d %s (%m) \n " ,
msg + 1 , rc , errno2name ( ) ) ;
2016-07-14 12:37:09 +03:00
# endif
2016-07-14 00:56:40 +03:00
rc = send_recv ( send_fd , - 1 , 0 , 0 ) ;
printf ( " recvmsg(-1, NULL, 0) = %d %s (%m) \n " ,
rc , errno2name ( ) ) ;
}
int
main ( void )
{
int fds [ 2 ] ;
if ( socketpair ( AF_UNIX , SOCK_STREAM , 0 , fds ) )
perror_msg_and_skip ( " socketpair " ) ;
const struct sockaddr_un un = {
. sun_family = AF_UNIX ,
. sun_path = " msg_name-recvmsg.test.send.socket "
} ;
( void ) unlink ( un . sun_path ) ;
if ( bind ( fds [ 1 ] , ( const void * ) & un , sizeof ( un ) ) )
perror_msg_and_skip ( " bind " ) ;
( void ) unlink ( un . sun_path ) ;
test_msg_name ( fds [ 1 ] , fds [ 0 ] ) ;
puts ( " +++ exited with 0 +++ " ) ;
return 0 ;
}