2012-08-10 17:31:14 +04:00
/*
2016-02-25 01:02:44 +03:00
* Copyright ( C ) 2011 - 2013 , 2016 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 . */
2016-05-13 13:46:35 +03:00
# include "virmock.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>
2019-10-09 17:43:53 +03:00
# include <selinux/label.h>
2013-08-14 00:19:14 +04:00
# include <sys/vfs.h>
2012-08-10 17:31:14 +04:00
# include <unistd.h>
2018-08-03 17:35:53 +03:00
# include <sys/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
2014-03-06 10:02:46 +04:00
# define VIR_FROM_THIS VIR_FROM_NONE
# include "viralloc.h"
2013-05-03 16:52:21 +04:00
# include "virstring.h"
2012-09-19 17:00:34 +04:00
2016-05-13 13:46:35 +03:00
static int ( * real_statfs ) ( const char * path , struct statfs * buf ) ;
static int ( * real_security_get_boolean_active ) ( const char * name ) ;
static int ( * real_is_selinux_enabled ) ( void ) ;
2014-03-06 10:02:46 +04:00
2016-05-13 13:46:35 +03:00
static const char * ( * real_selinux_virtual_domain_context_path ) ( void ) ;
static const char * ( * real_selinux_virtual_image_context_path ) ( void ) ;
2014-03-06 10:02:46 +04:00
# ifdef HAVE_SELINUX_LXC_CONTEXTS_PATH
2016-05-13 13:46:35 +03:00
static const char * ( * real_selinux_lxc_contexts_path ) ( void ) ;
2014-03-06 10:02:46 +04:00
# endif
2016-05-13 13:46:35 +03:00
static struct selabel_handle * ( * real_selabel_open ) ( unsigned int backend ,
2016-02-25 01:02:44 +03:00
VIR_SELINUX_OPEN_CONST
2014-03-06 10:02:46 +04:00
struct selinux_opt * opts ,
unsigned nopts ) ;
2016-05-13 13:46:35 +03:00
static void ( * real_selabel_close ) ( struct selabel_handle * handle ) ;
static int ( * real_selabel_lookup_raw ) ( struct selabel_handle * handle ,
2014-03-06 10:02:46 +04:00
security_context_t * con ,
const char * key ,
int type ) ;
2013-08-14 00:19:14 +04:00
static void init_syms ( void )
{
2016-05-13 13:46:35 +03:00
if ( real_statfs )
2013-08-14 00:19:14 +04:00
return ;
2016-05-13 13:46:35 +03:00
VIR_MOCK_REAL_INIT ( statfs ) ;
VIR_MOCK_REAL_INIT ( security_get_boolean_active ) ;
VIR_MOCK_REAL_INIT ( is_selinux_enabled ) ;
2013-08-14 00:19:14 +04:00
2016-05-13 13:46:35 +03:00
VIR_MOCK_REAL_INIT ( selinux_virtual_domain_context_path ) ;
VIR_MOCK_REAL_INIT ( selinux_virtual_image_context_path ) ;
2014-03-06 10:02:46 +04:00
# ifdef HAVE_SELINUX_LXC_CONTEXTS_PATH
2016-05-13 13:46:35 +03:00
VIR_MOCK_REAL_INIT ( selinux_lxc_contexts_path ) ;
2014-03-06 10:02:46 +04:00
# endif
2016-05-13 13:46:35 +03:00
VIR_MOCK_REAL_INIT ( selabel_open ) ;
VIR_MOCK_REAL_INIT ( selabel_close ) ;
VIR_MOCK_REAL_INIT ( selabel_lookup_raw ) ;
2013-08-14 00:19:14 +04:00
}
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
{
2014-03-06 10:02:46 +04:00
if ( ! is_selinux_enabled ( ) ) {
errno = EINVAL ;
return - 1 ;
}
if ( getenv ( " FAKE_SELINUX_CONTEXT " ) = = NULL ) {
2012-08-10 17:31:14 +04:00
* context = NULL ;
errno = EINVAL ;
return - 1 ;
}
2019-10-20 13:55:05 +03:00
* context = g_strdup ( getenv ( " FAKE_SELINUX_CONTEXT " ) ) ;
return 0 ;
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
{
2014-03-06 10:02:46 +04:00
if ( ! is_selinux_enabled ( ) ) {
errno = EINVAL ;
return - 1 ;
}
2012-08-10 17:31:14 +04:00
if ( pid ! = getpid ( ) ) {
* context = NULL ;
errno = ESRCH ;
return - 1 ;
}
2014-03-06 10:02:46 +04:00
if ( getenv ( " FAKE_SELINUX_CONTEXT " ) = = NULL ) {
2012-08-10 17:31:14 +04:00
* context = NULL ;
errno = EINVAL ;
return - 1 ;
}
2019-10-20 13:55:05 +03:00
* context = g_strdup ( getenv ( " FAKE_SELINUX_CONTEXT " ) ) ;
return 0 ;
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 ) ;
}
2019-10-09 17:43:53 +03:00
int setcon_raw ( const char * context )
2012-08-10 17:31:14 +04:00
{
2014-03-06 10:02:46 +04:00
if ( ! is_selinux_enabled ( ) ) {
errno = EINVAL ;
return - 1 ;
}
2019-12-18 20:16:19 +03:00
return g_setenv ( " FAKE_SELINUX_CONTEXT " , context , TRUE ) ;
2012-08-10 17:31:14 +04:00
}
2012-09-19 17:00:34 +04:00
2019-10-09 17:43:53 +03:00
int setcon ( const char * context )
2013-01-14 22:33:44 +04:00
{
return setcon_raw ( context ) ;
}
2012-09-19 17:00:34 +04:00
2019-10-09 17:43:53 +03:00
int setfilecon_raw ( const char * path , const char * 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 ) ;
}
2019-10-09 17:43:53 +03:00
int setfilecon ( const char * path , const char * con )
2013-01-14 22:33:44 +04:00
{
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 ( ) ;
2016-05-13 13:46:35 +03:00
ret = real_statfs ( path , buf ) ;
2013-08-14 00:19:14 +04:00
if ( ! ret & & STREQ ( path , abs_builddir " /securityselinuxlabeldata/nfs " ) )
buf - > f_type = NFS_SUPER_MAGIC ;
return ret ;
}
2014-03-06 10:02:46 +04:00
int is_selinux_enabled ( void )
{
return getenv ( " FAKE_SELINUX_DISABLED " ) = = NULL ;
}
int security_disable ( void )
{
if ( ! is_selinux_enabled ( ) ) {
errno = ENOENT ;
return - 1 ;
}
2019-12-18 20:16:19 +03:00
return g_setenv ( " FAKE_SELINUX_DISABLED " , " 1 " , TRUE ) ;
2014-03-06 10:02:46 +04:00
}
2013-08-14 00:19:14 +04:00
int security_getenforce ( void )
{
2014-03-06 10:02:46 +04:00
if ( ! is_selinux_enabled ( ) ) {
errno = ENOENT ;
return - 1 ;
}
2013-08-14 00:19:14 +04:00
/* For the purpose of our test, we are enforcing. */
return 1 ;
}
int security_get_boolean_active ( const char * name )
{
2014-03-06 10:02:46 +04:00
if ( ! is_selinux_enabled ( ) ) {
errno = ENOENT ;
return - 1 ;
}
2013-08-14 00:19:14 +04:00
/* For the purpose of our test, nfs is not permitted. */
if ( STREQ ( name , " virt_use_nfs " ) )
return 0 ;
init_syms ( ) ;
2016-05-13 13:46:35 +03:00
return real_security_get_boolean_active ( name ) ;
2013-08-14 00:19:14 +04:00
}
2014-03-06 10:02:46 +04:00
const char * selinux_virtual_domain_context_path ( void )
{
init_syms ( ) ;
2016-05-13 13:46:35 +03:00
if ( real_is_selinux_enabled ( ) )
return real_selinux_virtual_domain_context_path ( ) ;
2014-03-06 10:02:46 +04:00
2014-03-10 13:20:30 +04:00
return abs_srcdir " /securityselinuxhelperdata/virtual_domain_context " ;
2014-03-06 10:02:46 +04:00
}
const char * selinux_virtual_image_context_path ( void )
{
init_syms ( ) ;
2016-05-13 13:46:35 +03:00
if ( real_is_selinux_enabled ( ) )
return real_selinux_virtual_image_context_path ( ) ;
2014-03-06 10:02:46 +04:00
2014-03-10 13:20:30 +04:00
return abs_srcdir " /securityselinuxhelperdata/virtual_image_context " ;
2014-03-06 10:02:46 +04:00
}
# ifdef HAVE_SELINUX_LXC_CONTEXTS_PATH
const char * selinux_lxc_contexts_path ( void )
{
init_syms ( ) ;
2016-05-13 13:46:35 +03:00
if ( real_is_selinux_enabled ( ) )
return real_selinux_lxc_contexts_path ( ) ;
2014-03-06 10:02:46 +04:00
2014-03-10 13:20:30 +04:00
return abs_srcdir " /securityselinuxhelperdata/lxc_contexts " ;
2014-03-06 10:02:46 +04:00
}
# endif
2016-02-25 01:02:44 +03:00
struct selabel_handle *
selabel_open ( unsigned int backend ,
VIR_SELINUX_OPEN_CONST struct selinux_opt * opts ,
unsigned nopts )
2014-03-06 10:02:46 +04:00
{
char * fake_handle ;
init_syms ( ) ;
2016-05-13 13:46:35 +03:00
if ( real_is_selinux_enabled ( ) )
return real_selabel_open ( backend , opts , nopts ) ;
2014-03-06 10:02:46 +04:00
/* struct selabel_handle is opaque; fake it */
if ( VIR_ALLOC ( fake_handle ) < 0 )
return NULL ;
return ( struct selabel_handle * ) fake_handle ;
}
void selabel_close ( struct selabel_handle * handle )
{
init_syms ( ) ;
2016-05-13 13:46:35 +03:00
if ( real_is_selinux_enabled ( ) )
return real_selabel_close ( handle ) ;
2014-03-06 10:02:46 +04:00
VIR_FREE ( handle ) ;
}
int selabel_lookup_raw ( struct selabel_handle * handle ,
security_context_t * con ,
const char * key ,
int type )
{
init_syms ( ) ;
2016-05-13 13:46:35 +03:00
if ( real_is_selinux_enabled ( ) )
return real_selabel_lookup_raw ( handle , con , key , type ) ;
2014-03-06 10:02:46 +04:00
/* Unimplemented */
errno = ENOENT ;
return - 1 ;
}