From 97efaa73b0dff6b96c80e4504abb40d3e5cf653d Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Thu, 25 Nov 2021 10:52:53 +0200 Subject: [PATCH] lib-storage: Use faccessat2 instead of access This allows checking with effective credentials. --- configure.ac | 1 + m4/faccessat2.m4 | 10 +++++++ .../index/dbox-multi/mdbox-storage.c | 2 +- .../index/dbox-single/sdbox-storage.c | 2 +- .../index/maildir/maildir-storage.c | 6 ++--- src/lib-storage/index/mbox/mbox-lock.c | 2 +- src/lib-storage/index/mbox/mbox-storage.c | 10 +++---- src/lib-storage/mail-storage-settings.c | 2 +- src/lib/lib.h | 26 +++++++++++++++++++ 9 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 m4/faccessat2.m4 diff --git a/configure.ac b/configure.ac index 74090b44a1..5a771bd851 100644 --- a/configure.ac +++ b/configure.ac @@ -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 index 0000000000..1288d50833 --- /dev/null +++ b/m4/faccessat2.m4 @@ -0,0 +1,10 @@ +AC_DEFUN([DOVECOT_FACCESSAT2], [ + dnl * Do we have the syscall faccessat2 + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + ]], [[ + int syscall = __NR_faccessat2; + ]])],[ + AC_DEFINE(HAVE_FACCESSAT2,, [Define if we have syscall faccessat2]) + ],[]) +]) diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage.c b/src/lib-storage/index/dbox-multi/mdbox-storage.c index e9cf42deca..50397598a3 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-storage.c +++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c @@ -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; diff --git a/src/lib-storage/index/dbox-single/sdbox-storage.c b/src/lib-storage/index/dbox-single/sdbox-storage.c index bb07cf7c96..45d5cfc26f 100644 --- a/src/lib-storage/index/dbox-single/sdbox-storage.c +++ b/src/lib-storage/index/dbox-single/sdbox-storage.c @@ -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; diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index 6cb058bd4c..a9d6fe5ec7 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -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; } diff --git a/src/lib-storage/index/mbox/mbox-lock.c b/src/lib-storage/index/mbox/mbox-lock.c index 2432866ec0..7c4202367e 100644 --- a/src/lib-storage/index/mbox/mbox-lock.c +++ b/src/lib-storage/index/mbox/mbox-lock.c @@ -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); diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index bd9ca7edd2..7a7f5fc86e 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -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; } diff --git a/src/lib-storage/mail-storage-settings.c b/src/lib-storage/mail-storage-settings.c index cbe49fa052..548f0788cf 100644 --- a/src/lib-storage/mail-storage-settings.c +++ b/src/lib-storage/mail-storage-settings.c @@ -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); diff --git a/src/lib/lib.h b/src/lib/lib.h index 636e1b0f9a..7d945780c7 100644 --- a/src/lib/lib.h +++ b/src/lib/lib.h @@ -44,6 +44,11 @@ #include "byteorder.h" #include "fd-util.h" +#include +#ifdef HAVE_FACCESSAT2 +# include +#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 -- 2.47.3