]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
stats: Workaround opening /proc/self/io in processes that have only temporarily dropp...
authorTimo Sirainen <tss@iki.fi>
Sun, 8 Dec 2013 21:26:40 +0000 (23:26 +0200)
committerTimo Sirainen <tss@iki.fi>
Sun, 8 Dec 2013 21:26:40 +0000 (23:26 +0200)
src/plugins/stats/stats-plugin.c

index ee4e9afcb7372a311f624d903ac130182781c3eb..ed610f3ea724ba16b602e9df4975cca5dcb8a017 100644 (file)
@@ -119,16 +119,33 @@ process_io_buffer_parse(const char *buf, struct mail_stats *stats)
 
 static int process_io_open(void)
 {
-       if (proc_io_fd == -1) {
-               if (proc_io_disabled)
-                       return -1;
-               proc_io_fd = open(PROC_IO_PATH, O_RDONLY);
-               if (proc_io_fd == -1) {
-                       if (errno != ENOENT)
-                               i_error("open(%s) failed: %m", PROC_IO_PATH);
-                       proc_io_disabled = TRUE;
-                       return -1;
+       uid_t uid;
+
+       if (proc_io_fd != -1)
+               return proc_io_fd;
+
+       if (proc_io_disabled)
+               return -1;
+       proc_io_fd = open(PROC_IO_PATH, O_RDONLY);
+       if (proc_io_fd == -1 && errno == EACCES) {
+               /* kludge: if we're running with permissions temporarily
+                  dropped, get them temporarily back so we can open
+                  /proc/self/io. */
+               uid = geteuid();
+               if (seteuid(0) == 0) {
+                       proc_io_fd = open(PROC_IO_PATH, O_RDONLY);
+                       if (seteuid(uid) < 0) {
+                               /* oops, this is bad */
+                               i_fatal("stats: seteuid(%s) failed", dec2str(uid));
+                       }
                }
+               errno = EACCES;
+       }
+       if (proc_io_fd == -1) {
+               if (errno != ENOENT)
+                       i_error("open(%s) failed: %m", PROC_IO_PATH);
+               proc_io_disabled = TRUE;
+               return -1;
        }
        return proc_io_fd;
 }