]> granicus.if.org Git - sudo/commitdiff
Add PERM_IOLOG so we can create I/O log files on an NFS-mounted
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 21 Mar 2017 19:41:14 +0000 (13:41 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 21 Mar 2017 19:41:14 +0000 (13:41 -0600)
filesystem where root is remapped to an unprivileged user.

doc/sudoers.cat
doc/sudoers.man.in
doc/sudoers.mdoc.in
plugins/sudoers/iolog.c
plugins/sudoers/mkdir_parents.c
plugins/sudoers/set_perms.c
plugins/sudoers/sudoers.h
plugins/sudoers/timestamp.c

index b0caee9344a3c9239a1f17d949fab73d2b4059b4..5c5c3c8dbeca4e29dd46535d466b0f6e57c612b9 100644 (file)
@@ -1626,9 +1626,11 @@ S\bSU\bUD\bDO\bOE\bER\bRS\bS O\bOP\bPT\bTI\bIO\bON\bNS\bS
                        higher.
 
      iolog_group       The group name to look up when setting the group ID on
-                       new I/O log files and directories.  By default, I/O log
-                       files and directories inherit the group ID of the
-                       parent directory.
+                       new I/O log files and directories.  If _\bi_\bo_\bl_\bo_\bg_\b__\bg_\br_\bo_\bu_\bp is
+                       not set, the primary group ID of the user specified by
+                       _\bi_\bo_\bl_\bo_\bg_\b__\bu_\bs_\be_\br is used.  If neither _\bi_\bo_\bl_\bo_\bg_\b__\bg_\br_\bo_\bu_\bp nor
+                       _\bi_\bo_\bl_\bo_\bg_\b__\bu_\bs_\be_\br are set, I/O log files and directories are
+                       created with group ID 0.
 
                        This setting is only supported by version 1.8.19 or
                        higher.
@@ -1646,10 +1648,11 @@ S\bSU\bUD\bDO\bOE\bER\bRS\bS O\bOP\bPT\bTI\bIO\bON\bNS\bS
                        This setting is only supported by version 1.8.19 or
                        higher.
 
-     iolog_user        The user name to look up when setting the user ID on
-                       new I/O log files and directories.  By default, I/O log
-                       files and directories are owned by the superuser (user
-                       ID 0).
+     iolog_user        The user name to look up when setting the user and
+                       group IDs on new I/O log files and directories.  If
+                       _\bi_\bo_\bl_\bo_\bg_\b__\bg_\br_\bo_\bu_\bp is set, it will be used instead of the
+                       user's primary group ID.  By default, I/O log files and
+                       directories are created with user and group ID 0.
 
                        This setting is only supported by version 1.8.19 or
                        higher.
@@ -2760,4 +2763,4 @@ D\bDI\bIS\bSC\bCL\bLA\bAI\bIM\bME\bER\bR
      file distributed with s\bsu\bud\bdo\bo or https://www.sudo.ws/license.html for
      complete details.
 
-Sudo 1.8.20                     March 20, 2017                     Sudo 1.8.20
+Sudo 1.8.20                     March 21, 2017                     Sudo 1.8.20
index 49dbd77ad555720e493610b5ab20568084387ff6..a5bd2fe3b065c36ebce26b098942d697ef3f77c0 100644 (file)
@@ -21,7 +21,7 @@
 .\" Agency (DARPA) and Air Force Research Laboratory, Air Force
 .\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
 .\"
-.TH "SUDOERS" "5" "March 20, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.TH "SUDOERS" "5" "March 21, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -3331,8 +3331,17 @@ This setting is only supported by version 1.8.20 or higher.
 iolog_group
 The group name to look up when setting the group ID on new I/O log
 files and directories.
-By default, I/O log files and directories inherit the group ID of
-the parent directory.
+If
+\fIiolog_group\fR
+is not set,
+the primary group ID of the user specified by
+\fIiolog_user\fR
+is used.
+If neither
+\fIiolog_group\fR
+nor
+\fIiolog_user\fR
+are set, I/O log files and directories are created with group ID 0.
 .sp
 This setting is only supported by version 1.8.19 or higher.
 .TP 18n
@@ -3350,10 +3359,13 @@ Defaults to 0600 (read and write by user only).
 This setting is only supported by version 1.8.19 or higher.
 .TP 18n
 iolog_user
-The user name to look up when setting the user ID on new I/O log
-files and directories.
-By default, I/O log files and directories are owned by the superuser
-(user ID 0).
+The user name to look up when setting the user and group IDs on new
+I/O log files and directories.
+If
+\fIiolog_group\fR
+is set, it will be used instead of the user's primary group ID.
+By default, I/O log files and directories are created with user and
+group ID 0.
 .sp
 This setting is only supported by version 1.8.19 or higher.
 .TP 18n
index e872b7c6aa72bc5d6aaae0b9cf0d75eb5e0fbd45..44b05b0b5df25efb024bb4d08792c7c69c43c85b 100644 (file)
@@ -19,7 +19,7 @@
 .\" Agency (DARPA) and Air Force Research Laboratory, Air Force
 .\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
 .\"
-.Dd March 20, 2017
+.Dd March 21, 2017
 .Dt SUDOERS @mansectform@
 .Os Sudo @PACKAGE_VERSION@
 .Sh NAME
@@ -3124,8 +3124,17 @@ This setting is only supported by version 1.8.20 or higher.
 .It iolog_group
 The group name to look up when setting the group ID on new I/O log
 files and directories.
-By default, I/O log files and directories inherit the group ID of
-the parent directory.
+If
+.Em iolog_group
+is not set, 
+the primary group ID of the user specified by
+.Em iolog_user
+is used.
+If neither
+.Em iolog_group
+nor
+.Em iolog_user
+are set, I/O log files and directories are created with group ID 0.
 .Pp
 This setting is only supported by version 1.8.19 or higher.
 .It iolog_mode
@@ -3141,10 +3150,13 @@ Defaults to 0600 (read and write by user only).
 .Pp
 This setting is only supported by version 1.8.19 or higher.
 .It iolog_user
-The user name to look up when setting the user ID on new I/O log
-files and directories.
-By default, I/O log files and directories are owned by the superuser
-(user ID 0).
+The user name to look up when setting the user and group IDs on new
+I/O log files and directories.
+If
+.Em iolog_group
+is set, it will be used instead of the user's primary group ID.
+By default, I/O log files and directories are created with user and
+group ID 0.
 .Pp
 This setting is only supported by version 1.8.19 or higher.
 .It lecture_status_dir
index 058659d51e3f7126a31dd541cf0bd4d4253799ab..2c09f95884f0d4bc141cdb45bf85e66f346c0d3f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2009-2017 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -71,10 +71,13 @@ static bool iolog_compress = false;
 static bool warned = false;
 static struct timeval last_time;
 static unsigned int sessid_max = SESSID_MAX;
-static uid_t iolog_uid = ROOT_UID;
-static gid_t iolog_gid = (gid_t)-1;
 static mode_t iolog_filemode = S_IRUSR|S_IWUSR;
 static mode_t iolog_dirmode = S_IRWXU;
+static bool iolog_gid_set;
+
+/* shared with set_perms.c */
+uid_t iolog_uid = ROOT_UID;
+gid_t iolog_gid = ROOT_GID;
 
 /* sudoers_io is declared at the end of this file. */
 extern __dso_public struct io_plugin sudoers_io;
@@ -83,18 +86,27 @@ extern __dso_public struct io_plugin sudoers_io;
  * Create directory and any parent directories as needed.
  */
 static bool
-io_mkdirs(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediate)
+io_mkdirs(char *path)
 {
     struct stat sb;
-    uid_t parent_uid;
-    gid_t parent_gid;
-    mode_t parent_mode;
-    bool ok = true;
+    bool ok, uid_changed = false;
     debug_decl(io_mkdirs, SUDOERS_DEBUG_UTIL)
 
-    if (stat(path, &sb) == 0) {
+    ok = stat(path, &sb) == 0;
+    if (!ok) {
+       /* Try again as the I/O log owner (for NFS). */
+       if (set_perms(PERM_IOLOG)) {
+           ok = stat(path, &sb) == 0;
+           if (!restore_perms())
+               ok = false;
+       }
+    }
+    if (ok) {
        if (S_ISDIR(sb.st_mode)) {
-           parent_gid = sb.st_gid;
+           if ((sb.st_mode & ALLPERMS) != iolog_dirmode)
+               ignore_result(chmod(path, iolog_dirmode));
+           if (sb.st_uid != iolog_uid || sb.st_gid != iolog_gid)
+               ignore_result(chown(path, iolog_uid, iolog_gid));
        } else {
            sudo_warnx(U_("%s exists but is not a directory (0%o)"),
                path, (unsigned int) sb.st_mode);
@@ -103,35 +115,28 @@ io_mkdirs(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediate
        goto done;
     }
 
-    /* Parent directory ownership and mode. */
-    if (!set_intermediate) {
-       parent_mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
-       parent_uid = ROOT_UID;
-       parent_gid = (gid_t)-1;
-    } else {
-       parent_mode = mode;
-       parent_uid = uid;
-       parent_gid = *gidp;
+    ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
+    if (!ok) {
+       /* Try again as the I/O log owner (for NFS). */
+       uid_changed = set_perms(PERM_IOLOG);
+       ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
     }
-
-    ok = sudo_mkdir_parents(path, parent_uid, &parent_gid, parent_mode, false);
     if (ok) {
-       /* Use group ID if specified, else parent gid. */
-       gid_t gid = *gidp != (gid_t)-1 ? *gidp : parent_gid;
-
        /* Create final path component. */
        sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
-           "mkdir %s, mode 0%o", path, (unsigned int) mode);
-       if (mkdir(path, mode) != 0 && errno != EEXIST) {
-           sudo_warnx(U_("unable to mkdir %s"), path);
+           "mkdir %s, mode 0%o", path, (unsigned int) iolog_dirmode);
+       if (mkdir(path, iolog_dirmode) != 0 && errno != EEXIST) {
+           sudo_warn(U_("unable to mkdir %s"), path);
            ok = false;
        } else {
-           ignore_result(chown(path, uid, gid));
+           ignore_result(chown(path, iolog_uid, iolog_gid));
        }
     }
+    if (uid_changed) {
+       if (!restore_perms())
+           ok = false;
+    }
 done:
-    if (ok && *gidp == (gid_t)-1)
-       *gidp = parent_gid;
     debug_return_bool(ok);
 }
 
@@ -139,30 +144,19 @@ done:
  * Create temporary directory and any parent directories as needed.
  */
 static bool
-io_mkdtemp(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediate)
+io_mkdtemp(char *path)
 {
-    uid_t parent_uid;
-    gid_t parent_gid;
-    mode_t parent_mode;
     bool ok = true;
+    bool uid_changed = false;
     debug_decl(io_mkdtemp, SUDOERS_DEBUG_UTIL)
 
-    /* Parent directory ownership and mode. */
-    if (!set_intermediate) {
-       parent_mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
-       parent_uid = ROOT_UID;
-       parent_gid = (gid_t)-1;
-    } else {
-       parent_mode = mode;
-       parent_uid = uid;
-       parent_gid = *gidp;
+    ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
+    if (!ok) {
+       /* Try again as the I/O log owner (for NFS). */
+       uid_changed = set_perms(PERM_IOLOG);
+       ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
     }
-
-    ok = sudo_mkdir_parents(path, parent_uid, &parent_gid, parent_mode, false);
     if (ok) {
-       /* Use group ID if specified, else parent gid. */
-       gid_t gid = *gidp != (gid_t)-1 ? *gidp : parent_gid;
-
        /* Create final path component. */
        sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
            "mkdtemp %s", path);
@@ -170,12 +164,18 @@ io_mkdtemp(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediat
            sudo_warn(U_("unable to mkdir %s"), path);
            ok = false;
        } else {
-           ignore_result(chown(path, uid, gid));
+           ignore_result(chown(path, iolog_uid, iolog_gid));
+           if (chmod(path, iolog_dirmode) != 0) {
+               sudo_warn(U_("unable to change mode of %s to 0%o"),
+                   path, iolog_dirmode);
+           }
        }
     }
 
-    if (ok && *gidp == (gid_t)-1)
-       *gidp = parent_gid;
+    if (uid_changed) {
+       if (!restore_perms())
+           ok = false;
+    }
     debug_return_bool(ok);
 }
 
@@ -217,25 +217,31 @@ cb_maxseq(const union sudo_defs_val *sd_un)
 }
 
 /*
- * Look up I/O log user ID from user name.
+ * Look up I/O log user ID from user name.  Sets iolog_uid.
+ * Also sets iolog_gid if iolog_group not specified.
  */
 static bool
-iolog_set_uid(const char *name)
+iolog_set_user(const char *name)
 {
     struct passwd *pw;
-    debug_decl(iolog_set_uid, SUDOERS_DEBUG_UTIL)
+    debug_decl(iolog_set_user, SUDOERS_DEBUG_UTIL)
 
     if (name != NULL) {
        pw = sudo_getpwnam(name);
        if (pw != NULL) {
            iolog_uid = pw->pw_uid;
+           if (!iolog_gid_set)
+               iolog_gid = pw->pw_gid;
            sudo_pw_delref(pw);
        } else {
            log_warningx(SLOG_SEND_MAIL,
                N_("unknown user: %s"), name);
        }
     } else {
+       /* Reset to default. */
        iolog_uid = ROOT_UID;
+       if (!iolog_gid_set)
+           iolog_gid = ROOT_GID;
     }
 
     debug_return_bool(true);
@@ -247,29 +253,33 @@ iolog_set_uid(const char *name)
 bool
 cb_iolog_user(const union sudo_defs_val *sd_un)
 {
-    return iolog_set_uid(sd_un->str);
+    return iolog_set_user(sd_un->str);
 }
 
 /*
  * Look up I/O log group ID from group name.
+ * Sets iolog_gid.
  */
 static bool
-iolog_set_gid(const char *name)
+iolog_set_group(const char *name)
 {
     struct group *gr;
-    debug_decl(iolog_set_gid, SUDOERS_DEBUG_UTIL)
+    debug_decl(iolog_set_group, SUDOERS_DEBUG_UTIL)
 
     if (name != NULL) {
        gr = sudo_getgrnam(name);
        if (gr != NULL) {
            iolog_gid = gr->gr_gid;
+           iolog_gid_set = true;
            sudo_gr_delref(gr);
        } else {
            log_warningx(SLOG_SEND_MAIL,
                N_("unknown group: %s"), name);
        }
     } else {
-       iolog_gid = (mode_t)-1;
+       /* Reset to default. */
+       iolog_gid = ROOT_GID;
+       iolog_gid_set = false;
     }
 
     debug_return_bool(true);
@@ -281,7 +291,7 @@ iolog_set_gid(const char *name)
 bool
 cb_iolog_group(const union sudo_defs_val *sd_un)
 {
-    return iolog_set_gid(sd_un->str);
+    return iolog_set_group(sd_un->str);
 }
 
 /*
@@ -338,9 +348,8 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
 
     /*
      * Create I/O log directory if it doesn't already exist.
-     * Avoid modifying iolog_gid at this point.
      */
-    if (!io_mkdirs(iolog_dir, iolog_uid, &gid, iolog_dirmode, false))
+    if (!io_mkdirs(iolog_dir))
        goto done;
 
     /*
@@ -353,12 +362,18 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
        goto done;
     }
     fd = open(pathbuf, O_RDWR|O_CREAT, iolog_filemode);
+    if (fd == -1) {
+       /* Try again as the I/O log owner (for NFS). */
+       set_perms(PERM_IOLOG);
+       fd = open(pathbuf, O_RDWR|O_CREAT, iolog_filemode);
+       restore_perms();
+    }
     if (fd == -1) {
        log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), pathbuf);
        goto done;
     }
     sudo_lock_file(fd, SUDO_LOCK);
-    ignore_result(fchown(fd, iolog_uid, gid));
+    ignore_result(fchown(fd, iolog_uid, iolog_gid));
 
     /*
      * If there is no seq file in iolog_dir and a fallback dir was
@@ -372,7 +387,14 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
        len = snprintf(fallback, sizeof(fallback), "%s/seq",
            iolog_dir_fallback);
        if (len > 0 && (size_t)len < sizeof(fallback)) {
-           int fd2 = open(fallback, O_RDWR|O_CREAT, iolog_filemode);
+           int fd2;
+           fd2 = open(fallback, O_RDWR|O_CREAT, iolog_filemode);
+           if (fd == -1) {
+               /* Try again as the I/O log owner (for NFS). */
+               set_perms(PERM_IOLOG);
+               fd2 = open(fallback, O_RDWR|O_CREAT, iolog_filemode);
+               restore_perms();
+           }
            if (fd2 != -1) {
                ignore_result(fchown(fd2, iolog_uid, gid));
                nread = read(fd2, buf, sizeof(buf) - 1);
@@ -470,9 +492,9 @@ mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize)
      * Sets iolog_gid (if it is not already set) as a side effect.
      */
     if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0)
