2005-02-04 23:38:26 +03:00
/*
* Copyright ( C ) 2004 Daniel Walsh
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 of the License .
*
* This program 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
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
2006-08-28 02:29:11 +04:00
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2005-02-04 23:38:26 +03:00
*
*/
# include <stdlib.h>
# include <stdio.h>
# include <stddef.h>
# include <unistd.h>
# include <string.h>
# include <fcntl.h>
# include <ctype.h>
# include <limits.h>
# include <errno.h>
2007-09-06 15:12:48 +04:00
# include <sys/stat.h>
2005-02-04 23:38:26 +03:00
# include <selinux/selinux.h>
2005-12-26 19:21:25 +03:00
# include "udev.h"
2005-02-04 23:38:26 +03:00
# include "udev_selinux.h"
static security_context_t prev_scontext = NULL ;
static int is_selinux_running ( void )
{
static int selinux_enabled = - 1 ;
if ( selinux_enabled = = - 1 )
selinux_enabled = ( is_selinux_enabled ( ) > 0 ) ;
2008-04-20 23:07:06 +04:00
dbg ( " selinux=%i \n " , selinux_enabled ) ;
2005-02-04 23:38:26 +03:00
return selinux_enabled ;
}
static char * get_media ( const char * devname , int mode )
{
FILE * fp ;
char procfile [ PATH_MAX ] ;
char mediabuf [ 256 ] ;
int size ;
char * media = NULL ;
2006-05-08 00:31:06 +04:00
if ( ! ( mode & S_IFBLK ) )
2005-02-04 23:38:26 +03:00
return NULL ;
snprintf ( procfile , PATH_MAX , " /proc/ide/%s/media " , devname ) ;
procfile [ PATH_MAX - 1 ] = ' \0 ' ;
fp = fopen ( procfile , " r " ) ;
if ( ! fp )
goto out ;
if ( fgets ( mediabuf , sizeof ( mediabuf ) , fp ) = = NULL )
goto close_out ;
size = strlen ( mediabuf ) ;
while ( size - - > 0 ) {
if ( isspace ( mediabuf [ size ] ) ) {
mediabuf [ size ] = ' \0 ' ;
} else {
break ;
}
}
media = strdup ( mediabuf ) ;
2008-04-20 23:07:06 +04:00
info ( " selinux_get_media(%s)='%s' \n " , devname , media ) ;
2005-02-04 23:38:26 +03:00
close_out :
fclose ( fp ) ;
out :
return media ;
}
void selinux_setfilecon ( const char * file , const char * devname , unsigned int mode )
{
if ( is_selinux_running ( ) ) {
security_context_t scontext = NULL ;
char * media ;
int ret = - 1 ;
2007-02-15 00:29:03 +03:00
if ( devname ) {
2006-12-05 16:32:44 +03:00
media = get_media ( devname , mode ) ;
if ( media ) {
ret = matchmediacon ( media , & scontext ) ;
free ( media ) ;
}
2005-02-04 23:38:26 +03:00
}
if ( ret < 0 )
if ( matchpathcon ( file , mode , & scontext ) < 0 ) {
2008-04-20 23:07:06 +04:00
err ( " matchpathcon(%s) failed \n " , file ) ;
2005-02-04 23:38:26 +03:00
return ;
}
2006-12-05 16:32:44 +03:00
if ( lsetfilecon ( file , scontext ) < 0 )
2008-04-20 23:07:06 +04:00
err ( " setfilecon %s failed: %s \n " , file , strerror ( errno ) ) ;
2005-02-04 23:38:26 +03:00
freecon ( scontext ) ;
}
}
void selinux_setfscreatecon ( const char * file , const char * devname , unsigned int mode )
{
if ( is_selinux_running ( ) ) {
security_context_t scontext = NULL ;
char * media ;
int ret = - 1 ;
2007-04-12 03:10:08 +04:00
if ( devname ) {
media = get_media ( devname , mode ) ;
if ( media ) {
ret = matchmediacon ( media , & scontext ) ;
free ( media ) ;
}
2005-02-04 23:38:26 +03:00
}
if ( ret < 0 )
if ( matchpathcon ( file , mode , & scontext ) < 0 ) {
2008-04-20 23:07:06 +04:00
err ( " matchpathcon(%s) failed \n " , file ) ;
2005-02-04 23:38:26 +03:00
return ;
}
if ( setfscreatecon ( scontext ) < 0 )
2008-04-20 23:07:06 +04:00
err ( " setfscreatecon %s failed: %s \n " , file , strerror ( errno ) ) ;
2005-02-04 23:38:26 +03:00
freecon ( scontext ) ;
}
}
2005-04-27 10:52:14 +04:00
void selinux_resetfscreatecon ( void )
{
if ( is_selinux_running ( ) ) {
if ( setfscreatecon ( prev_scontext ) < 0 )
2008-04-20 23:07:06 +04:00
err ( " setfscreatecon failed: %s \n " , strerror ( errno ) ) ;
2005-04-27 10:52:14 +04:00
}
}
2005-02-04 23:38:26 +03:00
void selinux_init ( void )
{
/*
* record the present security context , for file - creation
* restoration creation purposes .
*/
if ( is_selinux_running ( ) ) {
2007-04-12 03:10:08 +04:00
if ( ! udev_root [ 0 ] )
2008-04-20 23:07:06 +04:00
err ( " selinux_init: udev_root not set \n " ) ;
2005-12-22 19:29:20 +03:00
matchpathcon_init_prefix ( NULL , udev_root ) ;
2005-04-27 10:52:14 +04:00
if ( getfscreatecon ( & prev_scontext ) < 0 ) {
2008-04-20 23:07:06 +04:00
err ( " getfscreatecon failed \n " ) ;
2005-04-27 10:52:14 +04:00
prev_scontext = NULL ;
}
2005-02-04 23:38:26 +03:00
}
}
2005-04-27 10:52:14 +04:00
void selinux_exit ( void )
2005-02-04 23:38:26 +03:00
{
2005-04-27 10:52:14 +04:00
if ( is_selinux_running ( ) & & prev_scontext ) {
freecon ( prev_scontext ) ;
prev_scontext = NULL ;
2005-02-04 23:38:26 +03:00
}
}