zuluCrypt  5.7.1
About: zuluCrypt is a simple but feature rich solution for hard drives encryption. It can manage PLAIN dm-crypt, LUKS, TrueCrypt and VeraCrypt encrypted volumes.
  Fossies Dox: zuluCrypt-5.7.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

create_loop_device.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2012-2015
4  * name : Francis Banyikwa
5  * email: mhogomchungu@gmail.com
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "includes.h"
21 #include <sys/ioctl.h>
22 #include <linux/loop.h>
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 
30 static int zuluExit( int result,string_t st,int fd_loop,int fd_path )
31 {
32  if( st == 0 ){
33 
34  StringDelete( &st ) ;
35 
36  if( fd_loop != -1 ){
37 
38  close( fd_loop ) ;
39  }
40  }
41  if( fd_path != -1 ){
42 
43  close( fd_path ) ;
44  }
45  return result ;
46 }
47 
49 {
51  StringDelete( st ) ;
52  return xt ;
53 }
54 
55 static const char * _clean_loop_path( string_t xt )
56 {
57  if( StringEndsWith( xt," (deleted)\n" ) ){
58 
59  return StringRemoveString( xt," (deleted)\n" ) ;
60 
61  }else if( StringEndsWith( xt,"\n" ) ){
62 
63  return StringRemoveRight( xt,1 ) ;
64  }else{
65  return StringContent( xt ) ;
66  }
67 }
68 
69 /*
70  * We only care about loop device path that are in a form of "/dev/loopX.
71  *
72  * We dont care about loop device path that are in a form of /dev/loopXpY
73  * and this method converts the latter path to the former if found.
74  */
75 static string_t _loop_device_path( const char * device )
76 {
77  string_t st ;
78 
79  char * e = StringCopy_2( device ) ;
80  char * s = e + 10 ;
81 
82  while( *s ){
83 
84  if( *s == 'p' ){
85 
86  *s = '\0' ;
87 
88  break ;
89  }else{
90  s++ ;
91  }
92  }
93 
94  st = String_1( "/sys/block/",e + 5,"/loop/backing_file",NULL ) ;
95 
96  StringFree( e ) ;
97 
98  return st ;
99 }
100 
102 {
103  int fd ;
104  char * path ;
105  struct loop_info64 l_info ;
106 
107  string_t st = _loop_device_path( device ) ;
108 
109  string_t xt = _StringGetFromVirtualFile( &st ) ;
110 
111  if( xt == StringVoid ){
112 
113  memset( &l_info,'\0',sizeof( struct loop_info64 ) ) ;
114 
115  fd = open( device,O_RDONLY ) ;
116 
117  ioctl( fd,LOOP_GET_STATUS64,&l_info ) ;
118 
119  path = zuluCryptRealPath( ( char * ) l_info.lo_file_name ) ;
120 
121  close( fd ) ;
122 
123  xt = StringInherit( &path ) ;
124  }
125 
126  _clean_loop_path( xt ) ;
127  /*
128  * zuluCryptEncodeMountEntry() is defined in mount_volume.c
129  */
131  return xt ;
132 }
133 
134 char * zuluCryptLoopDeviceAddress( const char * device )
135 {
136  string_t st = zuluCryptLoopDeviceAddress_2( device ) ;
137  return StringDeleteHandle( &st ) ;
138 }
139 
140 char * zuluCryptLoopDeviceAddress_1( const char * device )
141 {
142  int fd ;
143  char * path ;
144  struct loop_info64 l_info ;
145 
146  string_t st = _loop_device_path( device ) ;
147 
148  string_t xt = _StringGetFromVirtualFile( &st ) ;
149 
150  if( xt == StringVoid ){
151 
152  memset( &l_info,'\0',sizeof( struct loop_info64 ) ) ;
153 
154  fd = open( device,O_RDONLY ) ;
155 
156  ioctl( fd,LOOP_GET_STATUS64,&l_info ) ;
157 
158  path = zuluCryptRealPath( ( char * ) l_info.lo_file_name ) ;
159 
160  close( fd ) ;
161 
162  st = String( path ) ;
163 
164  StringFree( path ) ;
165 
166  _clean_loop_path( st ) ;
167  return StringDeleteHandle( &st ) ; ;
168  }else{
169  _clean_loop_path( xt ) ;
170  return StringDeleteHandle( &xt ) ;
171  }
172 }
173 
175 {
176  int i ;
177  string_t st = String( "" ) ;
178  const char * e ;
179  char * f ;
180 
181  for( i = 0 ; i < 255 ; i++ ){
182 
183  StringReplace( st,"/dev/loop" ) ;
184 
185  e = StringAppendInt( st,i ) ;
186 
188 
189  if( StringsAreEqual( path,f ) ){
190 
191  StringFree( f ) ;
192 
193  return StringDeleteHandle( &st ) ;
194  }else{
195  StringFree( f ) ;
196  }
197  }
198 
199  StringDelete( &st ) ;
200  return NULL ;
201 }
202 
203 char * zuluCryptGetLoopDeviceAddress( const char * device )
204 {
205  char * z = NULL ;
206  const char * e ;
207 
208  string_t st = StringVoid ;
209  string_t xt = StringVoid ;
210 
211  int i ;
212  int r ;
213 
214  z = zuluCryptLoopDeviceAddress_1( device ) ;
215 
216  if( z == NULL ){
217  return NULL ;
218  }else{
219  st = String( "" ) ;
220 
221  for( i = 0 ; i < 255 ; i++ ){
222 
223  StringReplace( st,"/sys/block/loop" ) ;
224  StringAppendInt( st,i ) ;
225 
226  xt = StringGetFromVirtualFile( StringAppend( st,"/loop/backing_file" ) ) ;
227 
228  e = _clean_loop_path( xt ) ;
229  r = StringsAreEqual( e,z ) ;
230 
231  StringDelete( &xt ) ;
232 
233  if( r ){
234 
235  StringReplace( st,"/dev/loop" ) ;
236  e = StringAppendInt( st,i ) ;
237 
238  if( StringsAreNotEqual( device,e ) ){
239 
240  break ;
241  }
242  }else{
243  StringReset( st ) ;
244  }
245  }
246 
247  StringFree( z ) ;
248 
249  if( StringIsEmpty( st ) ){
250 
251  StringDelete( &st ) ;
252  return NULL ;
253  }else{
254  return StringDeleteHandle( &st ) ;
255  }
256  }
257 }
258 
260 {
261  char * e ;
262  char * c ;
263 
264  string_t xt = String( "/proc/self/fd/" ) ;
265 
266  e = zuluCryptRealPath( StringAppendInt( xt,fd ) ) ;
267 
268  /*
269  * zuluCryptResolvePath_4() is defined in resolve_paths.c
270  */
271  c = zuluCryptResolvePath_4( e ) ;
272 
273  StringFree( e ) ;
274 
275  StringDelete( &xt ) ;
276 
277  return c ;
278 }
279 
280 /*
281  * Here,we check if the path we sent to open() is the path open() used. This check is necessary to
282  * guard against some known hypothetical exploits
283  */
284 static int _paths_are_not_sane( int fd,const char * path )
285 {
286  char * c = zuluCryptGetFileNameFromFileDescriptor( fd ) ;
287  int st = StringsAreNotEqual( c,path ) ;
288  StringFree( c ) ;
289  return st ;
290 }
291 
292 static int open_loop_device_1( string_t * loop_device )
293 {
294  string_t st = String( "" ) ;
295  int i ;
296  int fd ;
297  const char * path ;
298  struct loop_info64 l_info ;
299  int r = 0 ;
300 
301  for( i = 0 ; i < 255 ; i++ ){
302 
303  StringReplace( st,"/dev/loop" ) ;
304  path = StringAppendInt( st,i ) ;
305  fd = open( path,O_RDONLY ) ;
306 
307  if( fd == -1 ){
308  r = 0 ;
309  break ;
310  }
311  if( ioctl( fd,LOOP_GET_STATUS64,&l_info ) != 0 ){
312 
313  if( errno == ENXIO) {
314  *loop_device = StringCopy( st ) ;
315  close( fd ) ;
316  r = 1 ;
317  break ;
318  }
319  }
320  close( fd ) ;
321  }
322  StringDelete( &st ) ;
323  return r ;
324 }
325 
326 static int open_loop_device( string_t * loop_device )
327 {
328  int devnr ;
329  int fd_loop ;
330 
331  fd_loop = open( "/dev/loop-control",O_RDONLY ) ;
332 
333  if( fd_loop == -1 ){
334 
335  return open_loop_device_1( loop_device ) ;
336  }else{
337  devnr = ioctl( fd_loop,LOOP_CTL_GET_FREE ) ;
338  close( fd_loop ) ;
339 
340  if( devnr < 0 ){
341 
342  return open_loop_device_1( loop_device ) ;
343  }else{
344  *loop_device = String( "/dev/loop" ) ;
345  StringAppendInt( *loop_device,devnr ) ;
346  return 1 ;
347  }
348  }
349 }
350 
351 static int attach_device_to_loop( int fd_path,int * fd_loop,
352  string_t loop_device,int mode )
353 {
354  char * path ;
355  size_t size ;
356 
357  struct loop_info64 l_info ;
358 
359  *fd_loop = open( StringContent( loop_device ),mode ) ;
360 
361  memset( &l_info,'\0',sizeof( struct loop_info64 ) ) ;
362 
363  if( *fd_loop == -1 ){
364  return 0 ;
365  }
366  if( ioctl( *fd_loop,LOOP_SET_FD,fd_path ) == -1 ){
367  return 0 ;
368  }
369  if( ioctl( *fd_loop,LOOP_GET_STATUS64,&l_info ) == -1 ){
370  return 0;
371  }
372 
373  l_info.lo_flags |= LO_FLAGS_AUTOCLEAR;
374 
375  path = zuluCryptGetFileNameFromFileDescriptor( fd_path ) ;
376 
377  if( path == NULL ){
378  return 0 ;
379  }else{
380  size = sizeof( l_info.lo_file_name ) ;
381  strncpy( ( char * )l_info.lo_file_name,path,size ) ;
382  l_info.lo_file_name[ size - 1 ] = '\0' ;
383  free( path ) ;
384 
385  if( ioctl( *fd_loop,LOOP_SET_STATUS64,&l_info ) == -1 ){
386  return 0 ;
387  }else{
388  return 1 ;
389  }
390  }
391 }
392 
393 static int _attach_loop_device_to_file( const char * path,int mode,
394  int * loop_fd,string_t * loop_device )
395 {
396  string_t loopd = StringVoid ;
397 
398  int fd_loop = -1 ;
399  int fd_path = -1 ;
400 
401  if( !open_loop_device( &loopd ) ){
402  return zuluExit( 0,loopd,fd_loop,fd_path ) ;
403  }
404 
405  fd_path = open( path,mode ) ;
406 
407  if( fd_path == -1 ){
408  return zuluExit( 0,loopd,fd_loop,fd_path ) ;
409  }
410 
411  fcntl( fd_path,F_SETFD,FD_CLOEXEC ) ;
412 
413  if( _paths_are_not_sane( fd_path,path ) ){
414  return zuluExit( 0,loopd,fd_loop,fd_path ) ;
415  }
416  if( attach_device_to_loop( fd_path,&fd_loop,loopd,mode ) ){
417  *loop_device = loopd ;
418  *loop_fd = fd_loop ;
419  return zuluExit( 1,loopd,fd_loop,fd_path ) ;
420  }else{
421  return zuluExit( 0,loopd,fd_loop,fd_path ) ;
422  }
423 }
424 
425 int zuluCryptAttachLoopDeviceToFile( const char * path,int mode,
426  int * loop_fd,string_t * loop_device )
427 {
428  int i ;
429  int j ;
430  /*
431  * try to attach a loop device multiple times
432  */
433  for( j = 0 ; j < 3 ; j++ ){
434  i = _attach_loop_device_to_file( path,mode,loop_fd,loop_device ) ;
435  if( i == 1 ){
436  break ;
437  }else{
438  sleep( 1 ) ;
439  }
440  }
441  return i ;
442 }
443 
444 static int _attach_loop_device( int fd_path,int * fd_loop,int mode,string_t * loop_device )
445 {
446  string_t loopd = StringVoid ;
447 
448  if( !open_loop_device( &loopd ) ){
449  return 0 ;
450  }else{
451  if( attach_device_to_loop( fd_path,fd_loop,loopd,mode ) ){
452  *loop_device = loopd ;
453  return 1 ;
454  }else{
455  return 0 ;
456  }
457  }
458 }
459 
461  int * fd_loop,
462  int mode,
463  string_t * loop_device )
464 {
465  int i ;
466  int j ;
467  /*
468  * try to attach a loop device multiple times
469  */
470  for( j = 0 ; j < 3 ; j++ ){
471 
472  i = _attach_loop_device( fd_path,fd_loop,mode,loop_device ) ;
473 
474  if( i == 1 ){
475  break ;
476  }else{
477  sleep( 1 ) ;
478  }
479  }
480  return i ;
481 }
StringReplace
const char * StringReplace(string_t st, const char *s)
Definition: String.c:984
StringAppendInt
const char * StringAppendInt(string_t st, u_int64_t z)
Definition: String.c:1410
StringGetFromVirtualFile
string_t StringGetFromVirtualFile(const char *path)
Definition: String.c:2050
zuluCryptGetLoopDeviceAddress
char * zuluCryptGetLoopDeviceAddress(const char *device)
Definition: create_loop_device.c:203
StringReset
void StringReset(string_t st)
Definition: String.c:626
StringCopy
string_t StringCopy(string_t st)
Definition: String.c:260
_clean_loop_path
static const char * _clean_loop_path(string_t xt)
Definition: create_loop_device.c:55
zuluExit
static int zuluExit(int result, string_t st, int fd_loop, int fd_path)
Definition: create_loop_device.c:30
StringsAreNotEqual
#define StringsAreNotEqual(x, y)
Definition: zuluSafe.c:47
_attach_loop_device
static int _attach_loop_device(int fd_path, int *fd_loop, int mode, string_t *loop_device)
Definition: create_loop_device.c:444
zuluCryptLoopDeviceAddress_2
string_t zuluCryptLoopDeviceAddress_2(const char *device)
Definition: create_loop_device.c:101
StringEndsWith
int StringEndsWith(string_t st, const char *s)
Definition: String.c:781
open_loop_device
static int open_loop_device(string_t *loop_device)
Definition: create_loop_device.c:326
zuluCryptLoopDeviceAddress_1
char * zuluCryptLoopDeviceAddress_1(const char *device)
Definition: create_loop_device.c:140
zuluCryptGetALoopDeviceAssociatedWithAnImageFile
char * zuluCryptGetALoopDeviceAssociatedWithAnImageFile(const char *path)
Definition: create_loop_device.c:174
StringCopy_2
char * StringCopy_2(const char *str)
Definition: String.c:725
StringsAreEqual
#define StringsAreEqual(x, y)
Definition: zuluSafe.c:46
StringRemoveString
const char * StringRemoveString(string_t st, const char *s)
Definition: String.c:1328
StringDeleteHandle
char * StringDeleteHandle(string_t *xt)
Definition: String.c:233
StringInherit
string_t StringInherit(char **data)
Definition: String.c:391
StringContent
static const __inline__ char * StringContent(string_t st)
Definition: String.h:1011
open_loop_device_1
static int open_loop_device_1(string_t *loop_device)
Definition: create_loop_device.c:292
StringType
Definition: String.c:49
String
string_t String(const char *cstring)
Definition: String.c:318
String_1
string_t String_1(const char *cstring,...)
Definition: String.c:363
_paths_are_not_sane
static int _paths_are_not_sane(int fd, const char *path)
Definition: create_loop_device.c:284
zuluCryptEncodeMountEntry
const char * zuluCryptEncodeMountEntry(string_t)
Definition: mount_volume.c:425
zuluCryptGetFileNameFromFileDescriptor
char * zuluCryptGetFileNameFromFileDescriptor(int fd)
Definition: create_loop_device.c:259
zuluCryptResolvePath_4
char * zuluCryptResolvePath_4(const char *path)
Definition: resolve_paths.c:301
e
static QString e
Definition: about.cpp:31
includes.h
_StringGetFromVirtualFile
static string_t _StringGetFromVirtualFile(string_t *st)
Definition: create_loop_device.c:48
StringDelete
void StringDelete(string_t *st)
Definition: String.c:162
StringIsEmpty
int StringIsEmpty(string_t x)
Definition: String.c:1333
_attach_loop_device_to_file
static int _attach_loop_device_to_file(const char *path, int mode, int *loop_fd, string_t *loop_device)
Definition: create_loop_device.c:393
zuluCryptRealPath
char * zuluCryptRealPath(const char *path)
Definition: real_path.c:28
_loop_device_path
static string_t _loop_device_path(const char *device)
Definition: create_loop_device.c:75
StringRemoveRight
const char * StringRemoveRight(string_t st, size_t x)
Definition: String.c:634
zuluCryptAttachLoopDeviceToFile
int zuluCryptAttachLoopDeviceToFile(const char *path, int mode, int *loop_fd, string_t *loop_device)
Definition: create_loop_device.c:425
attach_device_to_loop
static int attach_device_to_loop(int fd_path, int *fd_loop, string_t loop_device, int mode)
Definition: create_loop_device.c:351
zuluCryptAttachLoopDeviceToFileUsingFileDescriptor
int zuluCryptAttachLoopDeviceToFileUsingFileDescriptor(int fd_path, int *fd_loop, int mode, string_t *loop_device)
Definition: create_loop_device.c:460
StringAppend
const char * StringAppend(string_t st, const char *s)
Definition: String.c:1052
zuluCryptLoopDeviceAddress
char * zuluCryptLoopDeviceAddress(const char *device)
Definition: create_loop_device.c:134
StringFree
static __inline__ void StringFree(const void *str)
Definition: String.h:823
StringVoid
#define StringVoid
Definition: String.h:47