summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcore_unix_p.h
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-09-21 17:36:36 -0700
committerThiago Macieira <thiago.macieira@intel.com>2023-10-17 19:08:25 -0700
commitc94bed69b7d84ff072eb370f3d754831eaaba08e (patch)
tree12cece3913e9a18bff76c2d78aaab34537cbdba3 /src/corelib/kernel/qcore_unix_p.h
parent25b19907842b199037a100abd97f2126f34ea3d6 (diff)
moveToTrash/Unix: refactor to use openat()/mkdirat()/renameat()
This ensures much better security against race conditions and attacks, at the expense of a few more system calls. On first run (when no trash dir is yet present): openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory) mkdirat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", 0700) = 0 openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5 newfstatat(5, "", {st_mode=S_IFDIR|0700, st_size=0, ...}, AT_EMPTY_PATH) = 0 getuid() = 1000 openat(5, "files", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory) mkdirat(5, "files", 0700) = 0 openat(5, "files", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6 openat(5, "info", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory) mkdirat(5, "info", 0700) = 0 openat(5, "info", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 7 close(5) = 0 openat(7, "tst_qfile.moveToTrashOpenFile.fjYRxv.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 5 openat(AT_FDCWD, "/usr/share/zoneinfo/UTC", O_RDONLY|O_CLOEXEC) = 8 newfstatat(8, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0 newfstatat(8, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0 read(8, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 114 lseek(8, -60, SEEK_CUR) = 54 read(8, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 60 close(8) = 0 write(5, "[Trash Info]\nPath=/home/tjmaciei"..., 103) = 103 renameat(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.fjYRxv", 6, "tst_qfile.moveToTrashOpenFile.fjYRxv") = 0 close(5) = 0 close(6) = 0 close(7) = 0 On subsequent runs: openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5 newfstatat(5, "", {st_mode=S_IFDIR|0700, st_size=18, ...}, AT_EMPTY_PATH) = 0 getuid() = 1000 openat(5, "files", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6 openat(5, "info", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 7 close(5) = 0 openat(7, "tst_qfile.moveToTrashOpenFile.sPjrcA.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 5 openat(AT_FDCWD, "/usr/share/zoneinfo/UTC", O_RDONLY|O_CLOEXEC) = 8 newfstatat(8, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0 newfstatat(8, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0 read(8, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 114 lseek(8, -60, SEEK_CUR) = 54 read(8, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 60 close(8) = 0 write(5, "[Trash Info]\nPath=/home/tjmaciei"..., 103) = 103 renameat(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.sPjrcA", 6, "tst_qfile.moveToTrashOpenFile.sPjrcA") = 0 close(5) = 0 close(6) = 0 close(7) = 0 Change-Id: I9d43e5b91eb142d6945cfffd1787117927650dab Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Diffstat (limited to 'src/corelib/kernel/qcore_unix_p.h')
-rw-r--r--src/corelib/kernel/qcore_unix_p.h10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 0ec3140cee..2d55b9dcdc 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -204,6 +204,16 @@ Q_CORE_EXPORT int qt_open64(const char *pathname, int flags, mode_t);
# endif
#endif
+#ifdef AT_FDCWD
+static inline int qt_safe_openat(int dfd, const char *pathname, int flags, mode_t mode = 0777)
+{
+ // everyone already has O_CLOEXEC
+ int fd;
+ EINTR_LOOP(fd, openat(dfd, pathname, flags | O_CLOEXEC, mode));
+ return fd;
+}
+#endif
+
// don't call QT_OPEN or ::open
// call qt_safe_open
static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)