-       ok = io_mkdtemp(pathbuf, iolog_uid, &iolog_gid, iolog_dirmode, true);
+       ok = io_mkdtemp(pathbuf);
     else
-       ok = io_mkdirs(pathbuf, iolog_uid, &iolog_gid, iolog_dirmode, true);
+       ok = io_mkdirs(pathbuf);
 
     debug_return_size_t(ok ? len : (size_t)-1);
 }
@@ -492,6 +514,12 @@ open_io_fd(char *pathbuf, size_t len, struct io_log_file *iol, bool docompress)
     strlcat(pathbuf, iol->suffix, PATH_MAX);
     if (iol->enabled) {
        int fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, iolog_filemode);
+       if (fd == -1) {
+           /* Try again as the I/O log owner (for NFS). */
+           set_perms(PERM_IOLOG);
+           fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, iolog_filemode);
+           restore_perms();
+       }
        if (fd != -1) {
            ignore_result(fchown(fd, iolog_uid, iolog_gid));
            (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -630,11 +658,11 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
                continue;
            }
            if (strncmp(*cur, "iolog_group=", sizeof("iolog_group=") - 1) == 0) {
-               iolog_set_gid(*cur + sizeof("iolog_group=") - 1);
+               iolog_set_group(*cur + sizeof("iolog_group=") - 1);
                continue;
            }
            if (strncmp(*cur, "iolog_user=", sizeof("iolog_user=") - 1) == 0) {
-               iolog_set_uid(*cur + sizeof("iolog_user=") - 1);
+               iolog_set_user(*cur + sizeof("iolog_user=") - 1);
                continue;
            }
            break;
@@ -725,6 +753,12 @@ write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
     pathbuf[len] = '\0';
     strlcat(pathbuf, "/log", PATH_MAX);
     fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, iolog_filemode);
