]> granicus.if.org Git - sudo/commitdiff
Create I/O log files with the same gid as the parent directory.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 26 Oct 2016 20:18:58 +0000 (14:18 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 26 Oct 2016 20:18:58 +0000 (14:18 -0600)
plugins/sudoers/iolog.c

index 99b42d1df4318b99e0596eba7e483721aa136a90..26a7021b94a6476dd79b8082d2f9b6842e001ca9 100644 (file)
@@ -80,7 +80,7 @@ extern __dso_public struct io_plugin sudoers_io;
  * If is_temp is set, use mkdtemp() for the final directory.
  */
 static bool
-io_mkdirs(char *path, mode_t mode, bool is_temp)
+io_mkdirs(char *path, mode_t mode, gid_t *gidp, bool is_temp)
 {
     struct stat sb;
     gid_t parent_gid = 0;
@@ -96,6 +96,8 @@ io_mkdirs(char *path, mode_t mode, bool is_temp)
                path, (unsigned int) sb.st_mode);
            ok = false;
        }
+       if (gidp != NULL)
+           *gidp = sb.st_gid;
        debug_return_bool(ok);
     }
 
@@ -151,6 +153,8 @@ io_mkdirs(char *path, mode_t mode, bool is_temp)
            }
        }
     }
+    if (gidp != NULL)
+       *gidp = parent_gid;
     debug_return_bool(ok);
 }
 
@@ -203,6 +207,7 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
     char buf[32], *ep;
     int i, len, fd = -1;
     unsigned long id = 0;
+    gid_t gid;
     ssize_t nread;
     bool ret = false;
     char pathbuf[PATH_MAX];
@@ -212,7 +217,7 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
     /*
      * Create I/O log directory if it doesn't already exist.
      */
-    if (!io_mkdirs(iolog_dir, S_IRWXU, false))
+    if (!io_mkdirs(iolog_dir, S_IRWXU, &gid, false))
        goto done;
 
     /*
@@ -230,6 +235,7 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
        goto done;
     }
     sudo_lock_file(fd, SUDO_LOCK);
+    ignore_result(fchown(fd, (uid_t)-1, gid));
 
     /*
      * If there is no seq file in iolog_dir and a fallback dir was
@@ -245,6 +251,7 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
        if (len > 0 && (size_t)len < sizeof(fallback)) {
            int fd2 = open(fallback, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
            if (fd2 != -1) {
+               ignore_result(fchown(fd2, (uid_t)-1, gid));
                nread = read(fd2, buf, sizeof(buf) - 1);
                if (nread > 0) {
                    if (buf[nread - 1] == '\n')
@@ -321,7 +328,7 @@ done:
  * Returns SIZE_MAX on error.
  */
 static size_t
-mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize)
+mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize, gid_t *gidp)
 {
     size_t len;
     bool is_temp = false;
@@ -340,7 +347,7 @@ mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize)
      */
     if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0)
        is_temp = true;
-    if (!io_mkdirs(pathbuf, S_IRWXU, is_temp))
+    if (!io_mkdirs(pathbuf, S_IRWXU, gidp, is_temp))
        len = (size_t)-1;
 
     debug_return_size_t(len);
@@ -353,7 +360,8 @@ mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize)
  * Stores the open file handle which has the close-on-exec flag set.
  */
 static bool
-open_io_fd(char *pathbuf, size_t len, struct io_log_file *iol, bool docompress)
+open_io_fd(char *pathbuf, size_t len, gid_t gid, struct io_log_file *iol,
+    bool docompress)
 {
     debug_decl(open_io_fd, SUDOERS_DEBUG_UTIL)
 
@@ -362,6 +370,7 @@ open_io_fd(char *pathbuf, size_t len, struct io_log_file *iol, bool docompress)
     if (iol->enabled) {
        int fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR);
        if (fd != -1) {
+           ignore_result(fchown(fd, (uid_t)-1, gid));
            (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
 #ifdef HAVE_ZLIB_H
            if (docompress)
@@ -566,8 +575,8 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
  * Write the "/log" file that contains the user and command info.
  */
 static bool
-write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
-    char * const argv[], struct timeval *now)
+write_info_log(char *pathbuf, size_t len, gid_t gid,
+    struct iolog_details *details, char * const argv[], struct timeval *now)
 {
     char * const *av;
     FILE *fp;
@@ -582,6 +591,7 @@ write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
        log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf);
        debug_return_bool(false);
     }
+    ignore_result(fchown(fd, (uid_t)-1, gid));
 
     fprintf(fp, "%lld:%s:%s:%s:%s:%d:%d\n%s\n%s", (long long)now->tv_sec,
        details->user ? details->user : "unknown", details->runas_pw->pw_name,
@@ -614,6 +624,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
     const char *cp, *plugin_path = NULL;
     size_t len;
     int i, ret = -1;
+    gid_t gid;
     debug_decl(sudoers_io_open, SUDOERS_DEBUG_PLUGIN)
 
     sudo_conv = conversation;
@@ -671,18 +682,19 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
      * Make local copy of I/O log path and create it, along with any
      * intermediate subdirs.  Calls mkdtemp() if iolog_path ends in XXXXXX.
      */
-    len = mkdir_iopath(iolog_details.iolog_path, pathbuf, sizeof(pathbuf));
+    len = mkdir_iopath(iolog_details.iolog_path, pathbuf, sizeof(pathbuf),
+       &gid);
     if (len >= sizeof(pathbuf))
        goto done;
 
     /* Write log file with user and command details. */
     if (gettimeofday(&last_time, NULL) == -1)
        goto done;
-    write_info_log(pathbuf, len, &iolog_details, argv, &last_time);
+    write_info_log(pathbuf, len, gid, &iolog_details, argv, &last_time);
 
     /* Create the timing and I/O log files. */
     for (i = 0; i < IOFD_MAX; i++) {
-       if (!open_io_fd(pathbuf, len, &io_log_files[i], iolog_compress))
+       if (!open_io_fd(pathbuf, len, gid, &io_log_files[i], iolog_compress))
            goto done;
     }