Fixes to mkhomedir behavior
- Provide a switch to restore pre-CVE-2020-10737 behavior - Always set the home directory permissions according to HOME_MODE Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
parent
85c42911bb
commit
f77ee4f2bb
246
oddjob-override-mask-fix.patch
Normal file
246
oddjob-override-mask-fix.patch
Normal file
@ -0,0 +1,246 @@
|
||||
From 71b0389fbb31833d827f5f0fec18880c2f602753 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
Date: Thu, 19 May 2022 13:52:22 +0300
|
||||
Subject: [PATCH 1/2] mkhomedir: add support for pre-CVE-2020-10737 behavior
|
||||
|
||||
Pre-CVE-2020-10737 behavior was used to allow creating home directories
|
||||
on NFS mounts when non-Kerberos authentication method is in use. This is
|
||||
exactly the case where a race condition addressed by the CVE-2020-10737
|
||||
fix could have happened. However, there are legit use cases where this
|
||||
setup is needed.
|
||||
|
||||
Add '-f' option to mkhomedir helper to activate previous behavior. In
|
||||
order to enable it, a change to oddjobd-mkhomedir.conf configuration
|
||||
file is needed by explicitly adding '-f' option to the executable file
|
||||
definition.
|
||||
|
||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2050079
|
||||
|
||||
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
---
|
||||
src/mkhomedir.c | 16 +++++++++++++---
|
||||
src/oddjobd-mkhomedir.conf.5.in | 9 +++++++++
|
||||
2 files changed, 22 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/mkhomedir.c b/src/mkhomedir.c
|
||||
index be85959..ac813a9 100644
|
||||
--- a/src/mkhomedir.c
|
||||
+++ b/src/mkhomedir.c
|
||||
@@ -53,9 +53,11 @@ static const char *skel;
|
||||
static const char *skel_dir;
|
||||
static struct passwd *pwd;
|
||||
static mode_t override_umask;
|
||||
+static int owner_mkdir_first = 0;
|
||||
|
||||
#define FLAG_POPULATE (1 << 0)
|
||||
#define FLAG_QUIET (1 << 1)
|
||||
+#define FLAG_OWNER_MKDIR_FIRST (1 << 2)
|
||||
|
||||
/* Given the path of an item somewhere in the skeleton directory, create as
|
||||
* identical as possible a copy in the destination tree. */
|
||||
@@ -158,7 +160,7 @@ copy_single_item(const char *source, const struct stat *sb,
|
||||
* target user just yet to avoid potential race conditions
|
||||
* involving symlink attacks when we copy over the skeleton
|
||||
* tree. */
|
||||
- if (status->level == 0) {
|
||||
+ if (status->level == 0 && !owner_mkdir_first) {
|
||||
uid = 0;
|
||||
gid = 0;
|
||||
}
|
||||
@@ -222,6 +224,9 @@ mkhomedir(const char *user, int flags)
|
||||
pwd->pw_dir);
|
||||
return HANDLER_INVALID_INVOCATION;
|
||||
}
|
||||
+ if (flags & FLAG_OWNER_MKDIR_FIRST) {
|
||||
+ owner_mkdir_first = 1;
|
||||
+ }
|
||||
if ((lstat(pwd->pw_dir, &st) == -1) && (errno == ENOENT)) {
|
||||
/* Figure out which location we're using as a
|
||||
* template. */
|
||||
@@ -237,7 +242,7 @@ mkhomedir(const char *user, int flags)
|
||||
int res = nftw(get_skel_dir(), copy_single_item, 5,
|
||||
FTW_PHYS);
|
||||
/* only now give ownership to the target user */
|
||||
- if (res == 0) {
|
||||
+ if (res == 0 && !owner_mkdir_first) {
|
||||
res = chown(pwd->pw_dir, pwd->pw_uid, pwd->pw_gid);
|
||||
}
|
||||
|
||||
@@ -317,8 +322,11 @@ main(int argc, char **argv)
|
||||
umask(override_umask);
|
||||
skel_dir = "/etc/skel";
|
||||
|
||||
- while ((i = getopt(argc, argv, "nqs:u:")) != -1) {
|
||||
+ while ((i = getopt(argc, argv, "nqfs:u:")) != -1) {
|
||||
switch (i) {
|
||||
+ case 'f':
|
||||
+ flags |= FLAG_OWNER_MKDIR_FIRST;
|
||||
+ break;
|
||||
case 'n':
|
||||
flags &= ~FLAG_POPULATE;
|
||||
break;
|
||||
@@ -339,6 +347,8 @@ main(int argc, char **argv)
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Valid options:\n"
|
||||
+ "-f\tCreate home directory initially owned by user, "
|
||||
+ "not root. See man page for security issues.\n"
|
||||
"-n\tDo not populate home directories, "
|
||||
"just create them.\n"
|
||||
"-q\tDo not print messages when creating "
|
||||
diff --git a/src/oddjobd-mkhomedir.conf.5.in b/src/oddjobd-mkhomedir.conf.5.in
|
||||
index d7a2429..6e35ad5 100644
|
||||
--- a/src/oddjobd-mkhomedir.conf.5.in
|
||||
+++ b/src/oddjobd-mkhomedir.conf.5.in
|
||||
@@ -10,6 +10,15 @@ directory.
|
||||
|
||||
The mkhomedir helper itself accepts these options:
|
||||
.TP
|
||||
+-f
|
||||
+Restore behavior before CVE-2020-10737 was fixed: create the home directory
|
||||
+with user's ownership directly rather than create it as a root and only after
|
||||
+populating it change to the user's ownership. The former behavior is insecure
|
||||
+but may be used to allow creation of NFS-mounted home directories when
|
||||
+non-Kerberos authentication is in use. It is prone for a race condition that
|
||||
+could be exploited in the NFS-mounted home directories use case. To avoid
|
||||
+CVE-2020-10737, do not use \fB-f\fR option in production environments.
|
||||
+.TP
|
||||
-q
|
||||
Refrain from outputting the usual "Creating home directory..." message when it
|
||||
creates a home directory.
|
||||
--
|
||||
2.38.1
|
||||
|
||||
|
||||
From b800e25258353dbb1a88506123c21ac3298fd2d0 Mon Sep 17 00:00:00 2001
|
||||
From: Carlos Santos <casantos@redhat.com>
|
||||
Date: Tue, 18 Oct 2022 08:59:16 -0300
|
||||
Subject: [PATCH 2/2] Always set the home directory permissions according to
|
||||
HOME_MODE
|
||||
|
||||
Currently the home directory permissions are set by taking the /etc/skel
|
||||
mode and masking it with HOME_MODE:
|
||||
|
||||
override_umask = 0777 & ~get_umask(&configured_umask, "HOME_MODE");
|
||||
stat(skel, &sb); /* performed by nftw() */
|
||||
oddjob_selinux_mkdir(newpath, sb->st_mode & ~override_umask, uid, gid);
|
||||
|
||||
The problem is that when HOME_MODE is more permissive than /etc/skel,
|
||||
the masking will not produce the desired result, e.g.
|
||||
|
||||
skel_mode = 0755
|
||||
HOME_MODE = 0775
|
||||
override_umask = 0777 & ~HOME_MODE /* 0002 */
|
||||
mode = skel_mode & ~override_umask /* 0755 & 0775 = 0755 */
|
||||
|
||||
In order to fix the problem, always use 0777 & ~override_umask for the
|
||||
top home directory.
|
||||
|
||||
Signed-off-by: Carlos Santos <casantos@redhat.com>
|
||||
Fixes: https://pagure.io/oddjob/issue/17
|
||||
---
|
||||
src/mkhomedir.c | 45 +++++++++++++++++++++------------------------
|
||||
1 file changed, 21 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/mkhomedir.c b/src/mkhomedir.c
|
||||
index ac813a9..932918f 100644
|
||||
--- a/src/mkhomedir.c
|
||||
+++ b/src/mkhomedir.c
|
||||
@@ -67,6 +67,7 @@ copy_single_item(const char *source, const struct stat *sb,
|
||||
{
|
||||
uid_t uid = pwd->pw_uid;
|
||||
gid_t gid = pwd->pw_gid;
|
||||
+ mode_t mode = sb->st_mode & ~override_umask;
|
||||
int sfd, dfd, i, res;
|
||||
char target[PATH_MAX + 1], newpath[PATH_MAX + 1];
|
||||
unsigned char buf[BUFSIZ];
|
||||
@@ -112,8 +113,7 @@ copy_single_item(const char *source, const struct stat *sb,
|
||||
oddjob_set_selinux_file_creation_context(newpath,
|
||||
sb->st_mode |
|
||||
S_IFREG);
|
||||
- dfd = open(newpath, O_WRONLY | O_CREAT | O_EXCL,
|
||||
- sb->st_mode & ~override_umask);
|
||||
+ dfd = open(newpath, O_WRONLY | O_CREAT | O_EXCL, mode);
|
||||
if (dfd != -1) {
|
||||
while ((i = read(sfd, buf, sizeof(buf))) > 0) {
|
||||
retry_write(dfd, buf, i);
|
||||
@@ -156,20 +156,22 @@ copy_single_item(const char *source, const struct stat *sb,
|
||||
}
|
||||
return 0;
|
||||
case FTW_D:
|
||||
- /* It's the home directory itself. Don't give it to the
|
||||
- * target user just yet to avoid potential race conditions
|
||||
- * involving symlink attacks when we copy over the skeleton
|
||||
- * tree. */
|
||||
- if (status->level == 0 && !owner_mkdir_first) {
|
||||
- uid = 0;
|
||||
- gid = 0;
|
||||
- }
|
||||
-
|
||||
/* It's a directory. Make one with the same name and
|
||||
* permissions, but owned by the target user. */
|
||||
- res = oddjob_selinux_mkdir(newpath,
|
||||
- sb->st_mode & ~override_umask,
|
||||
- uid, gid);
|
||||
+ if (status->level == 0) {
|
||||
+ /* It's the home directory itself. Use the configured
|
||||
+ * (or overriden) mode, not the source mode & umask. */
|
||||
+ mode = 0777 & ~override_umask;
|
||||
+
|
||||
+ /* Don't give it to the target user just yet to avoid
|
||||
+ * potential race conditions involving symlink attacks
|
||||
+ * when we copy over the skeleton tree. */
|
||||
+ if (!owner_mkdir_first) {
|
||||
+ uid = 0;
|
||||
+ gid = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ res = oddjob_selinux_mkdir(newpath, mode, uid, gid);
|
||||
|
||||
/* on unexpected errors, or if the home directory itself
|
||||
* suddenly already exists, abort the copy operation. */
|
||||
@@ -248,12 +250,8 @@ mkhomedir(const char *user, int flags)
|
||||
|
||||
return res;
|
||||
} else {
|
||||
- if (stat(skel, &st) != 0) {
|
||||
- st.st_mode = S_IRWXU;
|
||||
- }
|
||||
if ((oddjob_selinux_mkdir(pwd->pw_dir,
|
||||
- st.st_mode &
|
||||
- ~override_umask,
|
||||
+ 0777 & ~override_umask,
|
||||
pwd->pw_uid,
|
||||
pwd->pw_gid) != 0) &&
|
||||
(errno != EEXIST)) {
|
||||
@@ -269,11 +267,11 @@ mkhomedir(const char *user, int flags)
|
||||
}
|
||||
|
||||
static mode_t
|
||||
-get_umask(int *configured, const char *variable)
|
||||
+get_umask(int *configured, const char *variable, mode_t default_value)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[BUFSIZ], *p, *end;
|
||||
- mode_t mask = umask(0777);
|
||||
+ mode_t mask = default_value;
|
||||
long tmp;
|
||||
size_t vlen = strlen(variable);
|
||||
|
||||
@@ -315,11 +313,10 @@ main(int argc, char **argv)
|
||||
|
||||
openlog(PACKAGE "-mkhomedir", LOG_PID, LOG_DAEMON);
|
||||
/* Unlike UMASK, HOME_MODE is the file mode, so needs to be reverted */
|
||||
- override_umask = 0777 & ~get_umask(&configured_umask, "HOME_MODE");
|
||||
+ override_umask = 0777 & ~get_umask(&configured_umask, "HOME_MODE", 0);
|
||||
if (configured_umask == 0) {
|
||||
- override_umask = get_umask(&configured_umask, "UMASK");
|
||||
+ override_umask = get_umask(&configured_umask, "UMASK", 022);
|
||||
}
|
||||
- umask(override_umask);
|
||||
skel_dir = "/etc/skel";
|
||||
|
||||
while ((i = getopt(argc, argv, "nqfs:u:")) != -1) {
|
||||
--
|
||||
2.38.1
|
||||
|
||||
@ -22,9 +22,10 @@
|
||||
|
||||
Name: oddjob
|
||||
Version: 0.34.7
|
||||
Release: 6%{?dist}
|
||||
Release: 7%{?dist}
|
||||
Source0: https://releases.pagure.org/oddjob/oddjob-%{version}.tar.gz
|
||||
Source1: https://releases.pagure.org/oddjob/oddjob-%{version}.tar.gz.asc
|
||||
Patch1: oddjob-override-mask-fix.patch
|
||||
Summary: A D-Bus service which runs odd jobs on behalf of client applications
|
||||
License: BSD
|
||||
BuildRequires: make
|
||||
@ -88,6 +89,7 @@ This package contains a trivial sample oddjob service.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%patch1 -p1
|
||||
|
||||
%build
|
||||
sample_flag=
|
||||
@ -247,6 +249,10 @@ fi
|
||||
exit 0
|
||||
|
||||
%changelog
|
||||
* Fri Dec 09 2022 Alexander Bokovoy <abokovoy@redhat.com> - 0.34.7-7
|
||||
- Provide a switch to restore pre-CVE-2020-10737 behavior
|
||||
- Always set the home directory permissions according to HOME_MODE
|
||||
|
||||
* Fri Jul 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.34.7-6
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user