+    if (fd == -1) {
+       /* Try again as the I/O log owner (for NFS). */
+       set_perms(PERM_IOLOG);
+       fd = open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, iolog_filemode);
+       restore_perms();
+    }
     if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
        log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf);
        debug_return_bool(false);
index 40d8881911ef98edda3d6321cd143ff378eeec53..335a35704fb121bd2f6c5a91e13f8cffe3fdcbe1 100644 (file)
  * Note that path is modified but is restored before it returns.
  */
 bool
-sudo_mkdir_parents(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool quiet)
+sudo_mkdir_parents(char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet)
 {
     struct stat sb;
-    gid_t parent_gid = 0;
     char *slash = path;
     debug_decl(sudo_mkdir_parents, SUDOERS_DEBUG_UTIL)
 
-    /* If no gid specified, inherit from parent dir. */
-    if (*gidp != (gid_t)-1)
-       parent_gid = *gidp;
-    else if (stat("/", &sb) == 0)
-       parent_gid = sb.st_gid;
-
     /* Create parent directories as needed. */
     while ((slash = strchr(slash + 1, '/')) != NULL) {
        *slash = '\0';
        sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
            "mkdir %s, mode 0%o, uid %d, gid %d", path, (unsigned int)mode,
-           (int)uid, (int)parent_gid);
+           (int)uid, (int)gid);
        if (mkdir(path, mode) == 0) {
-           ignore_result(chown(path, uid, parent_gid));
+           if (uid != (uid_t)-1 && gid != (gid_t)-1)
+               ignore_result(chown(path, uid, gid));
        } else {
            if (errno != EEXIST) {
                if (!quiet)
@@ -77,16 +71,10 @@ sudo_mkdir_parents(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool quiet)
                        path, (unsigned int) sb.st_mode);
                goto bad;
            }
