Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs.copyFile fails with "EPERM" for CIFS destination #31170

Closed
likwidoxigen opened this issue Jan 3, 2020 · 6 comments
Closed

fs.copyFile fails with "EPERM" for CIFS destination #31170

likwidoxigen opened this issue Jan 3, 2020 · 6 comments
Labels
fs Issues and PRs related to the fs subsystem / file system. libuv Issues and PRs related to the libuv dependency or the uv binding. linux Issues and PRs related to the Linux platform.

Comments

@likwidoxigen
Copy link

likwidoxigen commented Jan 3, 2020

  • Version: 12.10.0 & 10.10.0 Both tested
  • Platform: Linux 3.10.0-1062.el7.x86_64 deps: update openssl to 1.0.1j #1 SMP Thu Jul 18 20:25:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux (RHEL7.7)
  • Subsystem: LibUV

require("fs").copyFile("/local/home/dim/testcopy/test.txt","/transfer/repository/Temp/test2.txt", (err) => { if (err) throw err; console.log('source.txt was copied to destination.txt'); } );

strace: https://gist.github.com/likwidoxigen/54a9f34c82772a84ae0a274994ef2774
The EPERM Error is at line 789, I don't know what else may be relevant so I didn't trim anything.
Using "cp" command works with no problem.
The copy fails if source path is on local system or CIFS share as long as destination path is on the CIFS share.
When files are copied or created on that share they are owned by a different user. So files are being copied as user "dim" and the owner that gets automatically set on the share is "cloudxfer".
If I run the script as the "cloudxfer" user, it all runs fine and everything is great, but if I can copy the file from the command line as "dim" I should be able to use copyFile.

@lolobug
Copy link

lolobug commented Jan 3, 2020

I'm also in trouble with copyFile in some Android devices.
EPERM: operation not permitted, copyfile '/storage/emulated/0/tencent/MicroMsg/wxafiles/wx8b3a98563fc40251/tmp_dcd8ad42aef82e70cde76423db5c55d982cfc1a8ea619682' -> '/storage/emulated/0/tencent/MicroMsg/wxanewfiles/7cee4ddf37306b58b38bc535383be489/layaairGame/tmp_dcd8ad42aef82e70cde76423db5c55d982cfc1a8ea619682.png'

I can't reproduce the error but a lot of errors as above are reported.
Pls show me the possible reasons..

@bnoordhuis bnoordhuis added fs Issues and PRs related to the fs subsystem / file system. libuv Issues and PRs related to the libuv dependency or the uv binding. linux Issues and PRs related to the Linux platform. labels Jan 3, 2020
@bnoordhuis
Copy link
Member

The relevant bits from the strace log:

[pid 15619] open("/local/home/dim/testcopy/test.txt", O_RDONLY|O_CLOEXEC) = 17
[pid 15619] fstat(17, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
[pid 15619] open("/transfer/repository/Temp/test2.txt", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0100644 = 18
[pid 15619] fstat(18, {st_mode=S_IFREG|0775, st_size=0, ...}) = 0
[pid 15619] fchmod(18, 0100644)         = -1 EPERM (Operation not permitted)
[pid 15619] close(17)                   = 0
[pid 15619] close(18)                   = 0
[pid 15619] unlink("/transfer/repository/Temp/test2.txt") = 0

Libuv tries to change the destination file's permissions with fchmod() to match the source file but it's rejected by the kernel.

I postulate CIFS doesn't like that we're passing in the S_IFREG flag (0100000) from fstat() verbatim. Can you try this patch?

diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index be256bfca6..2324cb67b6 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -1092,6 +1092,8 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
     goto out;
   }
 
+  /* Only use bits 0-11: user/group/other rwx + sticky + sgid + suid. */
+  src_statsbuf.st_mode &= 4095;
   dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
 
   if (req->flags & UV_FS_COPYFILE_EXCL)

@likwidoxigen
Copy link
Author

I've never built node before, but our sysadmin gave me a RHEL7 and root access so I'll give it a shot and keep you posted.
Thanks!

@likwidoxigen
Copy link
Author

likwidoxigen commented Jan 5, 2020

Ok, so today has been an adventure.
Built vanilla node 12 and proved that the copy is broken.
did a make clean
Build node 12 with that change.
Still have eperm.

Relevant parts of the stack trace should be below.
If not I updated the gist.

[pid 27919] open("./test.txt", O_RDONLY|O_CLOEXEC) = 17
[pid 27919] fstat(17, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
[pid 27919] open("/transfer/repository/wellsfargo/testn12customdimtest.txt", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644 <unfinished ...>
[pid 27922] futex(0x2a60f24, FUTEX_WAIT_PRIVATE, 5, NULL <unfinished ...>
[pid 27919] <... open resumed> )        = 18
[pid 27919] fstat(18, {st_mode=S_IFREG|0775, st_size=0, ...}) = 0
[pid 27919] fchmod(18, 0644)            = -1 EPERM (Operation not permitted)
[pid 27919] close(17)                   = 0
[pid 27919] close(18)                   = 0
[pid 27919] unlink("/transfer/repository/wellsfargo/testn12customdimtest.txt") = 0

@bnoordhuis
Copy link
Member

Thanks for testing that out. I dug through fs/cifs in the linux kernel source tree and it looks like chmod() and fchmod() will always error unless you mount the CIFS share with noperm, in which case they become no-ops.

I suppose that makes sense because UNIX-style permissions don't have a Windows counterpart.

Libuv can probably detect this particular condition. I've opened libuv/libuv#2596 to discuss.

@likwidoxigen
Copy link
Author

Wow, well that's an easy fix (for getting me up and running). I can confirm that when the CIFS share is mounted with "noperm" copyFile() works like a charm through node.

bnoordhuis added a commit to bnoordhuis/libuv that referenced this issue Jan 5, 2020
uv_fs_copyfile() calls fchmod() to change the target file's permissions
to the source file's permissions but that operation errors with EPERM on
CIFS shares unless they are mounted with the "noperm" option.

Since UNIX-style permissions don't make sense for CIFS anyway, let's
handle the error in libuv by recognizing that it's a CIFS share and
continuing when that is the case.

The same logic probably applies to (a subset of) FUSE file systems but
those haven't been whitelisted yet.

Fixes: libuv#2596
Refs: nodejs/node#31170
cjihrig pushed a commit to libuv/libuv that referenced this issue Jan 8, 2020
uv_fs_copyfile() calls fchmod() to change the target file's permissions
to the source file's permissions but that operation errors with EPERM on
CIFS shares unless they are mounted with the "noperm" option.

Since UNIX-style permissions don't make sense for CIFS anyway, let's
handle the error in libuv by recognizing that it's a CIFS share and
continuing when that is the case.

The same logic probably applies to (a subset of) FUSE file systems but
those haven't been whitelisted yet.

Fixes: #2596
Refs: nodejs/node#31170
PR-URL: #2597
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Saúl Ibarra Corretgé <[email protected]>
cjihrig added a commit to cjihrig/node that referenced this issue Jan 12, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: nodejs#31170
@Trott Trott closed this as completed in 216e423 Jan 15, 2020
MylesBorins pushed a commit that referenced this issue Jan 16, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: #31170

PR-URL: #31332
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
BethGriggs pushed a commit to BethGriggs/node that referenced this issue Feb 26, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: nodejs#31170

PR-URL: nodejs#31332
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
BethGriggs pushed a commit that referenced this issue Mar 2, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: #31170

PR-URL: #31332
Backport-PR-URL: #31969
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
codebytere pushed a commit that referenced this issue Mar 14, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: #31170

PR-URL: #31332
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
codebytere pushed a commit that referenced this issue Mar 17, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: #31170

PR-URL: #31332
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
zcbenz pushed a commit to yue/node that referenced this issue Apr 3, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: nodejs/node#31170

PR-URL: nodejs/node#31332
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
zcbenz pushed a commit to yue/node that referenced this issue Apr 3, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: nodejs/node#31170

PR-URL: nodejs/node#31332
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
zcbenz pushed a commit to yue/node that referenced this issue Apr 3, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: nodejs/node#31170

PR-URL: nodejs/node#31332
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
zcbenz pushed a commit to yue/node that referenced this issue Apr 3, 2020
Notable changes:

- uv_fs_copyfile() now supports CIFS share destinations.
- isatty() now works on IBMi
- TTYs are opened with the O_NOCTTY flag.

Fixes: nodejs/node#31170

PR-URL: nodejs/node#31332
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: David Carlier <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system. libuv Issues and PRs related to the libuv dependency or the uv binding. linux Issues and PRs related to the Linux platform.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants