string_t zuluCryptLoopDeviceAddress_2( const char * device ) { int fd ; char * path ; struct loop_info64 l_info ; string_t st = String_1( "/sys/block/",device + 5,"/loop/backing_file",NULL ) ; string_t xt = _StringGetFromVirtualFile( &st ) ; if( xt == StringVoid ){ memset( &l_info,'\0',sizeof( struct loop_info64 ) ) ; fd = open( device,O_RDONLY ) ; ioctl( fd,LOOP_GET_STATUS64,&l_info ) ; path = zuluCryptRealPath( ( char * ) l_info.lo_file_name ) ; close( fd ) ; xt = StringInherit( &path ) ; }else{ StringRemoveRight( xt,1 ) ; } /* * zuluCryptEncodeMountEntry() is defined in mount_volume.c */ zuluCryptEncodeMountEntry( xt ) ; return xt ; }
char * zuluCryptLoopDeviceAddress_1( const char * device ) { int fd ; char * path ; struct loop_info64 l_info ; string_t st = String_1( "/sys/block/",device + 5,"/loop/backing_file",NULL ) ; string_t xt = _StringGetFromVirtualFile( &st ) ; if( xt == StringVoid ){ memset( &l_info,'\0',sizeof( struct loop_info64 ) ) ; fd = open( device,O_RDONLY ) ; ioctl( fd,LOOP_GET_STATUS64,&l_info ) ; path = zuluCryptRealPath( ( char * ) l_info.lo_file_name ) ; close( fd ) ; return path ; }else{ StringRemoveRight( xt,1 ) ; return StringDeleteHandle( &xt ) ; } }
static string_t _root_device( const char * device,const char ** sys_device ) { size_t e ; ssize_t r ; string_t st = String( device ) ; if( StringStartsWithAtLeastOne( st,"/dev/sd","/dev/hd",NULL ) ){ /* * this path will convert something like: "/dev/sdc12" to "/dev/sdc". * basically,it removes digits from the end of the string to give the root device * required by tcplay's system volume or fde volume */ *sys_device = StringRemoveDigits( st ) ; }else if( StringStartsWith( st,"/dev/mmc" ) ){ /* * device path will be something like "/dev/mmcblk0p2" and what we want to do * is cut off the string from p to end iwth "/dev/mmcblk0" */ r = StringIndexOfChar( st,0,'p' ) ; if( r != -1 ){ e = StringLength( st ) - ( size_t )r ; *sys_device = StringRemoveRight( st,e ) ; }else{ *sys_device = StringContent( st ) ; } }else{ *sys_device = StringContent( st ) ; } return st ; }
char * zuluCryptGetLoopDeviceAddress( const char * device ) { char * z = NULL ; const char * e ; string_t st = StringVoid ; string_t xt = StringVoid ; int i ; int r ; z = zuluCryptLoopDeviceAddress_1( device ) ; if( z == NULL ){ return NULL ; }else{ st = String( "" ) ; for( i = 0 ; i < 255 ; i++ ){ StringReplace( st,"/sys/block/loop" ) ; StringAppendInt( st,i ) ; xt = StringGetFromVirtualFile( StringAppend( st,"/loop/backing_file" ) ) ; e = StringRemoveRight( xt,1 ) ; r = StringsAreEqual( e,z ) ; StringDelete( &xt ) ; if( r ){ StringReplace( st,"/dev/loop" ) ; e = StringAppendInt( st,i ) ; if( StringsAreNotEqual( device,e ) ){ break ; } }else{ StringReset( st ) ; } } StringFree( z ) ; if( StringIsEmpty( st ) ){ StringDelete( &st ) ; return NULL ; }else{ return StringDeleteHandle( &st ) ; } } }
static string_t _create_mount_point_0( const char * label,uid_t uid,string_t path,int need_privileges ) { const char * q = strrchr( label,'/' ) ; const char * e ; if( q == NULL ){ StringAppend( path,label ) ; }else{ if( *( q + 1 ) == '\0' ){ /* * -m option was given with a path that ends with "/",backtrack until you find the second "/" * from the right and use it as the last "/". */ e = q - 1 ; if( e < label ){ /* * -m option was given with a single "/". */ StringDelete( &path ) ; return StringVoid ; } while( 1 ){ if( e == label ){ StringAppend( path,e + 1 ) ; StringRemoveRight( path,1 ) ; break ; }else if( *e == '/' ){ StringAppend( path,e + 1 ) ; StringRemoveRight( path,1 ) ; break ; }else{ e-- ; } } }else{ StringAppend( path,q + 1 ) ; } } return _create_path( uid,path,need_privileges ) ; }
static const char * _remove_duplicates( string_t st ) { const char ** z = StringPointer( st ) ; while( StringHasComponent( *z,",," ) ){ StringReplaceString( st,",,","," ) ; } if( StringEndsWithChar( st,',' ) ){ return StringRemoveRight( st,1 ) ; }else{ return StringContent( st ) ; } }
static const char * _clean_loop_path( string_t xt ) { if( StringEndsWith( xt," (deleted)\n" ) ){ return StringRemoveString( xt," (deleted)\n" ) ; }else if( StringEndsWith( xt,"\n" ) ){ return StringRemoveRight( xt,1 ) ; }else{ return StringContent( xt ) ; } }
static void _zuluCryptPrintUnMountedPartitionProperties( stringList_t stl ) { /* * zuluCryptGetMoutedList() is defined in ../lib/process_mountinfo.c */ stringList_t stx = zuluCryptGetMoutedList() ; StringListIterator it ; StringListIterator end ; string_t st ; StringListGetIterators( stl,&it,&end ) ; while( it != end ){ st = *it ; it++ ; if( StringListHasStartSequence( stx,StringAppend( st," " ) ) == -1 ){ zuluCryptPrintPartitionProperties( StringRemoveRight( st,1 ) ) ; } } StringListDelete( &stx ) ; }
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 ; }
static int _zuluCryptCheckSYSifDeviceIsSystem( const char * device ) { /* * UDEV_SUPPORT is set at configure time by "-DUDEVSUPPORT=true" option,the option being absent equals "-DUDEVSUPPORT=false" * To set the option, configure with "-DUDEVSUPPORT=true" */ #if UDEV_SUPPORT /* * udev support is enabled */ int r ; size_t e ; ssize_t k ; string_t xt ; string_t st ; char dev[ PATH_MAX + 1 ] ; const char * path ; if( StringPrefixNotEqual( device,"/dev/" ) ){ /* * udev doesnt work with path to image files so return early */ return 0 ; } if( StringPrefixEqual( device,"/dev/loop" ) ){ /* * udev thinks all loop devices are system devices and we disagree and hence we return early */ return 0 ; } path = realpath( device,dev ) ; if( path != NULL ){ st = String( path ) ; }else{ st = String( device ) ; } if( StringStartsWithAtLeastOne( st,"/dev/sd","/dev/hd",NULL ) ){ /* * this path will convert something like: "/dev/sdc12" to "/dev/sdc" */ StringRemoveDigits( st ) ; }else if( StringStartsWith( st,"/dev/mmc" ) ){ /* * device path will be something like "/dev/mmcblk0p2" and what we want to do * is cut off the string from p to end iwth "/dev/mmcblk0" */ k = StringIndexOfChar( st,0,'p' ) ; if( k != -1 ){ e = StringLength( st ) - ( size_t )k ; StringRemoveRight( st,e ) ; } } StringReplaceString( st,"/dev/","/sys/block/" ) ; path = StringAppend( st,"/removable" ) ; /* * path will be something like "/sys/block/sda/removable" */ xt = StringGetFromVirtualFile( path ) ; StringDelete( &st ) ; if( xt == StringVoid ){ return 0 ; }else{ r = StringEqual( xt,"0\n" ) ; StringDelete( &xt ) ; return r ; } #else if( device ){;} /* * udev support is disabled */ return 0 ; #endif }