-           /* Inherit gid of parent dir for ownership. */
-           if (*gidp == (gid_t)-1)
-               parent_gid = sb.st_gid;
        }
        *slash = '/';
     }
 
-    /* Return parent gid if none was specified by caller. */
-    if (*gidp == (gid_t)-1)
-       *gidp = parent_gid;
     debug_return_bool(true);
 bad:
     /* We must restore the path before we return. */
index 9e6f86fcd6799edce44210ca47627389d928228d..000f33f2c3dad7e9f91574bf58d191046a2a2f97 100644 (file)
@@ -347,6 +347,37 @@ set_perms(int perm)
            goto bad;
        }
        break;
+
+    case PERM_IOLOG:
+       state->gidlist = ostate->gidlist;
+       sudo_gidlist_addref(state->gidlist);
+       state->rgid = ostate->rgid;
+       state->egid = iolog_gid;
+       state->sgid = ostate->sgid;
+       state->ruid = ROOT_UID;
+       state->euid = iolog_uid;
+       state->suid = ROOT_UID;
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: gid: "
+           "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+           (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+           (int)state->rgid, (int)state->egid, (int)state->sgid);
+       if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
+           snprintf(errbuf, sizeof(errbuf),
+               "PERM_IOLOG: setresgid(%d, %d, %d)",
+               (int)ID(rgid), (int)ID(egid), (int)ID(sgid));
+           goto bad;
+       }
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: uid: "
+           "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+           (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+           (int)state->ruid, (int)state->euid, (int)state->suid);
+       if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
+           snprintf(errbuf, sizeof(errbuf),
+               "PERM_IOLOG: setresuid(%d, %d, %d)",
+               (int)ID(ruid), (int)ID(euid), (int)ID(suid));
+           goto bad;
+       }
+       break;
     }
 
     perm_stack_depth++;
