SHA256
1
0
forked from pool/shadow

- Update to 4.6:

* Newgrp: avoid unnecessary lookups
  * Make language less binary
  * Add error when turning off man switch
  * Spelling fixes
  * Make userdel work with -R
  * newgidmap: enforce setgroups=deny if self-mapping a group
  * Norwegian bokmål translation
  * pwck: prevent crash by not passing O_CREAT
  * WITH_TCB fixes from Mandriva
  * Fix pwconv and grpconv entry skips
  * Fix -- slurping in su
  * add --prefix option
- Remove CVE-2018-7169.patch: upstreamed
- Remove shadow-4.1.5.1-pam_group.patch: upstreamed
- Update userdel-script.patch: change due to prefix
- Update useradd-mkdirs.patch: change due to prefix
  Additionally changed in that patch:
  * Test for strdup() failure
  * Directory to 0755 instead 0777
- Add shadow-4.6.0-fix-usermod-prefix-crash.patch:
  Fixes crash in usermod when called with --prefix.
  See https://github.com/shadow-maint/shadow/issues/110

OBS-URL: https://build.opensuse.org/package/show/Base:System/shadow?expand=0&rev=52
This commit is contained in:
Michael Vetter 2018-05-16 14:26:18 +00:00 committed by Git OBS Bridge
parent 59e14c5bc5
commit 60780ba34c
11 changed files with 186 additions and 293 deletions

View File

