Skip to content

Commit

Permalink
SystemNative_CopyFile(): move fchmod() call to top and add exception …
Browse files Browse the repository at this point in the history
…for Android.

The `fchmod()` call should happen first to ensure that the target file has the correct
permissions prior to writing into it.

On Android, we make an exception in case the `fchmod()` fails: if we can `fstat()` both
the source and the target file and the target file's permissions are at least as restrictive
as the source file's, then we allow the operation to proceed.

See mono/mono#17133 for details.
  • Loading branch information
Martin Baulig committed Oct 28, 2019
1 parent fb41040 commit 57fb181
Showing 1 changed file with 36 additions and 11 deletions.
47 changes: 36 additions & 11 deletions src/Native/Unix/System.Native/pal_io.c
Expand Up @@ -1257,6 +1257,42 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd)
int ret;
struct stat_ sourceStat;
bool copied = false;

// First, copy permissions.
while ((ret = fchmod(outFd, sourceStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) < 0 && errno == EINTR);
if (ret != 0)
{
#if MONODROID
// Exception for MonoDroid - see https://github.com/mono/mono/issues/17133.
struct stat_ targetStat;

// First, stat the source file.
while ((ret = fstat_(inFd, &sourceStat)) < 0 && errno == EINTR);
if (ret != 0)
{
// If we can't stat() it, then we likely don't have permission to read it.
return -1;
}

// Stat the target file - and if that fails, abort.
while ((ret = fstat_(outFd, &targetStat)) < 0 && errno == EINTR);
if (ret != 0)
{
return -1;
}

// If the target file has any permissions that are _less_ restrictive than the ones of the source file,
// it is unacceptable to continue and we need to abort.
if ((targetStat.st_mode & sourceStat.st_mode) != 0)
{
return -1;
}
#else
// Hard fail on all other platforms.
return -1;
#endif
}

#if HAVE_SENDFILE_4
// If sendfile is available (Linux), try to use it, as the whole copy
// can be performed in the kernel, without lots of unnecessary copying.
Expand Down Expand Up @@ -1333,17 +1369,6 @@ int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd)
while ((ret = futimes(outFd, origTimes)) < 0 && errno == EINTR);
#endif
}
if (ret != 0)
{
return -1;
}

// Then copy permissions.
while ((ret = fchmod(outFd, sourceStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) < 0 && errno == EINTR);
if (ret != 0)
{
return -1;
}

return 0;
#endif // HAVE_FCOPYFILE
Expand Down

0 comments on commit 57fb181

Please sign in to comment.