@@ -390,12 +421,6 @@ restore_perms(void)
            goto bad;
        }
     }
-    if (setresuid(OID(ruid), OID(euid), OID(suid))) {
-       sudo_warn("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
-           (int)state->ruid, (int)state->euid, (int)state->suid,
-           (int)OID(ruid), (int)OID(euid), (int)OID(suid));
-       goto bad;
-    }
     if (setresgid(OID(rgid), OID(egid), OID(sgid))) {
        sudo_warn("setresgid() [%d, %d, %d] -> [%d, %d, %d]",
            (int)state->rgid, (int)state->egid, (int)state->sgid,
@@ -408,6 +433,12 @@ restore_perms(void)
            goto bad;
        }
     }
+    if (setresuid(OID(ruid), OID(euid), OID(suid))) {
+       sudo_warn("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
+           (int)state->ruid, (int)state->euid, (int)state->suid,
+           (int)OID(ruid), (int)OID(euid), (int)OID(suid));
+       goto bad;
+    }
     sudo_gidlist_delref(state->gidlist);
     debug_return_bool(true);
 
@@ -686,6 +717,46 @@ set_perms(int perm)
            }
        }
        break;
+
+    case PERM_IOLOG:
+       state->gidlist = ostate->gidlist;
+       sudo_gidlist_addref(state->gidlist);
+       state->rgid = ostate->rgid;
+       state->egid = iolog_gid;
+       state->sgid = ostate->sgid;
+       state->ruid = ROOT_UID;
+       state->euid = iolog_uid;
+       state->suid = ROOT_UID;
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: gid: "
+           "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+           (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+           (int)state->rgid, (int)state->egid, (int)state->sgid);
+       if (GID_CHANGED && setgidx(ID_EFFECTIVE, iolog_gid)) {
+           snprintf(errbuf, sizeof(errbuf),
+               "PERM_IOLOG: setgidx(ID_EFFECTIVE, %d)", (int)iolog_gid);
+           goto bad;
+       }
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: uid: "
+           "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+           (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+           (int)state->ruid, (int)state->euid, (int)state->suid);
+       if (UID_CHANGED) {
+           if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) {
+               if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
+                   snprintf(errbuf, sizeof(errbuf),
+                       "PERM_IOLOG: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+                       ROOT_UID);
+                   goto bad;
+               }
+           }
+           if (setuidx(ID_EFFECTIVE, timestamp_uid)) {
+               snprintf(errbuf, sizeof(errbuf),
+                   "PERM_IOLOG: setuidx(ID_EFFECTIVE, %d)",
+                   (int)timestamp_uid);
+               goto bad;
+           }
+       }
+       break;
     }
 
     perm_stack_depth++;
