int zuluCryptBindUnmountVolume( stringList_t stx,const char * device,uid_t uid ) { stringList_t stl ; string_t xt ; string_t st ; string_t zt ; ssize_t index = -1 ; const char * f ; const char * g ; char * h = NULL ; int r = 1 ; int k ; int delete_stx = 0 ; /* * zuluCryptUserIsAMemberOfAGroup() is defined in security.c */ /* * root user is a member of all groups and hence is allowed */ int allowedUser = zuluCryptUserIsAMemberOfAGroup( uid,"zulumount" ) ; zuluCryptSecurityGainElevatedPrivileges() ; if( stx == StringListVoid ){ /* * zuluCryptGetMoutedListFromMountInfo() is defined in ../lib/process_mountinfo.c */ stx = zuluCryptGetMoutedListFromMountInfo() ; delete_stx = 1 ; } if( StringPrefixEqual( device,"/dev/loop" ) ){ /* * zuluCryptLoopDeviceAddress_2() is defined in ../lib/create_loop_device.c */ st = zuluCryptLoopDeviceAddress_2( device ) ; /* * Add a space at the end of the device name to make sure we check the full device name to avoid possible collisions * that may exist if one device is named "/home/abc" and another "/home/abcdef" */ zt = StringListHasStartSequence_1( stx,StringAppend( st," " ) ) ; StringRemoveRight( st,1 ) ; device = h = StringDeleteHandle( &st ) ; }else{ /* * Add a space at the end of the device name to make sure we check the full device name to avoid possible collisions * that may exist if one device is named "/dev/sdc1" and another "/dev/sdc12" */ st = String( device ) ; zt = StringListHasStartSequence_1( stx,StringAppend( st," " ) ) ; StringDelete( &st ) ; } if( zt == StringVoid ){ /* * The volume does not appear to be mounted */ r = 1 ; }else{ stl = StringListStringSplit( zt,' ' ) ; xt = StringListCopyStringAtSecondPlace( stl ) ; StringListDelete( &stl ) ; st = StringCopy( xt ) ; /* * zuluCryptDecodeMountEntry() is defined in ../lib/mount_volume.c * g will contain something like "/run/media/private/$USER/sdc1" */ g = zuluCryptDecodeMountEntry( st ) ; if( allowedUser ){ /* * a privileged user is attempting to unmount a shared mount point,allow them */ k = 1 ; }else{ /* * a non privileged user is attempting to unmount a shared mount point,allow them only if * they are the one that created it */ /* * zuluCryptSecurityMountPointPrefixMatch() is defined in ./security.c */ k = zuluCryptMountPointPrefixMatch( g,uid,NULL ) ; } StringDelete( &st ) ; if( k != 1 ){ /* * One none privileged user is attempting to unmount a bind mount from another use,disallow it */ r = 4 ; }else{ index = StringLastIndexOfChar( xt,'/' ) + 1 ; StringRemoveLeft( xt,index ) ; StringPrepend( xt,"/run/media/public/" ) ; /* * f will now contain something like "/run/media/public/sdc1" * space character is added before checking to avoid possible collisions * as explained in above comments */ f = StringAppend( xt," " ) ; zt = StringListHasSequence_1( stx,f ) ; f = StringRemoveRight( xt,1 ) ; if( zt == StringVoid ){ /* * volume is not shared */ }else{ /* * volume is shared,try to unmount it * a volume is assumed to be shared if its device path in mountinfo has two mount points,one * in /run/media/private/$USER and the other in /run/media/public/ */ if( StringStartsWith( zt,device ) ){ f = zuluCryptDecodeMountEntry( xt ) ; /* * good,the device associated with the shared mount is the same as that of the * private mount,try to unmount it. */ r = 3 ; for( k = 0 ; k < 3 ; k++ ){ /* * try to unmount 3 times before giving up */ if( umount( f ) == 0 ){ rmdir( f ) ; r = 0 ; break ; }else{ sleep( 1 ) ; } } }else{ /* * i dont see how we will get here,we shouldnt */ r = 0 ; } } } StringDelete( &xt ) ; } if( delete_stx ){ StringListDelete( &stx ) ; } StringFree( h ) ; zuluCryptSecurityDropElevatedPrivileges() ; return r ; }
int zuluMountUMount( ARGS * args ) { const char * device = args->device ; uid_t uid = args->uid ; char * loop_device ; char * m_point = NULL ; int status ; string_t st = StringVoid ; const char * dev = NULL ; const char * errorMsg = gettext( "\ ERROR: You can not umount volumes out of \"%s\" since you are not root and do not belong to group \"zulumount\"\n" ) ; string_t xt ; if( StringPrefixEqual( device,"/dev/loop" ) ){ /* * zuluCryptLoopDeviceAddress() is defined in ../zuluCrypt-cli/lib/create_loop_devices.c */ loop_device = zuluCryptLoopDeviceAddress( device ) ; if( loop_device == NULL ){ /* * the error msg is a lie,but its harmless since the user will most likely never see it as * this code path will not be passed. */ return _zuluExit( 100,StringVoid,m_point,gettext( "ERROR: Device does not appear to be mounted" ) ) ; }else{ st = StringInherit( &loop_device ) ; dev = StringContent( st ) ; /* * zuluCryptGetMountPointFromPath() is defined in defined in ../zuluCrypt-cli/lib/process_mountinfo.c */ m_point = zuluCryptGetMountPointFromPath( dev ) ; if( m_point == NULL ){ return _zuluExit( 100,st,m_point,gettext( "ERROR: Device does not appear to be mounted" ) ) ; } } }else{ /* * zuluCryptGetMountPointFromPath() is defined in defined in ../zuluCrypt-cli/lib/process_mountinfo.c */ m_point = zuluCryptGetMountPointFromPath( device ) ; if( m_point == NULL ){ return _zuluExit( 100,st,m_point,gettext( "ERROR: Device does not appear to be mounted" ) ) ; } } /* * zuluCryptMountPointPrefixMatch() is defined in ../zuluCrypt-cli/bin/create_mount_point.c */ if( zuluCryptMountPointPrefixMatch( m_point,uid,&xt ) ){ StringDelete( &xt ) ; }else{ /* * zuluCryptUserIsAMemberOfAGroup() is defined in ../zuluCrypt-cli/bin/security.c */ if( zuluCryptUserIsAMemberOfAGroup( uid,"zulumount" ) ){ StringDelete( &xt ) ; }else{ printf( errorMsg,StringContent( xt ) ) ; StringDelete( &xt ) ; return _zuluExit( 101,st,m_point,NULL ) ; } } StringFree( m_point ) ; m_point = NULL ; /* * zuluCryptBindUnmountVolume() is defined in ../zuluCrypt-cli/bin/bind.c */ switch( zuluCryptBindUnmountVolume( StringListVoid,device,uid ) ){ case 3 : return _zuluExit( 107,st,m_point,gettext( "ERROR: Shared mount point appear to be busy" ) ) ; case 4 : return _zuluExit( 108,st,m_point,gettext( "ERROR: Shared mount point appear to belong to a different user" ) ) ; case 5 : return _zuluExit( 109,st,m_point,gettext( "ERROR: Shared mount point appear to be in an ambiguous state,advice to unmount manually" ) ) ; default: ; } /* * zuluCryptSecurityGainElevatedPrivileges() is defined in ../zuluCrypt-cli/bin/security.c */ zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptUnmountVolume() is defined in ../zuluCrypt-cli/lib/unmount_volume.c */ status = zuluCryptUnmountVolume( device,&m_point ) ; /* * zuluCryptSecurityDropElevatedPrivileges() is defined in ../zuluCrypt-cli/bin/security.c */ zuluCryptSecurityDropElevatedPrivileges() ; if( status == 0 ){ if( m_point != NULL ){ /* * zuluCryptReuseMountPoint() is defined in ../zuluCrypt-cli/bin/create_mount_point.c */ if( !zuluCryptReuseMountPoint() ){ zuluCryptSecurityGainElevatedPrivileges() ; rmdir( m_point ) ; zuluCryptSecurityDropElevatedPrivileges() ; } } return _zuluExit( 0,st,m_point,gettext( "SUCCESS: umount complete successfully" ) ) ; }else{ switch( status ) { case 1 : return _zuluExit( 103,st,m_point,gettext( "ERROR: Device does not exist" ) ) ; case 2 : return _zuluExit( 104,st,m_point,gettext( "ERROR: Failed to unmount,the mount point and/or one or more files are in use" ) ) ; case 4 : return _zuluExit( 105,st,m_point,gettext( "ERROR: Failed to unmount,could not get a lock on /etc/mtab~" ) ) ; case 10: return _zuluExit( 111,st,m_point,gettext( "ERROR: Failed to unmount,multiple mount points for the volume detected" ) ) ; break ; default: return _zuluExit( 106,st,m_point,gettext( "ERROR: Failed to unmount the partition" ) ) ; } } }