]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Use faccessat2 instead of access
authorAki Tuomi <aki.tuomi@open-xchange.com>
Thu, 25 Nov 2021 08:52:53 +0000 (10:52 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 6 Oct 2023 16:00:06 +0000 (16:00 +0000)
This allows checking with effective credentials.

configure.ac
m4/faccessat2.m4 [new file with mode: 0644]
src/lib-storage/index/dbox-multi/mdbox-storage.c
src/lib-storage/index/dbox-single/sdbox-storage.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/mbox/mbox-lock.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/mail-storage-settings.c
src/lib/lib.h

index 74090b44a12acba6e422fc19d752772cf77d92f8..5a771bd851afce24c3d0821a9e8ce45e28c0b57c 100644 (file)
@@ -427,6 +427,7 @@ DOVECOT_LINUX_MREMAP
 DOVECOT_MMAP_WRITE
 
 DOVECOT_FD_PASSING
+DOVECOT_FACCESSAT2
 
 DOVECOT_SENDFILE
 
diff --git a/m4/faccessat2.m4 b/m4/faccessat2.m4
new file mode 100644 (file)
index 0000000..1288d50
--- /dev/null
@@ -0,0 +1,10 @@
+AC_DEFUN([DOVECOT_FACCESSAT2], [
+  dnl * Do we have the syscall faccessat2
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+    #include <asm/unistd.h>
+  ]], [[
+    int syscall = __NR_faccessat2;
+  ]])],[
+    AC_DEFINE(HAVE_FACCESSAT2,, [Define if we have syscall faccessat2])
+  ],[])
+])
index e9cf42deca2f05461731436483c53a825069b942..50397598a3738dce29453570d67f3f0f8a608f1f 100644 (file)
@@ -101,7 +101,7 @@ mdbox_storage_find_root_dir(const struct mail_namespace *ns)
        if (ns->owner != NULL &&
            mail_user_get_home(ns->owner, &home) > 0) {
                path = t_strconcat(home, "/mdbox", NULL);
-               if (access(path, R_OK|W_OK|X_OK) == 0) {
+               if (i_faccessat2(AT_FDCWD, path, R_OK | W_OK | X_OK, AT_EACCESS) == 0) {
                        e_debug(event,
                                "mdbox autodetect: root exists (%s)", path);
                        return path;
index bb07cf7c969746df0d180e9f237699117a1f01d0..45d5cfc26fd54d8dc96c9055183391edc0198d85 100644 (file)
@@ -65,7 +65,7 @@ sdbox_storage_find_root_dir(const struct mail_namespace *ns)
        if (ns->owner != NULL &&
            mail_user_get_home(ns->owner, &home) > 0) {
                path = t_strconcat(home, "/sdbox", NULL);
-               if (access(path, R_OK|W_OK|X_OK) == 0) {
+               if (i_faccessat2(AT_FDCWD, path, R_OK | W_OK | X_OK, AT_EACCESS) == 0) {
                        e_debug(event,
                                "sdbox autodetect: root exists (%s)", path);
                        return path;
index 6cb058bd4cdeb1fa2e6dbbd3ecbbecda4f60d238..a9d6fe5ec7f42c6e28e827c431abcf66fb1c297e 100644 (file)
@@ -106,7 +106,7 @@ maildir_storage_find_root_dir(const struct mail_namespace *ns)
        if (ns->owner != NULL &&
            mail_user_get_home(ns->owner, &home) > 0) {
                path = t_strconcat(home, "/Maildir", NULL);
-               if (access(path, R_OK|W_OK|X_OK) == 0) {
+               if (i_faccessat2(AT_FDCWD, path, R_OK | W_OK | X_OK, AT_EACCESS) == 0) {
                        e_debug(event,
                                "maildir autodetect: root exists (%s)", path);
                        return path;
@@ -115,7 +115,7 @@ maildir_storage_find_root_dir(const struct mail_namespace *ns)
                        "maildir autodetect: access(%s, rwx): failed: %m", path);
        } else {
                e_debug(event, "maildir autodetect: Home directory not set");
-               if (access("/cur", R_OK|W_OK|X_OK) == 0) {
+               if (i_faccessat2(AT_FDCWD, "/cur", R_OK | W_OK | X_OK, AT_EACCESS) == 0) {
                        e_debug(event,
                                "maildir autodetect: /cur exists, assuming chroot");
                        return "/";
@@ -712,7 +712,7 @@ bool maildir_is_backend_readonly(struct maildir_mailbox *mbox)
                const char *box_path = mailbox_get_path(&mbox->box);
 
                mbox->backend_readonly_set = TRUE;
-               if (access(t_strconcat(box_path, "/cur", NULL), W_OK) < 0 &&
+               if (i_faccessat2(AT_FDCWD, t_strconcat(box_path, "/cur", NULL), W_OK, AT_EACCESS) < 0 &&
                    errno == EACCES)
                        mbox->backend_readonly = TRUE;
        }
index 2432866ec01f8e797531e8091a32e67192f8cbd9..7c4202367ec5c0567fdcd84808b308ec4aa7c92f 100644 (file)
@@ -281,7 +281,7 @@ mbox_dotlock_privileged_op(struct mbox_mailbox *mbox,
                fname++;
        }
        if (op == MBOX_DOTLOCK_OP_LOCK) {
-               if (access(fname, R_OK) < 0) {
+               if (i_faccessat2(AT_FDCWD, fname, R_OK, AT_EACCESS) < 0) {
                        mailbox_set_critical(&mbox->box,
                                "access(%s) failed: %m", box_path);
                        i_close_fd(&orig_dir_fd);
index bd9ca7edd234a93c5ad18f54cbe34462c75ffc97..7a7f5fc86e765ca35fb1c13dbe8ce5c9852f8442 100644 (file)
@@ -232,7 +232,7 @@ static bool mbox_is_file(const char *path, const char *name, struct event *event
                        name, path);
                return FALSE;
        }
-       if (access(path, R_OK|W_OK) < 0) {
+       if (i_faccessat2(AT_FDCWD, path, R_OK | W_OK, AT_EACCESS) < 0) {
                e_debug(event, "mbox autodetect: %s: no R/W access (%s)",
                        name, path);
                return FALSE;
@@ -256,7 +256,7 @@ static bool mbox_is_dir(const char *path, const char *name, struct event *event)
                        name, path);
                return FALSE;
        }
-       if (access(path, R_OK|W_OK|X_OK) < 0) {
+       if (i_faccessat2(AT_FDCWD, path, R_OK | W_OK | X_OK, AT_EACCESS) < 0) {
                e_debug(event, "mbox autodetect: %s: no R/W/X access (%s)",
                        name, path);
                return FALSE;
@@ -305,14 +305,14 @@ mbox_storage_find_inbox_file(struct mail_user *user, struct event *event)
        const char *path;
 
        path = t_strconcat("/var/mail/", user->username, NULL);
-       if (access(path, R_OK|W_OK) == 0) {
+       if (i_faccessat2(AT_FDCWD, path, R_OK | W_OK, AT_EACCESS) == 0) {
                e_debug(event, "mbox autodetect: INBOX exists (%s)", path);
                return path;
        }
        e_debug(event, "mbox autodetect: INBOX: access(%s, rw) failed: %m", path);
 
        path = t_strconcat("/var/spool/mail/", user, NULL);
-       if (access(path, R_OK|W_OK) == 0) {
+       if (i_faccessat2(AT_FDCWD, path, R_OK | W_OK, AT_EACCESS) == 0) {
                e_debug(event, "INBOX exists (%s)", path);
                return path;
        }
@@ -811,7 +811,7 @@ bool mbox_is_backend_readonly(struct mbox_mailbox *mbox)
 {
        if (!mbox->backend_readonly_set) {
                mbox->backend_readonly_set = TRUE;
-               if (access(mailbox_get_path(&mbox->box), R_OK|W_OK) < 0 &&
+               if (i_faccessat2(AT_FDCWD, mailbox_get_path(&mbox->box), R_OK | W_OK, AT_EACCESS) < 0 &&
                    errno == EACCES)
                        mbox->backend_readonly = TRUE;
        }
index cbe49fa0529d679f73f1d3e635bd2afa79838bba..548f0788cf85b4d4528fd7858bb7a678f4c93683 100644 (file)
@@ -682,7 +682,7 @@ static bool mail_user_settings_check(void *_set, pool_t pool ATTR_UNUSED,
        }
 #else
        if (*set->mail_plugins != '\0' &&
-           access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
+           faccessat(AT_FDCWD, set->mail_plugin_dir, R_OK | X_OK, AT_EACCESS) < 0) {
                *error_r = t_strdup_printf(
                        "mail_plugin_dir: access(%s) failed: %m",
                        set->mail_plugin_dir);
index 636e1b0f9a7f6a161d2762eb4bdbcac631f6834d..7d945780c775dacad79d639333cd365975e0db79 100644 (file)
 #include "byteorder.h"
 #include "fd-util.h"
 
+#include <unistd.h>
+#ifdef HAVE_FACCESSAT2
+#  include <asm/unistd.h>
+#endif
+
 typedef struct buffer buffer_t;
 typedef struct buffer string_t;
 
@@ -151,4 +156,25 @@ static inline uint32_t time_to_uint32_trunc(time_t ts)
                return UINT32_MAX;
        return (uint32_t)(ts & 0xffffffff);
 }
+
+/* The original faccessat() syscall didn't handle the flag parameter.
+   glibc v2.33's faccessat() started using the new Linux faccessat2() syscall
+   However, we can still use faccessat2() syscall directly in some Linux distros
+   to avoid this problem, so just do it here when possible. */
+static inline int i_faccessat2(int fd, const char *file, int type, int flag)
+{
+#ifdef HAVE_FACCESSAT2
+       static bool failed = FALSE;
+       if (!failed) {
+               /* On bullseye the syscall is available,
+                  but the glibc wrapping function is not. */
+               int ret = syscall(__NR_faccessat2, fd, file, type, flag);
+               failed = ret == -1 && errno == ENOSYS;
+               if (!failed)
+                       return ret;
+       }
+#endif
+        return faccessat(fd, file, type, flag);
+}
+
 #endif