@@ -1045,6 +1116,31 @@ set_perms(int perm)
            goto bad;
        }
        break;
+
+    case PERM_IOLOG:
+       state->gidlist = ostate->gidlist;
+       sudo_gidlist_addref(state->gidlist);
+       state->rgid = ostate->rgid;
+       state->egid = iolog_gid;
+       state->ruid = ROOT_UID;
+       state->euid = iolog_uid;
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: gid: "
+           "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+           (int)ostate->egid, (int)state->rgid, (int)state->egid);
+       if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
+           snprintf(errbuf, sizeof(errbuf), "PERM_IOLOG: setregid(%d, %d)",
+               (int)ID(rgid), (int)ID(egid));
+           goto bad;
+       }
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: uid: "
+           "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+           (int)ostate->euid, (int)state->ruid, (int)state->euid);
+       if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
+           snprintf(errbuf, sizeof(errbuf), "PERM_IOLOG: setreuid(%d, %d)",
+               (int)ID(ruid), (int)ID(euid));
+           goto bad;
+       }
+       break;
     }
 
     perm_stack_depth++;
@@ -1341,6 +1437,31 @@ set_perms(int perm)
            goto bad;
        }
        break;
+
+    case PERM_IOLOG:
+       state->gidlist = ostate->gidlist;
+       sudo_gidlist_addref(state->gidlist);
+       state->rgid = ostate->rgid;
+       state->egid = iolog_gid;
+       state->ruid = ROOT_UID;
+       state->euid = iolog_uid;
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: gid: "
+           "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+           (int)ostate->egid, (int)state->rgid, (int)state->egid);
+       if (GID_CHANGED && setegid(iolog_gid)) {
+           snprintf(errbuf, sizeof(errbuf),
+               "PERM_IOLOG: setegid(%d)", (int)iolog_gid);
+           goto bad;
+       }
+       sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: uid: "
+           "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+           (int)ostate->euid, (int)state->ruid, (int)state->euid);
+       if (seteuid(timestamp_uid)) {
+           snprintf(errbuf, sizeof(errbuf),
+               "PERM_IOLOG: seteuid(%d)", (int)timestamp_uid);
+           goto bad;
+       }
+       break;
     }
 
     perm_stack_depth++;
