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:
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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. */
|
||||
|
@@ -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;
|
||||
|
@@ -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 {
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user