Add PERM_IOLOG so we can create I/O log files on an NFS-mounted

filesystem where root is remapped to an unprivileged user.
This commit is contained in:
Todd C. Miller
2017-03-21 13:41:14 -06:00
parent cfb15106e3
commit 8d57491dc1
8 changed files with 294 additions and 120 deletions

View File

@@ -1626,9 +1626,11 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS
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 _i_o_l_o_g___g_r_o_u_p is
not set, the primary group ID of the user specified by
_i_o_l_o_g___u_s_e_r is used. If neither _i_o_l_o_g___g_r_o_u_p nor
_i_o_l_o_g___u_s_e_r 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 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS
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
_i_o_l_o_g___g_r_o_u_p 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 @@ DDIISSCCLLAAIIMMEERR
file distributed with ssuuddoo 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

View 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

View 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

View 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);

View File

@@ -38,27 +38,21 @@
* 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. */

View 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;

View File

@@ -177,6 +177,7 @@ struct sudo_user {
#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 {

View 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,