2012-08-10 17:31:14 +04:00
/*
2013-02-23 02:42:39 +04:00
* Copyright ( C ) 2011 - 2013 Red Hat , Inc .
2012-08-10 17:31:14 +04:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
2012-09-21 02:30:55 +04:00
* License along with this library . If not , see
2012-08-10 17:31:14 +04:00
* < http : //www.gnu.org/licenses/>.
*
*/
# include <config.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
# include <selinux/selinux.h>
# include <selinux/context.h>
# include "internal.h"
# include "testutils.h"
2012-12-12 22:06:53 +04:00
# include "viralloc.h"
2012-12-12 21:59:27 +04:00
# include "virlog.h"
2012-12-13 22:21:53 +04:00
# include "virerror.h"
2013-05-09 22:59:04 +04:00
# include "virfile.h"
2012-08-10 17:31:14 +04:00
# include "security/security_manager.h"
2013-04-03 14:36:23 +04:00
# include "virstring.h"
2012-08-10 17:31:14 +04:00
# define VIR_FROM_THIS VIR_FROM_NONE
2014-02-28 16:16:17 +04:00
VIR_LOG_INIT ( " tests.securityselinuxtest " ) ;
2012-08-10 17:31:14 +04:00
struct testSELinuxGenLabelData {
virSecurityManagerPtr mgr ;
const char * pidcon ;
bool dynamic ;
const char * label ;
const char * baselabel ;
const char * user ;
const char * role ;
const char * imagerole ;
const char * type ;
const char * imagetype ;
int sensMin ;
int sensMax ;
int catMin ;
int catMax ;
} ;
static virDomainDefPtr
testBuildDomainDef ( bool dynamic ,
const char * label ,
const char * baselabel )
{
virDomainDefPtr def ;
virSecurityLabelDefPtr secdef ;
if ( VIR_ALLOC ( def ) < 0 )
2013-07-04 14:20:21 +04:00
goto error ;
2012-08-10 17:31:14 +04:00
if ( VIR_ALLOC_N ( def - > seclabels , 1 ) < 0 )
2013-07-04 14:20:21 +04:00
goto error ;
2012-08-10 17:31:14 +04:00
if ( VIR_ALLOC ( secdef ) < 0 )
2013-07-04 14:20:21 +04:00
goto error ;
2012-08-10 17:31:14 +04:00
2012-12-19 14:05:17 +04:00
def - > virtType = VIR_DOMAIN_VIRT_KVM ;
2012-08-10 17:31:14 +04:00
def - > seclabels [ 0 ] = secdef ;
def - > seclabels [ 0 ] - > type = dynamic ? VIR_DOMAIN_SECLABEL_DYNAMIC : VIR_DOMAIN_SECLABEL_STATIC ;
if ( label & &
2013-05-03 16:52:21 +04:00
VIR_STRDUP ( def - > seclabels [ 0 ] - > label , label ) < 0 )
goto error ;
2012-08-10 17:31:14 +04:00
if ( baselabel & &
2013-05-03 16:52:21 +04:00
VIR_STRDUP ( def - > seclabels [ 0 ] - > baselabel , baselabel ) < 0 )
goto error ;
2012-08-10 17:31:14 +04:00
return def ;
2014-03-25 10:53:44 +04:00
error :
2012-08-10 17:31:14 +04:00
virDomainDefFree ( def ) ;
return NULL ;
}
static bool
testSELinuxCheckCon ( context_t con ,
const char * user ,
const char * role ,
const char * type ,
int sensMin ,
int sensMax ATTRIBUTE_UNUSED ,
int catMin ,
int catMax )
{
const char * range ;
char * tmp ;
int gotSens ;
int gotCatOne ;
int gotCatTwo ;
if ( STRNEQ ( context_user_get ( con ) , user ) ) {
fprintf ( stderr , " Expect user %s got %s \n " ,
user , context_user_get ( con ) ) ;
return false ;
}
if ( STRNEQ ( context_role_get ( con ) , role ) ) {
fprintf ( stderr , " Expect role %s got %s \n " ,
role , context_role_get ( con ) ) ;
return false ;
}
if ( STRNEQ ( context_type_get ( con ) , type ) ) {
fprintf ( stderr , " Expect type %s got %s \n " ,
type , context_type_get ( con ) ) ;
return false ;
}
range = context_range_get ( con ) ;
if ( range [ 0 ] ! = ' s ' ) {
fprintf ( stderr , " Malformed range %s, cannot find sensitivity \n " ,
range ) ;
return false ;
}
if ( virStrToLong_i ( range + 1 , & tmp , 10 , & gotSens ) < 0 | |
! tmp ) {
fprintf ( stderr , " Malformed range %s, cannot parse sensitivity \n " ,
range + 1 ) ;
return false ;
}
if ( * tmp ! = ' : ' ) {
fprintf ( stderr , " Malformed range %s, too many sensitivity values \n " ,
tmp ) ;
return false ;
}
tmp + + ;
if ( * tmp ! = ' c ' ) {
fprintf ( stderr , " Malformed range %s, cannot find first category \n " ,
tmp ) ;
return false ;
}
tmp + + ;
if ( virStrToLong_i ( tmp , & tmp , 10 , & gotCatOne ) < 0 ) {
fprintf ( stderr , " Malformed range %s, cannot parse category one \n " ,
tmp ) ;
return false ;
}
if ( tmp & & * tmp = = ' , ' )
tmp + + ;
if ( tmp & & * tmp = = ' c ' ) {
tmp + + ;
if ( virStrToLong_i ( tmp , & tmp , 10 , & gotCatTwo ) < 0 ) {
fprintf ( stderr , " Malformed range %s, cannot parse category two \n " ,
tmp ) ;
return false ;
}
if ( * tmp ! = ' \0 ' ) {
fprintf ( stderr , " Malformed range %s, junk after second category \n " ,
tmp ) ;
return false ;
}
if ( gotCatOne = = gotCatTwo ) {
fprintf ( stderr , " Saw category pair %d,%d where cats were equal \n " ,
gotCatOne , gotCatTwo ) ;
return false ;
}
} else {
gotCatTwo = gotCatOne ;
}
if ( gotSens ! = sensMin ) {
fprintf ( stderr , " Sensitivity %d is not equal to min %d \n " ,
gotSens , sensMin ) ;
return false ;
}
if ( gotCatOne < catMin | |
gotCatOne > catMax ) {
fprintf ( stderr , " Category one %d is out of range %d-%d \n " ,
gotCatTwo , catMin , catMax ) ;
return false ;
}
if ( gotCatTwo < catMin | |
gotCatTwo > catMax ) {
fprintf ( stderr , " Category two %d is out of range %d-%d \n " ,
gotCatTwo , catMin , catMax ) ;
return false ;
}
if ( gotCatOne > gotCatTwo ) {
fprintf ( stderr , " Category one %d is greater than category two %d \n " ,
gotCatOne , gotCatTwo ) ;
return false ;
}
return true ;
}
static int
testSELinuxGenLabel ( const void * opaque )
{
const struct testSELinuxGenLabelData * data = opaque ;
int ret = - 1 ;
virDomainDefPtr def ;
context_t con = NULL ;
context_t imgcon = NULL ;
2012-10-05 18:41:22 +04:00
if ( setcon_raw ( ( security_context_t ) data - > pidcon ) < 0 ) {
2012-08-10 17:31:14 +04:00
perror ( " Cannot set process security context " ) ;
return - 1 ;
}
if ( ! ( def = testBuildDomainDef ( data - > dynamic ,
data - > label ,
data - > baselabel ) ) )
goto cleanup ;
if ( virSecurityManagerGenLabel ( data - > mgr , def ) < 0 ) {
virErrorPtr err = virGetLastError ( ) ;
2013-06-04 15:01:03 +04:00
fprintf ( stderr , " Cannot generate label: %s \n " , err - > message ) ;
2012-08-10 17:31:14 +04:00
goto cleanup ;
}
VIR_DEBUG ( " label=%s imagelabel=%s " ,
def - > seclabels [ 0 ] - > label , def - > seclabels [ 0 ] - > imagelabel ) ;
if ( ! ( con = context_new ( def - > seclabels [ 0 ] - > label ) ) )
goto cleanup ;
if ( ! ( imgcon = context_new ( def - > seclabels [ 0 ] - > imagelabel ) ) )
goto cleanup ;
if ( ! testSELinuxCheckCon ( con ,
data - > user , data - > role , data - > type ,
data - > sensMin , data - > sensMax ,
data - > catMin , data - > catMax ) )
goto cleanup ;
if ( ! testSELinuxCheckCon ( imgcon ,
data - > user , data - > imagerole , data - > imagetype ,
data - > sensMin , data - > sensMax ,
data - > catMin , data - > catMax ) )
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2012-08-10 17:31:14 +04:00
context_free ( con ) ;
context_free ( imgcon ) ;
virDomainDefFree ( def ) ;
return ret ;
}
static int
mymain ( void )
{
int ret = 0 ;
virSecurityManagerPtr mgr ;
if ( ! ( mgr = virSecurityManagerNew ( " selinux " , " QEMU " , false , true , false ) ) ) {
virErrorPtr err = virGetLastError ( ) ;
fprintf ( stderr , " Unable to initialize security driver: %s \n " ,
err - > message ) ;
2013-02-23 02:42:39 +04:00
return EXIT_FAILURE ;
2012-08-10 17:31:14 +04:00
}
# define DO_TEST_GEN_LABEL(desc, pidcon, \
dynamic , label , baselabel , \
user , role , imageRole , \
type , imageType , \
sensMin , sensMax , catMin , catMax ) \
do { \
struct testSELinuxGenLabelData data = { \
mgr , pidcon , dynamic , label , baselabel , \
user , role , imageRole , type , imageType , \
sensMin , sensMax , catMin , catMax \
} ; \
2013-09-20 22:13:35 +04:00
if ( virtTestRun ( " GenLabel " # desc , testSELinuxGenLabel , & data ) < 0 ) \
2012-08-10 17:31:14 +04:00
ret = - 1 ; \
} while ( 0 )
2013-03-13 21:58:26 +04:00
DO_TEST_GEN_LABEL ( " dynamic unconfined, s0, c0.c1023 " ,
" unconfined_u:unconfined_r:unconfined_t:s0 " ,
true , NULL , NULL ,
" unconfined_u " , " unconfined_r " , " object_r " ,
" svirt_t " , " svirt_image_t " ,
0 , 0 , 0 , 1023 ) ;
DO_TEST_GEN_LABEL ( " dynamic unconfined, s0, c0.c1023 " ,
" unconfined_u:unconfined_r:unconfined_t:s0-s0 " ,
true , NULL , NULL ,
" unconfined_u " , " unconfined_r " , " object_r " ,
" svirt_t " , " svirt_image_t " ,
0 , 0 , 0 , 1023 ) ;
2012-08-10 17:31:14 +04:00
DO_TEST_GEN_LABEL ( " dynamic unconfined, s0, c0.c1023 " ,
" unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 " ,
true , NULL , NULL ,
" unconfined_u " , " unconfined_r " , " object_r " ,
" svirt_t " , " svirt_image_t " ,
0 , 0 , 0 , 1023 ) ;
DO_TEST_GEN_LABEL ( " dynamic virtd, s0, c0.c1023 " ,
" system_u:system_r:virtd_t:s0-s0:c0.c1023 " ,
true , NULL , NULL ,
" system_u " , " system_r " , " object_r " ,
" svirt_t " , " svirt_image_t " ,
0 , 0 , 0 , 1023 ) ;
DO_TEST_GEN_LABEL ( " dynamic virtd, s0, c0.c10 " ,
" system_u:system_r:virtd_t:s0-s0:c0.c10 " ,
true , NULL , NULL ,
" system_u " , " system_r " , " object_r " ,
" svirt_t " , " svirt_image_t " ,
0 , 0 , 0 , 10 ) ;
DO_TEST_GEN_LABEL ( " dynamic virtd, s2-s3, c0.c1023 " ,
" system_u:system_r:virtd_t:s2-s3:c0.c1023 " ,
true , NULL , NULL ,
" system_u " , " system_r " , " object_r " ,
" svirt_t " , " svirt_image_t " ,
2 , 3 , 0 , 1023 ) ;
2013-06-10 16:37:40 +04:00
DO_TEST_GEN_LABEL ( " dynamic virtd, missing range " ,
" system_u:system_r:virtd_t " ,
true , NULL , NULL ,
" system_u " , " system_r " , " object_r " ,
" svirt_t " , " svirt_image_t " ,
0 , 0 , 0 , 1023 ) ;
2012-08-10 17:31:14 +04:00
return ( ret = = 0 ) ? EXIT_SUCCESS : EXIT_FAILURE ;
}
VIRT_TEST_MAIN_PRELOAD ( mymain , abs_builddir " /.libs/libsecurityselinuxhelper.so " )