@@ -164,7 +164,6 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
164
164
assert (!enc -> pf );
165
165
166
166
int ret ;
167
- char * normpath = NULL ;
168
167
169
168
if (!pal_handle ) {
170
169
enum pal_create_mode create_mode = create ? PAL_CREATE_ALWAYS : PAL_CREATE_NEVER ;
@@ -185,21 +184,6 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
185
184
}
186
185
size_t size = pal_attr .pending_size ;
187
186
188
- assert (strstartswith (enc -> uri , URI_PREFIX_FILE ));
189
- const char * path = enc -> uri + static_strlen (URI_PREFIX_FILE );
190
-
191
- size_t normpath_size = strlen (path ) + 1 ;
192
- normpath = malloc (normpath_size );
193
- if (!normpath ) {
194
- ret = - ENOMEM ;
195
- goto out ;
196
- }
197
-
198
- if (!get_norm_path (path , normpath , & normpath_size )) {
199
- ret = - EINVAL ;
200
- goto out ;
201
- }
202
-
203
187
pf_context_t * pf ;
204
188
lock (& g_keys_lock );
205
189
if (!enc -> volume -> key -> is_set ) {
@@ -209,8 +193,9 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
209
193
goto out ;
210
194
}
211
195
pf_mac_t opening_root_gmac ;
212
- pf_status_t pfs = pf_open (pal_handle , normpath , size , PF_FILE_MODE_READ | PF_FILE_MODE_WRITE ,
213
- create , & enc -> volume -> key -> pf_key , & opening_root_gmac , & pf );
196
+ pf_status_t pfs =
197
+ pf_open (pal_handle , enc -> norm_path , size , PF_FILE_MODE_READ | PF_FILE_MODE_WRITE , create ,
198
+ & enc -> volume -> key -> pf_key , & opening_root_gmac , & pf );
214
199
unlock (& g_keys_lock );
215
200
if (PF_FAILURE (pfs )) {
216
201
log_warning ("pf_open failed: %s" , pf_strerror (pfs ));
@@ -219,17 +204,26 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
219
204
}
220
205
// rollback protection
221
206
struct libos_encrypted_volume_state_map * file_state = NULL ;
207
+ log_debug ("file '%s' opened with MAC=" MAC_PRINTF_PATTERN , enc -> norm_path ,
208
+ MAC_PRINTF_ARGS (opening_root_gmac )); // TODO (MST): remove me eventually?
222
209
lock (& (enc -> volume -> files_state_map_lock ));
223
210
// - check current state
224
211
if ((!create ) && (enc -> volume -> protection_mode != PF_ENCLAVE_LIFE_RB_PROTECTION_NONE )) {
225
- HASH_FIND_STR (enc -> volume -> files_state_map , normpath , file_state );
212
+ HASH_FIND_STR (enc -> volume -> files_state_map , enc -> norm_path , file_state );
226
213
if (file_state ) {
227
- if ((file_state -> state != PF_FILE_CLOSED ) ||
228
- (memcmp (file_state -> last_seen_root_gmac , opening_root_gmac , sizeof (pf_mac_t )) !=
229
- 0 )) {
214
+ /* TODO (MST): figure out what to test. Seems our test-cases, e.g., in open_close do
215
+ * allow for scenarios such as two concurrent open writeable fds for same file which i
216
+ * thought would be illegal
217
+ * (file_state->state != PF_FILE_CLOSED) ||
218
+ */
219
+ if (memcmp (file_state -> last_seen_root_gmac , opening_root_gmac , sizeof (pf_mac_t )) != 0 ) {
230
220
log_warning (
231
- "file '%s' was seen before but in different inconsistent (rolled-back?) state" ,
232
- normpath );
221
+ "file '%s' was seen before but in different inconsistent (rolled-back?) "
222
+ "state, expected MAC=" MAC_PRINTF_PATTERN
223
+ " but file had "
224
+ "MAC=" MAC_PRINTF_PATTERN ,
225
+ enc -> norm_path , MAC_PRINTF_ARGS (file_state -> last_seen_root_gmac ),
226
+ MAC_PRINTF_ARGS (opening_root_gmac ));
233
227
pf_set_corrupted (pf );
234
228
ret = - EACCES ;
235
229
goto out_unlock_map ;
@@ -238,24 +232,24 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
238
232
if (enc -> volume -> protection_mode == PF_ENCLAVE_LIFE_RB_PROTECTION_STRICT ) {
239
233
log_warning (
240
234
"file '%s' was not seen before, not allowing strict rollback protection" ,
241
- normpath );
235
+ enc -> norm_path );
242
236
pf_set_corrupted (pf );
243
237
ret = - EACCES ;
244
238
goto out_unlock_map ;
245
239
}
246
240
}
247
241
}
248
242
// - uodate map with new state
249
- if (! file_state ) {
243
+ if (file_state == NULL ) {
250
244
file_state = malloc (sizeof (struct libos_encrypted_volume_state_map ));
251
- if (! file_state ) {
245
+ if (file_state == NULL ) {
252
246
ret = - ENOMEM ;
253
247
goto out_unlock_map ;
254
248
}
255
- file_state -> uri = normpath ;
249
+ file_state -> norm_path = enc -> norm_path ;
256
250
memcpy (file_state -> last_seen_root_gmac , opening_root_gmac , sizeof (pf_mac_t ));
257
- HASH_ADD_KEYPTR (hh , enc -> volume -> files_state_map , file_state -> uri , strlen ( file_state -> uri ) ,
258
- file_state );
251
+ HASH_ADD_KEYPTR (hh , enc -> volume -> files_state_map , file_state -> norm_path ,
252
+ strlen ( file_state -> norm_path ), file_state );
259
253
}
260
254
file_state -> state = (create ? PF_FILE_IN_USE_NEW : PF_FILE_IN_USE_EXISTING );
261
255
@@ -267,7 +261,6 @@ static int encrypted_file_internal_open(struct libos_encrypted_file* enc, PAL_HA
267
261
unlock (& (enc -> volume -> files_state_map_lock ));
268
262
out :
269
263
if (ret < 0 ) {
270
- free (normpath );
271
264
PalObjectDestroy (pal_handle );
272
265
}
273
266
return ret ;
@@ -296,10 +289,12 @@ static void encrypted_file_internal_close(struct libos_encrypted_file* enc) {
296
289
297
290
pf_mac_t closing_root_gmac ;
298
291
pf_status_t pfs = pf_close (enc -> pf , & closing_root_gmac );
299
- struct libos_encrypted_volume_state_map * file_state = NULL ;
292
+ log_debug ("file '%s' closed with MAC=" MAC_PRINTF_PATTERN , enc -> norm_path ,
293
+ MAC_PRINTF_ARGS (closing_root_gmac )); // TODO (MST): remove me eventually?
300
294
lock (& (enc -> volume -> files_state_map_lock ));
301
- HASH_FIND_STR (enc -> volume -> files_state_map , enc -> uri , file_state );
302
- // TODO (MST): error handling if filestate is not found
295
+ struct libos_encrypted_volume_state_map * file_state = NULL ;
296
+ HASH_FIND_STR (enc -> volume -> files_state_map , enc -> norm_path , file_state );
297
+ assert (file_state != NULL );
303
298
if (PF_FAILURE (pfs )) {
304
299
log_warning ("pf_close failed: %s" , pf_strerror (pfs ));
305
300
file_state -> state = PF_FILE_ERROR ;
@@ -515,17 +510,47 @@ static int encrypted_file_alloc(const char* uri, struct libos_encrypted_volume*
515
510
if (!enc )
516
511
return - ENOMEM ;
517
512
513
+ int ret ;
514
+ enc -> uri = NULL ;
515
+ enc -> norm_path = NULL ;
516
+
518
517
enc -> uri = strdup (uri );
519
518
if (!enc -> uri ) {
520
- free ( enc ) ;
521
- return - ENOMEM ;
519
+ ret = - ENOMEM ;
520
+ goto err ;
522
521
}
522
+
523
+ assert (strstartswith (enc -> uri , URI_PREFIX_FILE ));
524
+ const char * path = enc -> uri + static_strlen (URI_PREFIX_FILE );
525
+
526
+ size_t norm_path_size = strlen (path ) + 1 ;
527
+ enc -> norm_path = malloc (norm_path_size );
528
+ if (!enc -> norm_path ) {
529
+ ret = - ENOMEM ;
530
+ goto err ;
531
+ }
532
+
533
+ if (!get_norm_path (path , enc -> norm_path , & norm_path_size )) {
534
+ ret = - EINVAL ;
535
+ goto err ;
536
+ }
537
+
523
538
enc -> volume = volume ;
524
539
enc -> use_count = 0 ;
525
540
enc -> pf = NULL ;
526
541
enc -> pal_handle = NULL ;
527
542
* out_enc = enc ;
528
543
return 0 ;
544
+
545
+ err :
546
+ if (enc ) {
547
+ if (enc -> uri )
548
+ free (enc -> uri );
549
+ if (enc -> norm_path )
550
+ free (enc -> norm_path );
551
+ free (enc );
552
+ }
553
+ return ret ;
529
554
}
530
555
531
556
int encrypted_file_open (const char * uri , struct libos_encrypted_volume * volume ,
@@ -568,6 +593,7 @@ void encrypted_file_destroy(struct libos_encrypted_file* enc) {
568
593
assert (!enc -> pf );
569
594
assert (!enc -> pal_handle );
570
595
free (enc -> uri );
596
+ // do _not_ free enc->norm_path as this is still used in file_state_map!
571
597
free (enc );
572
598
}
573
599
@@ -679,32 +705,30 @@ int encrypted_file_rename(struct libos_encrypted_file* enc, const char* new_uri)
679
705
assert (enc -> pf );
680
706
681
707
int ret ;
682
- char * new_normpath = NULL ;
708
+ char * new_norm_path = NULL ;
709
+ char * old_norm_path = enc -> norm_path ;
683
710
684
711
char * new_uri_copy = strdup (new_uri );
685
712
if (!new_uri_copy )
686
713
return - ENOMEM ;
687
714
688
- assert (strstartswith (enc -> uri , URI_PREFIX_FILE ));
689
- const char * old_path = enc -> uri + static_strlen (URI_PREFIX_FILE );
690
-
691
715
assert (strstartswith (new_uri , URI_PREFIX_FILE ));
692
716
const char * new_path = new_uri + static_strlen (URI_PREFIX_FILE );
693
717
694
- size_t new_normpath_size = strlen (new_path ) + 1 ;
695
- new_normpath = malloc (new_normpath_size );
696
- if (!new_normpath ) {
718
+ size_t new_norm_path_size = strlen (new_path ) + 1 ;
719
+ new_norm_path = malloc (new_norm_path_size );
720
+ if (!new_norm_path ) {
697
721
ret = - ENOMEM ;
698
722
goto out ;
699
723
}
700
724
701
- if (!get_norm_path (new_path , new_normpath , & new_normpath_size )) {
725
+ if (!get_norm_path (new_path , new_norm_path , & new_norm_path_size )) {
702
726
ret = - EINVAL ;
703
727
goto out ;
704
728
}
705
729
706
730
pf_mac_t new_root_gmac ;
707
- pf_status_t pfs = pf_rename (enc -> pf , new_normpath , & new_root_gmac );
731
+ pf_status_t pfs = pf_rename (enc -> pf , new_norm_path , & new_root_gmac );
708
732
if (PF_FAILURE (pfs )) {
709
733
log_warning ("pf_rename failed: %s" , pf_strerror (pfs ));
710
734
ret = - EACCES ;
@@ -716,33 +740,65 @@ int encrypted_file_rename(struct libos_encrypted_file* enc, const char* new_uri)
716
740
log_warning ("PalStreamChangeName failed: %s" , pal_strerror (ret ));
717
741
718
742
/* We failed to rename the file. Try to restore the name in header. */
719
- pfs = pf_rename (enc -> pf , old_path , & new_root_gmac );
743
+ pfs = pf_rename (enc -> pf , old_norm_path , & new_root_gmac );
720
744
if (PF_FAILURE (pfs )) {
721
745
log_warning ("pf_rename (during cleanup) failed, the file might be unusable: %s" ,
722
746
pf_strerror (pfs ));
723
747
}
724
-
748
+ old_norm_path = NULL ; // don't free it later ...
725
749
ret = pal_to_unix_errno (ret );
726
750
goto out ;
727
751
}
728
- // TODO (MST): everything worked fine, so
729
- // - get state for old_path
730
- // abort if it doesn't exist and we are in strict protection_mode
731
- // - add new_path together with new_root_gmac and copy state from old_path entry (should be
732
- // either PF_FILE_IN_USE_EXISTING, PF_FILE_IN_USE_NEW or PF_FILE_CLOSED)
733
- // - remove old_path from map & set its state to PF_FILE_DELETED.
752
+ log_debug ("file '%s' renamed to '%s' with MAC=" MAC_PRINTF_PATTERN , old_norm_path ,
753
+ new_norm_path ,
754
+ MAC_PRINTF_ARGS (new_root_gmac )); // TODO (MST): remove me eventually?
755
+ lock (& (enc -> volume -> files_state_map_lock ));
756
+ struct libos_encrypted_volume_state_map * old_file_state = NULL ;
757
+ HASH_FIND_STR (enc -> volume -> files_state_map , old_norm_path , old_file_state );
758
+ assert (old_file_state != NULL );
759
+ struct libos_encrypted_volume_state_map * new_file_state = NULL ;
760
+ HASH_FIND_STR (enc -> volume -> files_state_map , new_norm_path , new_file_state );
761
+ if (new_file_state == NULL ) {
762
+ new_file_state = malloc (sizeof (struct libos_encrypted_volume_state_map ));
763
+ if (new_file_state == NULL ) {
764
+ ret = - ENOMEM ;
765
+ goto out ;
766
+ }
767
+ new_file_state -> norm_path = new_norm_path ;
768
+ HASH_ADD_KEYPTR (hh , enc -> volume -> files_state_map , new_file_state -> norm_path ,
769
+ strlen (new_file_state -> norm_path ), new_file_state );
770
+ } else {
771
+ free (new_file_state -> norm_path ); // should be same but free old one to simplify below
772
+ new_file_state -> norm_path = new_norm_path ;
773
+ }
774
+ new_file_state -> state = old_file_state -> state ;
775
+ memcpy (new_file_state -> last_seen_root_gmac , new_root_gmac , sizeof (pf_mac_t ));
776
+ old_file_state -> state = PF_FILE_DELETED ;
777
+ memset (old_file_state -> last_seen_root_gmac , 0 , sizeof (pf_mac_t ));
778
+ unlock (& (enc -> volume -> files_state_map_lock ));
734
779
735
780
free (enc -> uri );
736
- enc -> uri = new_uri_copy ;
781
+ enc -> uri = new_uri_copy ;
737
782
new_uri_copy = NULL ;
783
+ enc -> norm_path = new_norm_path ;
784
+ new_norm_path = NULL ;
785
+
738
786
ret = 0 ;
739
787
740
788
out :
741
- // TODO (MST): in case of error
742
- // - set state for old_path to PF_FILE_ERROR (even when restore rename worked? or just update
743
- // hash in that case?) Also correspondingly set pf->file_status =
744
- // PF_STATUS_CORRUPTED?)
745
- free (new_normpath );
789
+ if (ret ) {
790
+ // store in file state map fact that we could not rename file properly
791
+ if (!locked (& (enc -> volume -> files_state_map_lock ))) // for OOM case from above!
792
+ lock (& (enc -> volume -> files_state_map_lock ));
793
+ if (old_file_state == NULL ) // we might already have it!
794
+ HASH_FIND_STR (enc -> volume -> files_state_map , old_norm_path , old_file_state );
795
+ assert (old_file_state != NULL );
796
+ old_file_state -> state = PF_FILE_ERROR ;
797
+ pf_set_corrupted (enc -> pf );
798
+ unlock (& (enc -> volume -> files_state_map_lock ));
799
+ }
800
+ free (old_norm_path );
801
+ free (new_norm_path );
746
802
free (new_uri_copy );
747
803
return ret ;
748
804
}
0 commit comments