2017-07-08 19:27:26 +00:00
/*
* Check decoding of SO_PEERCRED socket option .
*
* Copyright ( c ) 2017 Dmitry V . Levin < ldv @ altlinux . org >
2018-06-14 11:00:00 +00:00
* Copyright ( c ) 2017 - 2018 The strace developers .
2017-07-08 19:27:26 +00:00
* All rights reserved .
*
2018-12-10 00:00:00 +00:00
* SPDX - License - Identifier : GPL - 2.0 - or - later
2017-07-08 19:27:26 +00:00
*/
# include "tests.h"
# include <stddef.h>
# include <stdio.h>
2018-07-17 22:07:40 +00:00
# include <string.h>
2017-07-08 19:27:26 +00:00
# include <sys/socket.h>
# include <unistd.h>
# include "print_fields.h"
static const char * errstr ;
static int
get_peercred ( int fd , void * val , socklen_t * len )
{
int rc = getsockopt ( fd , SOL_SOCKET , SO_PEERCRED , val , len ) ;
errstr = sprintrc ( rc ) ;
return rc ;
}
2018-04-11 19:34:31 +02:00
static const char *
so_str ( void )
{
static char buf [ 256 ] ;
if ( ! buf [ 0 ] ) {
# if XLAT_RAW
snprintf ( buf , sizeof ( buf ) ,
" %#x, %#x " , SOL_SOCKET , SO_PEERCRED ) ;
# elif XLAT_VERBOSE
snprintf ( buf , sizeof ( buf ) ,
" %#x /* SOL_SOCKET */, %#x /* SO_PEERCRED */ " ,
SOL_SOCKET , SO_PEERCRED ) ;
# else
snprintf ( buf , sizeof ( buf ) ,
" SOL_SOCKET, SO_PEERCRED " ) ;
# endif
}
return buf ;
}
2017-07-08 19:27:26 +00:00
int
main ( void )
{
TAIL_ALLOC_OBJECT_CONST_PTR ( struct ucred , peercred ) ;
TAIL_ALLOC_OBJECT_CONST_PTR ( socklen_t , len ) ;
2018-07-17 22:07:40 +00:00
const unsigned int sizeof_pid = sizeof ( peercred - > pid ) ;
struct ucred * const pid = tail_alloc ( sizeof_pid ) ;
const unsigned int sizeof_pid_truncated = sizeof_pid - 1 ;
struct ucred * const pid_truncated =
tail_alloc ( sizeof_pid_truncated ) ;
const unsigned int sizeof_uid = offsetofend ( struct ucred , uid ) ;
struct ucred * const uid = tail_alloc ( sizeof_uid ) ;
const unsigned int sizeof_uid_truncated = sizeof_uid - 1 ;
struct ucred * const uid_truncated =
tail_alloc ( sizeof_uid_truncated ) ;
const unsigned int sizeof_gid_truncated =
offsetofend ( struct ucred , gid ) - 1 ;
struct ucred * const gid_truncated =
tail_alloc ( sizeof_gid_truncated ) ;
2017-07-08 19:27:26 +00:00
int sv [ 2 ] ;
if ( socketpair ( AF_UNIX , SOCK_STREAM , 0 , sv ) )
perror_msg_and_skip ( " socketpair AF_UNIX SOCK_STREAM " ) ;
/* classic getsockopt */
* len = sizeof ( * peercred ) ;
get_peercred ( sv [ 0 ] , peercred , len ) ;
2018-04-11 19:34:31 +02:00
printf ( " getsockopt(%d, %s " , sv [ 0 ] , so_str ( ) ) ;
2017-07-08 19:27:26 +00:00
PRINT_FIELD_D ( " , { " , * peercred , pid ) ;
PRINT_FIELD_UID ( " , " , * peercred , uid ) ;
PRINT_FIELD_UID ( " , " , * peercred , gid ) ;
printf ( " }, [%d]) = %s \n " , * len , errstr ) ;
2018-07-17 22:07:40 +00:00
/* getsockopt with zero optlen */
* len = 0 ;
get_peercred ( sv [ 0 ] , peercred , len ) ;
printf ( " getsockopt(%d, %s, %p, [0]) = %s \n " ,
sv [ 0 ] , so_str ( ) , peercred , errstr ) ;
2017-07-08 19:27:26 +00:00
/* getsockopt with optlen larger than necessary - shortened */
* len = sizeof ( * peercred ) + 1 ;
2018-07-17 22:07:40 +00:00
get_peercred ( sv [ 0 ] , peercred , len ) ;
printf ( " getsockopt(%d, %s " , sv [ 0 ] , so_str ( ) ) ;
2017-07-08 19:27:26 +00:00
PRINT_FIELD_D ( " , { " , * peercred , pid ) ;
PRINT_FIELD_UID ( " , " , * peercred , uid ) ;
PRINT_FIELD_UID ( " , " , * peercred , gid ) ;
printf ( " }, [%u->%d]) = %s \n " ,
( unsigned int ) sizeof ( * peercred ) + 1 , * len , errstr ) ;
2018-07-17 22:07:40 +00:00
/*
* getsockopt with optlen less than offsetofend ( struct ucred , pid ) :
* the part of struct ucred . pid is printed in hex .
*/
* len = sizeof_pid_truncated ;
get_peercred ( sv [ 0 ] , pid_truncated , len ) ;
printf ( " getsockopt(%d, %s, {pid= " , sv [ 0 ] , so_str ( ) ) ;
print_quoted_hex ( pid_truncated , * len ) ;
printf ( " }, [%d]) = %s \n " , * len , errstr ) ;
/*
* getsockopt with optlen equals to sizeof ( struct ucred . pid ) :
* struct ucred . uid and struct ucred . gid are not printed .
*/
* len = sizeof_pid ;
get_peercred ( sv [ 0 ] , pid , len ) ;
printf ( " getsockopt(%d, %s " , sv [ 0 ] , so_str ( ) ) ;
PRINT_FIELD_D ( " , { " , * pid , pid ) ;
printf ( " }, [%d]) = %s \n " , * len , errstr ) ;
/*
* getsockopt with optlen greater than sizeof ( struct ucred . pid )
* but smaller than offsetofend ( struct ucred , uid ) :
* the part of struct ucred . uid is printed in hex .
*/
* len = sizeof_uid_truncated ;
get_peercred ( sv [ 0 ] , uid_truncated , len ) ;
/*
* Copy to a properly aligned structure to avoid unaligned access
* to struct ucred . pid field .
*/
memcpy ( uid , uid_truncated , sizeof_uid_truncated ) ;
printf ( " getsockopt(%d, %s " , sv [ 0 ] , so_str ( ) ) ;
PRINT_FIELD_D ( " , { " , * uid , pid ) ;
printf ( " , uid= " ) ;
print_quoted_hex ( & uid - > uid , sizeof_uid_truncated -
offsetof ( struct ucred , uid ) ) ;
2017-07-08 19:27:26 +00:00
printf ( " }, [%d]) = %s \n " , * len , errstr ) ;
2018-07-17 22:07:40 +00:00
/*
* getsockopt with optlen equals to offsetofend ( struct ucred , uid ) :
* struct ucred . gid is not printed .
*/
* len = sizeof_uid ;
get_peercred ( sv [ 0 ] , uid , len ) ;
printf ( " getsockopt(%d, %s " , sv [ 0 ] , so_str ( ) ) ;
PRINT_FIELD_D ( " , { " , * uid , pid ) ;
PRINT_FIELD_UID ( " , " , * uid , uid ) ;
printf ( " }, [%d]) = %s \n " , * len , errstr ) ;
/*
* getsockopt with optlen greater than sizeof ( struct ucred . uid )
* but smaller than offsetofend ( struct ucred , gid ) :
* the part of struct ucred . gid is printed in hex .
*/
* len = sizeof_gid_truncated ;
get_peercred ( sv [ 0 ] , gid_truncated , len ) ;
/*
* Copy to a properly aligned structure to avoid unaligned access
* to struct ucred . pid and struct ucred . uid fields .
*/
memcpy ( peercred , gid_truncated , sizeof_gid_truncated ) ;
printf ( " getsockopt(%d, %s " , sv [ 0 ] , so_str ( ) ) ;
2017-07-08 19:27:26 +00:00
PRINT_FIELD_D ( " , { " , * peercred , pid ) ;
PRINT_FIELD_UID ( " , " , * peercred , uid ) ;
2018-07-17 22:07:40 +00:00
printf ( " , gid= " ) ;
print_quoted_hex ( & peercred - > gid , sizeof_gid_truncated -
offsetof ( struct ucred , gid ) ) ;
2017-07-08 19:27:26 +00:00
printf ( " }, [%d]) = %s \n " , * len , errstr ) ;
/* getsockopt optval EFAULT */
* len = sizeof ( * peercred ) ;
2018-07-17 22:07:40 +00:00
get_peercred ( sv [ 0 ] , & peercred - > uid , len ) ;
2018-04-11 19:34:31 +02:00
printf ( " getsockopt(%d, %s, %p, [%d]) = %s \n " ,
2018-07-17 22:07:40 +00:00
sv [ 0 ] , so_str ( ) , & peercred - > uid , * len , errstr ) ;
2017-07-08 19:27:26 +00:00
/* getsockopt optlen EFAULT */
2018-07-17 22:07:40 +00:00
get_peercred ( sv [ 0 ] , peercred , len + 1 ) ;
2018-04-11 19:34:31 +02:00
printf ( " getsockopt(%d, %s, %p, %p) = %s \n " ,
2018-07-17 22:07:40 +00:00
sv [ 0 ] , so_str ( ) , peercred , len + 1 , errstr ) ;
2017-07-08 19:27:26 +00:00
puts ( " +++ exited with 0 +++ " ) ;
return 0 ;
}