@@ -1499,6 +1620,7 @@ set_perms(int perm)
     case PERM_SUDOERS:
     case PERM_RUNAS:
     case PERM_TIMESTAMP:
+    case PERM_IOLOG:
        /* Unsupported since we can't set euid. */
        state->ruid = ostate->ruid;
        state->rgid = ostate->rgid;
index 745619e83a477a00d7ce21490d03969797e23e72..37b69a561da5ca1dcab7373b1707d88ecbd6c548 100644 (file)
@@ -170,13 +170,14 @@ struct sudo_user {
 /*
  * Used with set_perms()
  */
-#define PERM_INITIAL             0x00
-#define PERM_ROOT                0x01
-#define PERM_USER                0x02
-#define PERM_FULL_USER           0x03
-#define PERM_SUDOERS             0x04
-#define PERM_RUNAS               0x05
-#define PERM_TIMESTAMP           0x06
+#define PERM_INITIAL           0x00
+#define PERM_ROOT              0x01
+#define PERM_USER              0x02
+#define PERM_FULL_USER         0x03
+#define PERM_SUDOERS           0x04
+#define PERM_RUNAS             0x05
+#define PERM_TIMESTAMP         0x06
+#define PERM_IOLOG             0x07
 
 /*
  * Shortcuts for sudo_user contents.
@@ -333,6 +334,8 @@ bool cb_maxseq(const union sudo_defs_val *sd_un);
 bool cb_iolog_user(const union sudo_defs_val *sd_un);
 bool cb_iolog_group(const union sudo_defs_val *sd_un);
 bool cb_iolog_mode(const union sudo_defs_val *sd_un);
+extern uid_t iolog_uid;
+extern gid_t iolog_gid;
 
 /* iolog_path.c */
 char *expand_iolog_path(const char *prefix, const char *dir, const char *file,
@@ -394,7 +397,7 @@ char *resolve_editor(const char *ed, size_t edlen, int nfiles, char **files,
     int *argc_out, char ***argv_out, char * const *whitelist);
 
 /* mkdir_parents.c */
-bool sudo_mkdir_parents(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool quiet);
+bool sudo_mkdir_parents(char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet);
 
 /* gc.c */
 enum sudoers_gc_types {
index 8343c1a5cac8780186e031d475baccc99c8b4d51..f3c7bf58e3253fb13f27ef0ea3a7acbb54858724 100644 (file)
@@ -156,7 +156,7 @@ ts_mkdirs(char *path, uid_t owner, gid_t group, mode_t mode,
     bool ret;
     debug_decl(ts_mkdirs, SUDOERS_DEBUG_AUTH)
 
-    ret = sudo_mkdir_parents(path, owner, &group, parent_mode, quiet); 
+    ret = sudo_mkdir_parents(path, owner, group, parent_mode, quiet); 
     if (ret) {
        /* Create final path component. */
        sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,