2012-08-10 17:31:14 +04:00
/*
2013-08-14 00:19:14 +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>
2013-08-14 00:19:14 +04:00
/* This file is only compiled on Linux, and only if xattr support was
* detected . */
# include <dlfcn.h>
# include <errno.h>
2013-10-07 13:45:00 +04:00
# if HAVE_LINUX_MAGIC_H
# include <linux / magic.h>
# endif
2012-08-10 17:31:14 +04:00
# include <selinux/selinux.h>
2013-08-14 00:19:14 +04:00
# include <stdio.h>
2012-08-10 17:31:14 +04:00
# include <stdlib.h>
# include <string.h>
2013-08-14 00:19:14 +04:00
# include <sys/vfs.h>
2012-08-10 17:31:14 +04:00
# include <unistd.h>
2013-08-14 00:19:14 +04:00
# include <attr/xattr.h>
2012-09-19 17:00:34 +04:00
2013-10-07 13:45:00 +04:00
# ifndef NFS_SUPER_MAGIC
# define NFS_SUPER_MAGIC 0x6969
# endif
2013-05-03 16:52:21 +04:00
# include "virstring.h"
2012-09-19 17:00:34 +04:00
2013-08-14 00:19:14 +04:00
static int ( * realstatfs ) ( const char * path , struct statfs * buf ) ;
static int ( * realsecurity_get_boolean_active ) ( const char * name ) ;
static void init_syms ( void )
{
if ( realstatfs )
return ;
# define LOAD_SYM(name) \
do { \
if ( ! ( real # # name = dlsym ( RTLD_NEXT , # name ) ) ) { \
fprintf ( stderr , " Cannot find real '%s' symbol \n " , # name ) ; \
abort ( ) ; \
} \
} while ( 0 )
LOAD_SYM ( statfs ) ;
LOAD_SYM ( security_get_boolean_active ) ;
# undef LOAD_SYM
}
2012-08-10 17:31:14 +04:00
/*
* The kernel policy will not allow us to arbitrarily change
* test process context . This helper is used as an LD_PRELOAD
* so that the libvirt code / thinks / it is changing / reading
2013-08-14 00:19:14 +04:00
* the process context , whereas in fact we ' re faking it all .
* Furthermore , we fake out that we are using an nfs subdirectory ,
* where we control whether selinux is enforcing and whether
* the virt_use_nfs bool is set .
2012-08-10 17:31:14 +04:00
*/
2012-10-05 18:41:22 +04:00
int getcon_raw ( security_context_t * context )
2012-08-10 17:31:14 +04:00
{
if ( getenv ( " FAKE_CONTEXT " ) = = NULL ) {
* context = NULL ;
errno = EINVAL ;
return - 1 ;
}
2013-05-03 16:52:21 +04:00
return VIR_STRDUP_QUIET ( * context , getenv ( " FAKE_CONTEXT " ) ) ;
2012-08-10 17:31:14 +04:00
}
2013-01-14 22:33:44 +04:00
int getcon ( security_context_t * context )
{
return getcon_raw ( context ) ;
}
2012-10-05 18:41:22 +04:00
int getpidcon_raw ( pid_t pid , security_context_t * context )
2012-08-10 17:31:14 +04:00
{
if ( pid ! = getpid ( ) ) {
* context = NULL ;
errno = ESRCH ;
return - 1 ;
}
if ( getenv ( " FAKE_CONTEXT " ) = = NULL ) {
* context = NULL ;
errno = EINVAL ;
return - 1 ;
}
2013-05-03 16:52:21 +04:00
return VIR_STRDUP_QUIET ( * context , getenv ( " FAKE_CONTEXT " ) ) ;
2012-08-10 17:31:14 +04:00
}
2013-01-14 22:33:44 +04:00
int getpidcon ( pid_t pid , security_context_t * context )
{
return getpidcon_raw ( pid , context ) ;
}
2012-10-05 18:41:22 +04:00
int setcon_raw ( security_context_t context )
2012-08-10 17:31:14 +04:00
{
return setenv ( " FAKE_CONTEXT " , context , 1 ) ;
}
2012-09-19 17:00:34 +04:00
2013-01-14 22:33:44 +04:00
int setcon ( security_context_t context )
{
return setcon_raw ( context ) ;
}
2012-09-19 17:00:34 +04:00
2013-01-14 22:33:44 +04:00
int setfilecon_raw ( const char * path , security_context_t con )
2012-09-19 17:00:34 +04:00
{
const char * constr = con ;
2013-08-14 00:19:14 +04:00
if ( STRPREFIX ( path , abs_builddir " /securityselinuxlabeldata/nfs/ " ) ) {
errno = EOPNOTSUPP ;
return - 1 ;
}
2012-09-19 17:00:34 +04:00
return setxattr ( path , " user.libvirt.selinux " ,
constr , strlen ( constr ) , 0 ) ;
}
2013-01-14 22:33:44 +04:00
int setfilecon ( const char * path , security_context_t con )
{
return setfilecon_raw ( path , con ) ;
}
2012-09-19 17:00:34 +04:00
2013-01-14 22:33:44 +04:00
int getfilecon_raw ( const char * path , security_context_t * con )
2012-09-19 17:00:34 +04:00
{
char * constr = NULL ;
ssize_t len = getxattr ( path , " user.libvirt.selinux " ,
NULL , 0 ) ;
2013-08-14 00:19:14 +04:00
if ( STRPREFIX ( path , abs_builddir " /securityselinuxlabeldata/nfs/ " ) ) {
errno = EOPNOTSUPP ;
return - 1 ;
}
2012-09-19 17:00:34 +04:00
if ( len < 0 )
return - 1 ;
if ( ! ( constr = malloc ( len + 1 ) ) )
return - 1 ;
memset ( constr , 0 , len ) ;
if ( getxattr ( path , " user.libvirt.selinux " , constr , len ) < 0 ) {
free ( constr ) ;
return - 1 ;
}
* con = constr ;
constr [ len ] = ' \0 ' ;
return 0 ;
}
2013-08-14 00:19:14 +04:00
2013-01-14 22:33:44 +04:00
int getfilecon ( const char * path , security_context_t * con )
{
return getfilecon_raw ( path , con ) ;
}
2013-08-14 00:19:14 +04:00
int statfs ( const char * path , struct statfs * buf )
{
int ret ;
init_syms ( ) ;
ret = realstatfs ( path , buf ) ;
if ( ! ret & & STREQ ( path , abs_builddir " /securityselinuxlabeldata/nfs " ) )
buf - > f_type = NFS_SUPER_MAGIC ;
return ret ;
}
int security_getenforce ( void )
{
/* For the purpose of our test, we are enforcing. */
return 1 ;
}
int security_get_boolean_active ( const char * name )
{
/* For the purpose of our test, nfs is not permitted. */
if ( STREQ ( name , " virt_use_nfs " ) )
return 0 ;
init_syms ( ) ;
return realsecurity_get_boolean_active ( name ) ;
}