@ -1,180 +0,0 @@
From fb28c99b8a66ff2605c5cb96abc0a4d975f92de0 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asarai@suse.de>
Date: Thu, 15 Feb 2018 23:49:40 +1100
Subject: [PATCH] newgidmap: enforce setgroups=deny if self-mapping a group
This is necessary to match the kernel-side policy of "self-mapping in a
user namespace is fine, but you cannot drop groups" -- a policy that was
created in order to stop user namespaces from allowing trivial privilege
escalation by dropping supplementary groups that were "blacklisted" from
certain paths.
This is the simplest fix for the underlying issue, and effectively makes
it so that unless a user has a valid mapping set in /etc/subgid (which
only administrators can modify) -- and they are currently trying to use
that mapping -- then /proc/$pid/setgroups will be set to deny. This
workaround is only partial, because ideally it should be possible to set
an "allow_setgroups" or "deny_setgroups" flag in /etc/subgid to allow
administrators to further restrict newgidmap(1).
We also don't write anything in the "allow" case because "allow" is the
default, and users may have already written "deny" even if they
technically are allowed to use setgroups. And we don't write anything if
the setgroups policy is already "deny".
Ref: https://bugs.launchpad.net/ubuntu/+source/shadow/+bug/1729357
Fixes: CVE-2018-7169
Reported-by: Craig Furman <craig.furman89@gmail.com>
Signed-off-by: Aleksa Sarai <asarai@suse.de>
---
src/newgidmap.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 80 insertions(+), 9 deletions(-)
diff --git a/src/newgidmap.c b/src/newgidmap.c
index b1e33513..59a2e75c 100644
--- a/src/newgidmap.c
+++ b/src/newgidmap.c
@@ -46,32 +46,37 @@
*/
const char *Prog;
-static bool verify_range(struct passwd *pw, struct map_range *range)
+
+static bool verify_range(struct passwd *pw, struct map_range *range, bool *allow_setgroups)
{
/* An empty range is invalid */
if (range->count == 0)
return false;
- /* Test /etc/subgid */
- if (have_sub_gids(pw->pw_name, range->lower, range->count))
+ /* Test /etc/subgid. If the mapping is valid then we allow setgroups. */
+ if (have_sub_gids(pw->pw_name, range->lower, range->count)) {
+ *allow_setgroups = true;
return true;
+ }
- /* Allow a process to map its own gid */
- if ((range->count == 1) && (pw->pw_gid == range->lower))
+ /* Allow a process to map its own gid. */
+ if ((range->count == 1) && (pw->pw_gid == range->lower)) {
+ /* noop -- if setgroups is enabled already we won't disable it. */
return true;
+ }
return false;
}
static void verify_ranges(struct passwd *pw, int ranges,
- struct map_range *mappings)
+ struct map_range *mappings, bool *allow_setgroups)
{
struct map_range *mapping;
int idx;
mapping = mappings;
for (idx = 0; idx < ranges; idx++, mapping++) {
- if (!verify_range(pw, mapping)) {
+ if (!verify_range(pw, mapping, allow_setgroups)) {
fprintf(stderr, _( "%s: gid range [%lu-%lu) -> [%lu-%lu) not allowed\n"),
Prog,
mapping->upper,
@@ -89,6 +94,70 @@ static void usage(void)
exit(EXIT_FAILURE);
}
+void write_setgroups(int proc_dir_fd, bool allow_setgroups)
+{
+ int setgroups_fd;
+ char *policy, policy_buffer[4096];
+
+ /*
+ * Default is "deny", and any "allow" will out-rank a "deny". We don't
+ * forcefully write an "allow" here because the process we are writing
+ * mappings for may have already set themselves to "deny" (and "allow"
+ * is the default anyway). So allow_setgroups == true is a noop.
+ */
+ policy = "deny\n";
+ if (allow_setgroups)
+ return;
+
+ setgroups_fd = openat(proc_dir_fd, "setgroups", O_RDWR|O_CLOEXEC);
+ if (setgroups_fd < 0) {
+ /*
+ * If it's an ENOENT then we are on too old a kernel for the setgroups
+ * code to exist. Emit a warning and bail on this.
+ */
+ if (ENOENT == errno) {
+ fprintf(stderr, _("%s: kernel doesn't support setgroups restrictions\n"), Prog);
+ goto out;
+ }
+ fprintf(stderr, _("%s: couldn't open process setgroups: %s\n"),
+ Prog,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Check whether the policy is already what we want. /proc/self/setgroups
+ * is write-once, so attempting to write after it's already written to will
+ * fail.
+ */
+ if (read(setgroups_fd, policy_buffer, sizeof(policy_buffer)) < 0) {
+ fprintf(stderr, _("%s: failed to read setgroups: %s\n"),
+ Prog,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if (!strncmp(policy_buffer, policy, strlen(policy)))
+ goto out;
+
+ /* Write the policy. */
+ if (lseek(setgroups_fd, 0, SEEK_SET) < 0) {
+ fprintf(stderr, _("%s: failed to seek setgroups: %s\n"),
+ Prog,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if (dprintf(setgroups_fd, "%s", policy) < 0) {
+ fprintf(stderr, _("%s: failed to setgroups %s policy: %s\n"),
+ Prog,
+ policy,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+out:
+ close(setgroups_fd);
+}
+
/*
* newgidmap - Set the gid_map for the specified process
*/
@@ -103,6 +172,7 @@ int main(int argc, char **argv)
struct stat st;
struct passwd *pw;
int written;
+ bool allow_setgroups = false;
Prog = Basename (argv[0]);
@@ -145,7 +215,7 @@ int main(int argc, char **argv)
(unsigned long) getuid ()));
return EXIT_FAILURE;
}
-
+
/* Get the effective uid and effective gid of the target process */
if (fstat(proc_dir_fd, &st) < 0) {
fprintf(stderr, _("%s: Could not stat directory for target %u\n"),
@@ -177,8 +247,9 @@ int main(int argc, char **argv)
if (!mappings)
usage();
- verify_ranges(pw, ranges, mappings);
+ verify_ranges(pw, ranges, mappings, &allow_setgroups);
+ write_setgroups(proc_dir_fd, allow_setgroups);
write_mapping(proc_dir_fd, ranges, mappings, "gid_map");
sub_gid_close();

View File

@ -1,50 +0,0 @@
Date: Thu Apr 6 16:04:17 CEST 2017
Bug: bnc#1031643
Upstream: https://github.com/shadow-maint/shadow/pull/74
dynamically added users via pam_group are not listed in groups
databases but are still valid.
Index: shadow-4.1.5.1/src/newgrp.c
===================================================================
--- shadow-4.1.5.1.orig/src/newgrp.c
+++ shadow-4.1.5.1/src/newgrp.c
@@ -372,6 +372,7 @@ int main (int argc, char **argv)
{
bool initflag = false;
int i;
+ bool is_member = false;
bool cflag = false;
int err = 0;
gid_t gid;
@@ -610,6 +611,18 @@ int main (int argc, char **argv)
goto failure;
}
+#ifdef HAVE_SETGROUPS
+ /* when using pam_group, she will not be listed in the groups
+ * database. However getgroups() will return the group. So
+ * if she is listed there already it is ok to grant membership.
+ */
+ for (i = 0; i < ngroups; i++) {
+ if (grp->gr_gid == grouplist[i]) {
+ is_member = true;
+ break;
+ }
+ }
+#endif /* HAVE_SETGROUPS */
/*
* For splitted groups (due to limitations of NIS), check all
* groups of the same GID like the requested group for
@@ -638,7 +651,9 @@ int main (int argc, char **argv)
/*
* Check if the user is allowed to access this group.
*/
- check_perms (grp, pwd, group);
+ if (!is_member) {
+ check_perms (grp, pwd, group);
+ }
/*
* all successful validations pass through this point. The group id

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fc8c858381ad577a5c25ff5beb6ee60a34f8719c73e4e7c61e74188b4e54b741
size 1626704

View File

@ -1,11 +0,0 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAABCgAGBQJZHKsTAAoJEOn+6gaoXj+dIT8H/2UNtVDHrtXk4Z6d5RGZPKvs
eBOiK03Mk89jtD1YFBLu4kk2tkFP86lylfRdnQisqAovLwsOF36gAoZUK/0X71x3
AcyYUEno2Go8Sf+Ol432+Tj6FdBG3n/yXzroh7PmxG58PBMV1PBm95RLZ/uVp7hz
WLtrd8FL4QC4fe0rt00BOb2bW6Bbcx+XiXI6QCvLwtQi2bnJt2DcIYxiqZPni4YT
FUAClxYB/hHbjChg3EMFn8JZkaf8SLMuiyLGYKNbqLaXu88/El80QYATSuCNH14y
ywMYEXxKHIiaJ+KnNfjUb3fXHlWyaeWDltguIr0EMfIjF5VrtN4fKxsJy8ZJtMc=
=G9lG
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,86 @@
Bug: https://github.com/shadow-maint/shadow/issues/110
Containing following two fixes.
From 73a876a05612c278da747faeaeea40c3b8d34a53 Mon Sep 17 00:00:00 2001
From: fariouche <fariouche@yahoo.fr>
Date: Tue, 8 May 2018 21:17:46 -0500
Subject: [PATCH 1/2] Fix usermod crash
Return newly allocated pointers when the caller will free them.
Closes #110
---
libmisc/prefix_flag.c | 2 +-
src/usermod.c | 10 ++++++----
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/libmisc/prefix_flag.c b/libmisc/prefix_flag.c
index 6581235e..8ceffd26 100644
--- a/libmisc/prefix_flag.c
+++ b/libmisc/prefix_flag.c
@@ -333,7 +333,7 @@ extern struct group *prefix_getgr_nam_gid(const char *grname)
&& (gid == (gid_t)gid)) {
return prefix_getgrgid ((gid_t) gid);
}
- return prefix_getgrnam (grname);
+ return __gr_dup(prefix_getgrnam (grname));
}
else
return getgr_nam_gid(grname);
diff --git a/src/usermod.c b/src/usermod.c
index e571426f..7355ad31 100644
--- a/src/usermod.c
+++ b/src/usermod.c
@@ -1251,11 +1251,13 @@ static void process_flags (int argc, char **argv)
prefix_user_home = xmalloc(len);
wlen = snprintf(prefix_user_home, len, "%s/%s", prefix, user_home);
assert (wlen == (int) len -1);
+ if (user_newhome) {
+ len = strlen(prefix) + strlen(user_newhome) + 2;
+ prefix_user_newhome = xmalloc(len);
+ wlen = snprintf(prefix_user_newhome, len, "%s/%s", prefix, user_newhome);
+ assert (wlen == (int) len -1);
+ }
- len = strlen(prefix) + strlen(user_newhome) + 2;
- prefix_user_newhome = xmalloc(len);
- wlen = snprintf(prefix_user_newhome, len, "%s/%s", prefix, user_newhome);
- assert (wlen == (int) len -1);
}
else {
prefix_user_home = user_home;
From 48dcf7852e51b9d8e7926737cc7f7823978b7d7d Mon Sep 17 00:00:00 2001
From: Serge Hallyn <shallyn@cisco.com>
Date: Tue, 8 May 2018 21:37:55 -0500
Subject: [PATCH 2/2] usermod: prevent a segv
in the case where prefix does not exist.
Signed-off-by: Serge Hallyn <shallyn@cisco.com>
---
libmisc/prefix_flag.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libmisc/prefix_flag.c b/libmisc/prefix_flag.c
index 8ceffd26..96b11faa 100644
--- a/libmisc/prefix_flag.c
+++ b/libmisc/prefix_flag.c
@@ -319,6 +319,7 @@ extern struct group *prefix_getgr_nam_gid(const char *grname)
{
long long int gid;
char *endptr;
+ struct group *g;
if (NULL == grname) {
return NULL;
@@ -333,7 +334,8 @@ extern struct group *prefix_getgr_nam_gid(const char *grname)
&& (gid == (gid_t)gid)) {
return prefix_getgrgid ((gid_t) gid);
}
- return __gr_dup(prefix_getgrnam (grname));
+ g = prefix_getgrnam (grname);
+ return g ? __gr_dup(g) : NULL;
}
else
return getgr_nam_gid(grname);

3
shadow-4.6.tar.xz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0998c8d84242a231ab0acb7f8613927ff5bcff095f8aa6b79478893a03f05583
size 1678100

11
shadow-4.6.tar.xz.asc Normal file
View File

@ -0,0 +1,11 @@
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEE8dCNt3gYW/eEAC3/6f7qBqheP50FAlrncOkACgkQ6f7qBqhe
P52UGAf/eOnoIYIZ52y72iMxeNfQMTMjYTZd1YrtjlK0RQKquK7FrCOg91MvOF2B
hLVKu2OU7mzuPTMSAraAxjXLkrM0E3vFjMtu1fHBGlGTMspAfik/9Gu9qoevAKXy
BRqgN5m5HMfoGPeEjzILzaGq8bnPKIOfJ0iAYVkjjIa73Vn20uTmNgNZIRqHqwfw
5GUFHn6cjQXFcQ3ngywgwQD7/h/65w8dBbGysF551sAqzPJRbneQL9Wtklcqi1ub
55NyF0ifT67RqMh+EyxhuhXP1Hi57PTEAeqaFMFxnPlQPb+8pQ8nszWBmI+vUN8D
FmhwCtSTnmKlj0jeAqevmkijJhGPQQ==
=fk/F
-----END PGP SIGNATURE-----

View File

@ -1,3 +1,30 @@
-------------------------------------------------------------------
Mon May 14 12:45:42 UTC 2018 - mvetter@suse.com
- Update to 4.6:
* Newgrp: avoid unnecessary lookups
* Make language less binary
* Add error when turning off man switch
* Spelling fixes
* Make userdel work with -R
* newgidmap: enforce setgroups=deny if self-mapping a group
* Norwegian bokmål translation
* pwck: prevent crash by not passing O_CREAT
* WITH_TCB fixes from Mandriva
* Fix pwconv and grpconv entry skips
* Fix -- slurping in su
* add --prefix option
- Remove CVE-2018-7169.patch: upstreamed
- Remove shadow-4.1.5.1-pam_group.patch: upstreamed
- Update userdel-script.patch: change due to prefix
- Update useradd-mkdirs.patch: change due to prefix
Additionally changed in that patch:
* Test for strdup() failure
* Directory to 0755 instead 0777
- Add shadow-4.6.0-fix-usermod-prefix-crash.patch:
Fixes crash in usermod when called with --prefix.
See https://github.com/shadow-maint/shadow/issues/110
-------------------------------------------------------------------
Thu Feb 22 15:10:45 UTC 2018 - fvogt@suse.com

View File

@ -17,7 +17,7 @@
Name: shadow
Version: 4.5
Version: 4.6
Release: 0
Summary: Utilities to Manage User and Group Accounts
License: BSD-3-Clause AND GPL-2.0+
@ -43,9 +43,8 @@ Patch6: shadow-4.1.5.1-userdel-helpfix.patch
Patch7: shadow-4.1.5.1-logmsg.patch
Patch10: encryption_method_nis.patch
Patch11: useradd-mkdirs.patch
Patch18: shadow-4.1.5.1-pam_group.patch
Patch12: shadow-4.6.0-fix-usermod-prefix-crash.patch
Patch20: disable_new_audit_function.patch
Patch21: CVE-2018-7169.patch
BuildRequires: audit-devel > 2.3
BuildRequires: libacl-devel
BuildRequires: libattr-devel
@ -68,7 +67,7 @@ group accounts.
%prep
%setup -q -a 1
%patch0
%patch1
%patch1 -p1
%patch2
%patch3
%patch4
@ -76,11 +75,10 @@ group accounts.
%patch6
%patch7
%patch10
%patch11
%patch18 -p1
%patch11 -p1
%patch12 -p1
%if 0%{?suse_version} < 1330
%patch20 -p1
%patch21 -p1
%endif
iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8

View File

@ -1,30 +1,37 @@
Index: src/useradd.c
===================================================================
--- src/useradd.c.orig
+++ src/useradd.c
@@ -1943,6 +1943,13 @@ static void usr_update (void)
https://github.com/shadow-maint/shadow/pull/112
useradd-mkdirs.patch adapted to two comments in https://github.com/shadow-maint/shadow/pull/2
* check for stdup failure
* create dirs with 0755 instead of 0777
diff -urEbwB shadow-4.6/src/useradd.c shadow-4.6.new-useradd-mkdirs/src/useradd.c
--- shadow-4.6/src/useradd.c 2018-04-29 18:42:37.000000000 +0200
+++ shadow-4.6.new-useradd-mkdirs/src/useradd.c 2018-05-15 17:11:03.706371270 +0200
@@ -2018,6 +2018,19 @@
static void create_home (void)
{
if (access (user_home, F_OK) != 0) {
+ char path[strlen (user_home) + 2];
if (access (prefix_user_home, F_OK) != 0) {
+ char path[strlen (prefix_user_home) + 2];
+ char *bhome, *cp;
+
+ path[0] = '\0';
+ bhome = strdup (user_home);
+ bhome = strdup (prefix_user_home);
+ if (!bhome) {
+ fprintf (stderr,
+ _("%s: error while duplicating string %s\n"),
+ Prog, user_home);
+ fail_exit (E_HOMEDIR);
+ }
+ ++bhome;
+
#ifdef WITH_SELINUX
if (set_selinux_file_context (user_home) != 0) {
if (set_selinux_file_context (prefix_user_home) != 0) {
fprintf (stderr,
@@ -1951,19 +1958,42 @@ static void create_home (void)
@@ -2026,11 +2039,20 @@
fail_exit (E_HOMEDIR);
}
#endif
- /* XXX - create missing parent directories. --marekm */
- if (mkdir (user_home, 0) != 0) {
- fprintf (stderr,
- _("%s: cannot create directory %s\n"),
- Prog, user_home);
- if (mkdir (prefix_user_home, 0) != 0) {
+
+ /* Check for every part of the path, if the directory
+ exists. If not, create it with permissions 755 and
@ -36,36 +43,31 @@ Index: src/useradd.c
+ strcat (path, cp);
+ if (access (path, F_OK) != 0) {
+ if (mkdir (path, 0) != 0) {
+ fprintf (stderr,
+ _("%s: cannot create directory %s\n"),
fprintf (stderr,
_("%s: cannot create directory %s\n"),
- Prog, prefix_user_home);
+ Prog, path);
#ifdef WITH_AUDIT
- audit_logger (AUDIT_ADD_USER, Prog,
- "adding home directory",
- user_name, (unsigned int) user_id,
- SHADOW_AUDIT_FAILURE);
+ audit_logger (AUDIT_ADD_USER, Prog,
+ "adding home directory",
+ user_name, (unsigned int) user_id,
+ SHADOW_AUDIT_FAILURE);
audit_logger (AUDIT_ADD_USER, Prog,
"adding home directory",
@@ -2039,6 +2061,20 @@
#endif
- fail_exit (E_HOMEDIR);
+ fail_exit (E_HOMEDIR);
+ }
fail_exit (E_HOMEDIR);
}
+ if (chown (path, 0, 0) < 0) {
+ fprintf (stderr,
+ _("%s: warning: chown on `%s' failed: %m\n"),
+ Prog, path);
+ }
+ if (chmod (path, 0777) < 0) {
+ if (chmod (path, 0755) < 0) {
+ fprintf (stderr,
+ _("%s: warning: chmod on `%s' failed: %m\n"),
+ Prog, path);
+ }
+ }
+ cp = strtok (NULL, "/");
}
+ }
+
chown (user_home, user_id, user_gid);
chmod (user_home,
(void) chown (prefix_user_home, user_id, user_gid);
chmod (prefix_user_home,
0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));

View File

@ -1,6 +1,16 @@
--- src/userdel.c
+++ src/userdel.c
@@ -762,13 +762,13 @@ static void update_user (void)
diff -urEbwB shadow-4.6/src/userdel.c shadow-4.6.new/src/userdel.c
--- shadow-4.6/src/userdel.c 2018-04-29 18:42:37.000000000 +0200
+++ shadow-4.6.new/src/userdel.c 2018-05-14 16:13:43.996280216 +0200
@@ -125,7 +125,7 @@
static void fail_exit (int);
static void open_files (void);
static void update_user (void);
-static void user_cancel (const char *);
+static void call_script (const char *, const char *);
#ifdef EXTRA_CHECK_HOME_DIR
static bool path_prefix (const char *, const char *);
@@ -767,13 +767,13 @@
* cron, at, or print jobs.
*/
@ -16,7 +26,7 @@
if (NULL == cmd) {
return;
}
@@ -1163,9 +1163,10 @@ int main (int argc, char **argv)
@@ -1213,9 +1213,10 @@
}
/*
@ -25,20 +35,20 @@
+ * Do the hard stuff - open the files, remove the user entries,
+ * remove the home directory, then close and update the files.
*/
+ call_script ("USERDEL_PRECMD", user_name);
+ call_script ("USERDEL_PRECMD", user_name);
open_files ();
update_user ();
update_groups ();
@@ -1268,7 +1269,7 @@ int main (int argc, char **argv)
* Cancel any crontabs or at jobs. Have to do this before we remove
@@ -1319,7 +1320,7 @@
* the entry from /etc/passwd.
*/
- user_cancel (user_name);
+ call_script ("USERDEL_CMD", user_name);
if(prefix[0] == '\0')
- user_cancel (user_name);
+ call_script ("USERDEL_CMD", user_name);
close_files ();
#ifdef WITH_TCB
@@ -1278,6 +1279,8 @@ int main (int argc, char **argv)
@@ -1329,6 +1330,9 @@
nscd_flush_cache ("passwd");
nscd_flush_cache ("group");
@ -47,4 +57,4 @@
+
return ((0 != errors) ? E_HOMEDIR : E_SUCCESS);
}
-