This allows checking with effective credentials.
DOVECOT_MMAP_WRITE
DOVECOT_FD_PASSING
+DOVECOT_FACCESSAT2
DOVECOT_SENDFILE
--- /dev/null
+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])
+ ],[])
+])
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;
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;
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;
"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 "/";
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;
}
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);
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;
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;
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;
}
{
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;
}
}
#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);
#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;
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