try u/mount as current user early; clean all mount points on unmount

This commit is contained in:
IgnorantGuru 2012-06-04 09:05:43 -06:00
parent 9b2563f4dc
commit c02e79769d
4 changed files with 155 additions and 27 deletions

View File

@ -2,7 +2,7 @@ IgnorantGuru <ignorantguru@gmx.com> http://igurublog.wordpress.com/
Source code taken from other projects:
* spacefm (udev support)
* mount (secure realpath)
* util-linux (secure canonicalize)
* udisks 1.0.4 (device info functions - modified)
* pmount 0.99 (physical tty test function - modified)

View File

@ -1,5 +1,5 @@
0.2.6+
try u/mount as current user early; clean all mount points on unmount
0.2.6 2012-06-03:
replace realpath.c with canonicalize.c
0.2.5 2012-05-30:

View File

@ -39,9 +39,6 @@ log_keep_days = 10
# the specific user 'USERNAME'. For example, to allow user 'jim' to mount
# only vfat filesystems, add:
# allowed_types_jim = vfat
# Note: For greater control for specific users, including root, copy this
# file to /etc/udevil/udevil-user-USERNAME.conf replacing USERNAME with the
# desired username (eg /etc/udevil/udevil-user-jim.conf).
# Setting allowed_types = * does NOT allow all types, as this is a security
# risk, but does allow all recognized types.
# allowed_types = $KNOWN_FILESYSTEMS, smbfs, nfs, ftpfs, curlftpfs, file
@ -61,7 +58,8 @@ allowed_types = $KNOWN_FILESYSTEMS
# the internal fstype of the file.
# For example, to allow only user 'bob' to mount nfs shares, add:
# allowed_users_nfs = bob
# The root user is NOT automatically allowed to use udevil unless listed here.
# The root user is NOT automatically allowed to use udevil in some cases unless
# listed here (except for unmounting anything or mounting fstab devices).
allowed_users = *
@ -78,7 +76,8 @@ allowed_users = *
# use both of these lines:
# allowed_groups_smbfs = network
# allowed_groups_nfs = network
# The root group is NOT automatically allowed to use udevil unless listed here.
# The root user is NOT automatically allowed to use udevil in some cases unless
# listed here (except for unmounting anything or mounting fstab devices).
allowed_groups = *
@ -107,9 +106,9 @@ allowed_media_dirs = /media, /run/media/$USER
# allowed_devices is the first criteria for what block devices users may mount
# or unmount. If a device is not listed in allowed_devices, it cannot be
# un/mounted. However, even if a device is listed, other factors may prevent
# its use. For example, access to system internal devices will be denied
# to normal users even if they are included in allowed_devices.
# un/mounted (unless in fstab). However, even if a device is listed, other
# factors may prevent its use. For example, access to system internal devices
# will be denied to normal users even if they are included in allowed_devices.
# allowed_devices_FSTYPE, if present, is used to override allowed_devices when
# mounting or unmounting a specific fstype (eg ext3, ntfs). For example, to
# prevent all block devices containing an ext4 filesystem from being
@ -144,7 +143,7 @@ allowed_devices = /dev/*
# forbidden_devices is used to prevent block devices from being un/mounted
# even if other settings would allow them.
# even if other settings would allow them (except devices in fstab).
# forbidden_devices_FSTYPE, if present, is used to override
# forbidden_devices when mounting or unmounting a specific fstype
# (eg ext3, ntfs). For example, to prevent device /dev/sdd1 from being
@ -173,7 +172,7 @@ allowed_networks = *
# forbidden_networks and forbidden_networks_FSTYPE are used to specify networks
# that are never allowed, even if other settings allow them.
# that are never allowed, even if other settings allow them (except fstab).
# NO REVERSE LOOKUP IS PERFORMED, so including bad.com will only have an effect
# if the user uses that hostname. IP lookup is always performed, so forbidding
# an IP address will also forbid all corresponding hostnames.
@ -192,7 +191,7 @@ allowed_files = *
# forbidden_files is used to specify files that are never allowed, even if
# other settings allow them. Specify a full path.
# other settings allow them (except fstab). Specify a full path.
# Note: Wildcards may be used, but a wildcard will never match a /, except
# for "forbidden_files = *".
# NOTE: file paths are canonicalized before being tested, so forbidding

View File

@ -61,6 +61,8 @@
#define ALLOWED_TYPES "$KNOWN_FILESYSTEMS,smbfs,nfs,ftpfs,curlftpfs,file"
#define MAX_LOG_DAYS 60 // don't set this too high
static int command_clean();
int verbose = 1;
char* logfile = NULL;
char* logmem = NULL;
@ -1804,6 +1806,69 @@ static int exec_program( const char* var, const char* msg, gboolean show_error,
return exit_status;
}
static int try_umount( const char* device_file, gboolean force, gboolean lazy )
{
// setup command
int status = 0;
int exit_status = 1;
gchar *argv[6] = { NULL };
char* sstdout = NULL;
char* sstderr = NULL;
int a = 0;
argv[a++] = g_strdup( read_config( "umount_program", NULL ) );
if ( !argv[0] )
return 1;
if ( verbose == 0 )
argv[a++] = g_strdup( "-v" );
if ( force )
argv[a++] = g_strdup( "-f" );
if ( lazy )
argv[a++] = g_strdup( "-l" );
argv[a++] = g_strdup( device_file );
char* allarg = g_strjoinv( " ", argv );
// insurance
drop_privileges( 0 );
// log
wlog( "udevil: trying umount as current user\n", NULL, 0 );
wlog( "USER: %s\n", allarg, 0 );
g_free( allarg );
// run
if ( g_spawn_sync( NULL, argv, NULL, 0, NULL, NULL, &sstdout, &sstderr, &status, NULL ) )
{
if ( status && WIFEXITED( status ) )
exit_status = WEXITSTATUS( status );
else
exit_status = 0;
}
else
wlog( "udevil: warning: unable to run umount (%s)\n",
read_config( "umount_program", NULL ), 1 );
if ( exit_status )
{
char* str = g_strdup_printf( " umount exit status = %d\n", exit_status );
wlog( str, NULL, 0 );
g_free( str );
g_free( sstdout );
g_free( sstderr );
return 1;
}
// success - show output
wlog( "udevil: success running umount as current user\n", NULL, 1 );
if ( sstderr )
fprintf( stderr, sstderr );
if ( sstdout )
fprintf( stdout, sstdout );
g_free( sstdout );
g_free( sstderr );
return 0;
}
static int umount_path( const char* path, gboolean force, gboolean lazy )
{
// setup command
@ -2488,6 +2553,77 @@ _get_type:
}
}
// try normal user u/mount early
if ( !data->point )
{
if ( data->cmd_type == CMD_UNMOUNT )
{
ret = try_umount( type == MOUNT_NET ? netmount->url : data->device_file,
data->force, data->lazy );
if ( ret == 0 )
{
// success_exec
str = g_strdup_printf( "%s unmounted %s", g_get_user_name(),
type == MOUNT_NET ? netmount->url : data->device_file );
exec_program( "success_rootexec", str, FALSE, TRUE );
exec_program( "success_exec", str, FALSE, FALSE );
g_free( str );
if ( orig_euid == 0 )
command_clean();
return 0;
}
}
else if ( data->cmd_type == CMD_MOUNT
&& !( data->options && strstr( data->options, "remount" ) ) )
{
if ( mount_knows( type == MOUNT_NET ? netmount->url : data->device_file ) )
{
// mount knows (in fstab) so mount as normal user with only specified opts
wlog( "udevil: %s is known to mount - running mount as current user\n",
type == MOUNT_NET ? netmount->url : data->device_file, 1 );
if ( data->fstype )
wlog( "udevil: warning: fstype ignored for device in fstab (or specify mount point)\n",
NULL, 1 );
if ( data->options )
wlog( "udevil: warning: options ignored for device in fstab (or specify mount point)\n",
NULL, 1 );
ret = mount_device( type == MOUNT_NET ? netmount->url : data->device_file,
NULL, NULL, NULL, FALSE );
// print
if ( !ret )
{
if ( device_is_mounted_mtab(
type == MOUNT_NET ? netmount->url : data->device_file,
&str, NULL ) )
{
str = g_strdup_printf( "Mounted %s at %s\n",
type == MOUNT_NET ? netmount->url : data->device_file,
str );
}
else
str = g_strdup_printf( "Mounted %s\n",
type == MOUNT_NET ? netmount->url : data->device_file );
wlog( str, NULL, -1 );
g_free( str );
// success_exec
if ( !ret )
{
str = g_strdup_printf( "%s mounted %s (in fstab)",
g_get_user_name(),
type == MOUNT_NET ? netmount->url : data->device_file );
exec_program( "success_rootexec", str, FALSE, TRUE );
exec_program( "success_exec", str, FALSE, FALSE );
g_free( str );
}
}
return ret;
}
}
ret = 0;
}
// determine device from unmount point
if ( data->cmd_type == CMD_UNMOUNT && type == MOUNT_FILE )
{
@ -2579,6 +2715,7 @@ _get_type:
}
// get fstype and device info
ret = 0;
if ( type == MOUNT_NET )
{
fstype = g_strdup( netmount->fstype );
@ -3059,24 +3196,16 @@ _get_type:
if ( data->point && !( ret = umount_path( data->point, data->force,
data->lazy ) ) )
{
// remove mount point if udevil created
str = g_build_filename( data->point, ".udevil-mount-point", NULL );
restore_privileges(); // needed for stat and rm
if ( stat64( str, &statbuf ) == 0 && statbuf.st_uid == 0 )
{
// .udevil-mount-point exists and is root-owned
unlink ( str );
rmdir( data->point );
}
g_free( str );
drop_privileges( 0 );
// success_exec
str = g_strdup_printf( "%s unmounted %s", g_get_user_name(),
data->point );
exec_program( "success_rootexec", str, FALSE, TRUE );
exec_program( "success_exec", str, FALSE, FALSE );
g_free( str );
// cleanup mount points
if ( orig_euid == 0 )
command_clean();
}
goto _finish;
}
@ -3288,8 +3417,8 @@ _get_type:
if ( mount_knows( type == MOUNT_NET ? netmount->url : data->device_file ) )
{
// mount knows (in fstab) so mount as normal user with only specified opts
wlog( "udevil: %s is known to mount - running mount as normal user\n",
data->device_file, 1 );
wlog( "udevil: %s is known to mount - running mount as current user\n",
type == MOUNT_NET ? netmount->url : data->device_file, 1 );
if ( data->fstype )
wlog( "udevil: warning: fstype ignored for device in fstab (or specify mount point)\n",
NULL, 1 );