@@ -156,6 +156,7 @@ static void test_rename_replace(const char* path1, const char* path2) {
156
156
err (1 , "rename" );
157
157
158
158
should_not_exist (path1 );
159
+
159
160
should_exist (path2 , message1_len );
160
161
161
162
/* We expect `fd` to still point to old data, even though we replaced the file under its path */
@@ -177,6 +178,94 @@ static void test_rename_replace(const char* path1, const char* path2) {
177
178
err (1 , "unlink %s" , path2 );
178
179
}
179
180
181
+ static void test_rename_follow (const char * path1 , const char * path2 ) {
182
+ printf ("%s...\n" , __func__ );
183
+
184
+ int fd = create_file (path1 , message1 , message1_len );
185
+
186
+ if (fd < 0 )
187
+ err (1 , "open %s" , path1 );
188
+
189
+ if (rename (path1 , path2 ) != 0 )
190
+ err (1 , "rename" );
191
+
192
+ should_not_exist (path1 );
193
+ should_exist (path2 , message1_len );
194
+
195
+ if (lseek (fd , 0 , SEEK_SET ) != 0 )
196
+ err (1 , "lseek" );
197
+
198
+ ssize_t n = posix_fd_write (fd , message2 , message2_len );
199
+ if (n < 0 )
200
+ errx (1 , "posix_fd_write failed" );
201
+ if ((size_t )n != message2_len )
202
+ errx (1 , "wrote less bytes than expected" );
203
+
204
+ should_contain ("file opened before it's renamed" , fd , message2 , message2_len );
205
+
206
+ if (close (fd ) != 0 )
207
+ err (1 , "close %s" , path2 );
208
+
209
+ fd = open (path2 , O_RDONLY , 0 );
210
+ if (fd < 0 )
211
+ err (1 , "open %s" , path2 );
212
+
213
+ /* We expect `fd` to point to new data, even though we changed data via old fd after rename */
214
+ should_contain ("file opened after it's renamed" , fd , message2 , message2_len );
215
+
216
+ if (close (fd ) != 0 )
217
+ err (1 , "close %s" , path2 );
218
+
219
+ if (unlink (path2 ) != 0 )
220
+ err (1 , "unlink %s" , path2 );
221
+ }
222
+
223
+ // NOTE: below will _not_ run correctly when directly executed unless you run as root.
224
+ // But it should run properly in gramine when executed as normal user.
225
+ static void test_rename_fchown_fchmod (const char * path1 , const char * path2 ) {
226
+ printf ("%s...\n" , __func__ );
227
+
228
+ int fd = create_file (path1 , message1 , message1_len );
229
+
230
+ if (fchown (fd , 1 , 1 ))
231
+ err (1 , "fchown before rename" );
232
+ if (fchmod (fd , S_IRWXU | S_IRWXG ) != 0 ) // Note: no other!
233
+ err (1 , "fchmod before rename" );
234
+ struct stat st ;
235
+ if (stat (path1 , & st ) != 0 )
236
+ err (1 , "Failed to stat file %s" , path1 );
237
+ if (st .st_uid != 1 || st .st_gid != 1 )
238
+ err (1 , "wrong ownership of file %s" , path1 );
239
+ if (st .st_mode & S_IRWXO )
240
+ err (1 , "wrong permissions of file %s" , path1 );
241
+
242
+ if (fd < 0 )
243
+ err (1 , "open %s" , path1 );
244
+
245
+ if (rename (path1 , path2 ) != 0 )
246
+ err (1 , "rename" );
247
+
248
+ should_not_exist (path1 );
249
+ should_exist (path2 , message1_len );
250
+
251
+ if (fchown (fd , 2 , 2 ))
252
+ err (1 , "fchown after rename" );
253
+ if (fchmod (fd , S_IRWXU | S_IRWXG | S_IRWXO ) != 0 ) // Note: with other now!
254
+ err (1 , "fchmod after rename" );
255
+ if (stat (path2 , & st ) != 0 )
256
+ err (1 , "Failed to stat (renamed) file %s" , path2 );
257
+ if (st .st_uid != 2 || st .st_gid != 2 )
258
+ err (1 , "wrong ownership of (renamed) file %s" , path2 );
259
+ if (!(st .st_mode & S_IRWXO ))
260
+ err (1 , "wrong permissions of (renamed) file %s" , path2 );
261
+
262
+ if (close (fd ) != 0 )
263
+ err (1 , "close %s" , path2 );
264
+
265
+ if (unlink (path2 ) != 0 )
266
+ err (1 , "unlink %s" , path2 );
267
+ }
268
+
180
269
static void test_rename_open_file (const char * path1 , const char * path2 ) {
181
270
printf ("%s...\n" , __func__ );
182
271
@@ -271,6 +360,8 @@ int main(int argc, char* argv[]) {
271
360
test_rename_same_file (path1 );
272
361
test_simple_rename (path1 , path2 );
273
362
test_rename_replace (path1 , path2 );
363
+ test_rename_follow (path1 , path2 );
364
+ test_rename_fchown_fchmod (path1 , path2 );
274
365
test_rename_open_file (path1 , path2 );
275
366
test_unlink_and_recreate (path1 );
276
367
test_unlink_and_write (path1 );
0 commit comments