@@ -435,14 +435,20 @@ file_in_chroot_jail(HANDLE handle) {
435435 return 1 ;
436436 }
437437
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 */
438445 to_wlower_case (final_path );
439446 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 )] != '\\' ) {
442449 debug3 ("access denied due to attempt to escape chroot jail" );
443450 return 0 ;
444451 }
445-
446452 return 1 ;
447453}
448454
@@ -1268,6 +1274,7 @@ fileio_symlink(const char *target, const char *linkpath)
12681274 DWORD ret = -1 ;
12691275 char target_modified [PATH_MAX ] = { 0 };
12701276 char * linkpath_resolved = NULL , * target_resolved = NULL ;
1277+ wchar_t * linkpath_utf16 = NULL , * resolved_target_utf16 = NULL , * resolved_target_chroot = NULL ;
12711278
12721279 if (target == NULL || linkpath == NULL ) {
12731280 errno = EFAULT ;
@@ -1301,13 +1308,21 @@ fileio_symlink(const char *target, const char *linkpath)
13011308 strcpy_s (target_modified , _countof (target_modified ), target_resolved );
13021309 }
13031310
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 ) {
13071313 errno = ENOMEM ;
13081314 goto cleanup ;
13091315 }
13101316
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+
13111326 /* unlike other platforms, we need to know whether the symbolic link target is
13121327 * a file or a directory. the only way we can confidently do this is to
13131328 * get the attributes of the target. therefore, our symlink() has the
@@ -1338,15 +1353,18 @@ fileio_symlink(const char *target, const char *linkpath)
13381353 ret = 0 ;
13391354cleanup :
13401355
1356+ if (linkpath_resolved )
1357+ free (linkpath_resolved );
1358+
13411359 if (linkpath_utf16 )
13421360 free (linkpath_utf16 );
13431361
1362+ if (resolved_target_chroot )
1363+ free (resolved_target_chroot );
1364+
13441365 if (resolved_target_utf16 )
13451366 free (resolved_target_utf16 );
13461367
1347- if (linkpath_resolved )
1348- free (linkpath_resolved );
1349-
13501368 if (target_resolved )
13511369 free (target_resolved );
13521370
0 commit comments