@@ -435,14 +435,20 @@ file_in_chroot_jail(HANDLE handle) {
435
435
return 1 ;
436
436
}
437
437
438
+ return file_in_chroot_jail_helper (final_path );
439
+ }
440
+
441
+ /* returns 1 if true, 0 otherwise */
442
+ int
443
+ file_in_chroot_jail_helper (wchar_t * final_path ) {
444
+ /* ensure final path is within chroot */
438
445
to_wlower_case (final_path );
439
446
if ((wcslen (final_path ) < wcslen (chroot_pathw )) ||
440
- memcmp (final_path , chroot_pathw , 2 * wcslen (chroot_pathw )) != 0 ||
441
- final_path [wcslen (chroot_pathw )] != '\\' ) {
447
+ memcmp (final_path , chroot_pathw , 2 * wcslen (chroot_pathw )) != 0 ||
448
+ final_path [wcslen (chroot_pathw )] != '\\' ) {
442
449
debug3 ("access denied due to attempt to escape chroot jail" );
443
450
return 0 ;
444
451
}
445
-
446
452
return 1 ;
447
453
}
448
454
@@ -1268,6 +1274,7 @@ fileio_symlink(const char *target, const char *linkpath)
1268
1274
DWORD ret = -1 ;
1269
1275
char target_modified [PATH_MAX ] = { 0 };
1270
1276
char * linkpath_resolved = NULL , * target_resolved = NULL ;
1277
+ wchar_t * linkpath_utf16 = NULL , * resolved_target_utf16 = NULL , * resolved_target_chroot = NULL ;
1271
1278
1272
1279
if (target == NULL || linkpath == NULL ) {
1273
1280
errno = EFAULT ;
@@ -1301,13 +1308,21 @@ fileio_symlink(const char *target, const char *linkpath)
1301
1308
strcpy_s (target_modified , _countof (target_modified ), target_resolved );
1302
1309
}
1303
1310
1304
- wchar_t * linkpath_utf16 = resolved_path_utf16 (linkpath );
1305
- wchar_t * resolved_target_utf16 = utf8_to_utf16 (target_modified );
1306
- if (resolved_target_utf16 == NULL || linkpath_utf16 == NULL ) {
1311
+ if ((linkpath_utf16 = resolved_path_utf16 (linkpath )) == NULL ||
1312
+ (resolved_target_utf16 = utf8_to_utf16 (target_modified )) == NULL ) {
1307
1313
errno = ENOMEM ;
1308
1314
goto cleanup ;
1309
1315
}
1310
1316
1317
+ /* if chroot, get full path for target, similar to behavior in realpath() in misc.c
1318
+ note: _wfullpath() is required to resolve paths containing unicode characters */
1319
+ if (chroot_pathw != NULL &&
1320
+ (resolved_target_chroot = _wfullpath (NULL , resolved_target_utf16 , 0 )) != NULL &&
1321
+ file_in_chroot_jail_helper (resolved_target_chroot ) != 1 ) {
1322
+ errno = EPERM ;
1323
+ goto cleanup ;
1324
+ }
1325
+
1311
1326
/* unlike other platforms, we need to know whether the symbolic link target is
1312
1327
* a file or a directory. the only way we can confidently do this is to
1313
1328
* get the attributes of the target. therefore, our symlink() has the
@@ -1338,15 +1353,18 @@ fileio_symlink(const char *target, const char *linkpath)
1338
1353
ret = 0 ;
1339
1354
cleanup :
1340
1355
1356
+ if (linkpath_resolved )
1357
+ free (linkpath_resolved );
1358
+
1341
1359
if (linkpath_utf16 )
1342
1360
free (linkpath_utf16 );
1343
1361
1362
+ if (resolved_target_chroot )
1363
+ free (resolved_target_chroot );
1364
+
1344
1365
if (resolved_target_utf16 )
1345
1366
free (resolved_target_utf16 );
1346
1367
1347
- if (linkpath_resolved )
1348
- free (linkpath_resolved );
1349
-
1350
1368
if (target_resolved )
1351
1369
free (target_resolved );
1352
1370
0 commit comments