Bug #58962
openftruncate fails with EACCES on a read-only file created with write permissions
0%
Description
When creating a new file with write permissions, with mode set to read-only such as 400 or 444, ftruncate fails with EACCES. This has been a problem recently discovered, that has been around since at least August 2020. I have confirmed this with ceph-fuse, but I'm unsure if the same problem exists within the Linux Ceph kernel driver.
The snippet I used to test this behaviour:
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
void print(char *verb, int perms) {
fprintf(stdout, "%s with permissions %o: error #%d %s\n", verb, perms, errno, strerror(errno));
}
int main(int argc, char *argv[]) {
const char *fn = "./ceph/testfile";
const int permissions[2] = { 0666, 0444 };
int fd;
int i;
for (i = 0; i < 2; i++) {
if ((fd = open(fn, O_CREAT | O_WRONLY, permissions[i])) < 0) {
print("Can't create", permissions[i]);
} else {
if (ftruncate(fd, 0) != 0) {
print("Can't truncate", permissions[i]);
} else {
print("Succesfully truncated", permissions[i]);
}
close(fd);
unlink(fn);
}
}
}
The expected output since both files are created with write permissions would be to complete successfully, but the second operation results in failure instead:
$ ./ceph-test Succesfully truncated with permissions 666: error #0 Success Can't truncate with permissions 444: error #13 Permission deniedAdditionally, the EACCES return value is invalid as per the standards, because either we have a valid writable file descriptor, or it should return EBADF/EINVAL:
- https://pubs.opengroup.org/onlinepubs/000095399/functions/ftruncate.html
- https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
I'll also leave a link to the relevant discussion with Node/libuv where we encountered this problem, which has additional information albeit tangential: https://github.com/libuv/libuv/issues/3919
Updated by Bruno Passeri about 1 year ago
Forgot to mention that this has been recently verified on v15.2.17 and v16.2.11.
Updated by Venky Shankar about 1 year ago
Apologies for looking into this rather late, Bruno.
Updated by Venky Shankar about 1 year ago
- Assignee set to Venky Shankar
- Target version set to v18.0.0
- Backport set to pacific,quincy
Updated by Venky Shankar about 1 year ago
This happens when setattr is called on truncate and looks like an incorrect check in inode_permission().
2023-04-05T06:18:22.819-0400 7fd4fa7fc6c0 8 client.474148 _ll_setattrx 0x10000000008.head mask 20 2023-04-05T06:18:22.819-0400 7fd4fa7fc6c0 20 client.474148 may_setattr 0x10000000008.head(faked_ino=0 nref=10 ll_ref=2 cap_refs={} open={2=1} mode=100444 size=0/4194304 nlink=1 btime=2023-04-05T06:18:22.820259-0400 mtime=2023-04-05T06:18:22.820259-0400 ctime=2023-04-05T06:18:22.820259-0400 change_attr=0 caps=pAsxLsXsxFsxcrwb(0=pAsxLsXsxFsxcrwb) objectset[0x10000000008 ts 0/0 objects 0 dirty_or_tx 0] parents=0x1.head["testfile"] 0x7fd504008330); UserPerm(uid: 1000, gid: 1000) 2023-04-05T06:18:22.819-0400 7fd4fa7fc6c0 10 client.474148 _getattr mask As issued=1 2023-04-05T06:18:22.819-0400 7fd4fa7fc6c0 3 client.474148 may_setattr 0x7fd504008330 = -13 2023-04-05T06:18:22.819-0400 7fd4fa7fc6c0 3 client.474148 ll_setattr 0x10000000008.head = -13
I'll push a fix.
Updated by Venky Shankar about 1 year ago
- Category set to Correctness/Safety
- Target version changed from v18.0.0 to v19.0.0
- Backport changed from pacific,quincy to reef,quincy,pacific
Updated by Venky Shankar about 1 year ago
ftruncate end up calling Client::ll_setattr() with size=0 in ceph-fuse. Note that there is no file handle (fh) that's passed to userspace. Now, this piece of code is what causes the failure (from Client::ll_setattrx):
if (!fuse_default_permissions) { int res = may_setattr(in, stx, mask, perms); if (res < 0) return res; }
This check is performed when fuse_default_permissions is unset (default). Setting this config to true (`fuse default permissions = true`) fixes the issue. You could use that if use of Posix ACLs are not desired.
Updated by Venky Shankar about 1 year ago
And BTW, the linux kernel driver does not have this issue.
Updated by Patrick Donnelly 13 days ago
- Target version changed from v19.0.0 to v20.0.0