- Two new upstream patches:

* id and groups, when invoked with no user name argument, would
    print the default group ID listed in the password database, and
    sometimes that ID would be neither real nor effective.  For
    example, when run set-GID, or in a session for which the default
    group has just been changed, the new group ID would be listed,
    even though it is not yet effective.
  * 'cp S D' is no longer subject to a race: if an existing D were
    removed between the initial stat and subsequent
    open-without-O_CREAT, cp would fail with a confusing diagnostic
    saying that the destination, D, was not found.  Now, in this
    unusual case, it retries the open (but with O_CREAT), and hence
    usually succeeds.  With NFS attribute caching, the condition was
    particularly easy to trigger, since there, the removal of D could
    precede the initial stat.  [This bug was present in "the
    beginning".] (bnc#760926).

OBS-URL: https://build.opensuse.org/package/show/Base:System/coreutils?expand=0&rev=152
This commit is contained in:
Philipp Thomas 2012-05-07 12:25:45 +00:00 committed by Git OBS Bridge
parent 47c879ecc6
commit 684831c59a
4 changed files with 382 additions and 0 deletions

View File

@ -0,0 +1,176 @@
commit 032a549481444395558286b433296c97c09c721d
Author: Jim Meyering <meyering@redhat.com>
Date: Fri Apr 27 13:28:32 2012 +0200
id,groups: with no user name, print only real and/or effective IDs,
... i.e., don't use the getpw* functions.
Before this change, running groups or id with no user name argument
would include a group name or ID from /etc/passwd. Thus, under unusual
circumstances (default group is changed, but has not taken effect for a
given session), those programs could print a name or ID that is neither
real nor effective.
To demonstrate, run this:
echo 'for i in 1 2; do id -G; sleep 1.5; done' \
|su -s /bin/sh ftp - &
sleep 1; perl -pi -e 's/^(ftp:x:\d+):(\d+)/$1:9876/' /etc/passwd
Those id -G commands printed the following:
50
50 9876
With this change, they print this:
50
50
Similarly, running those programs set-GID could make them
print one ID too many.
* src/group-list.c (print_group_list): When username is NULL, pass
egid, not getpwuid(ruid)->pw_gid), to xgetgroups, per the API
requirements of xgetgroups callee, mgetgroups.
When not using the password database, don't call getpwuid.
* NEWS (Bug fixes): Mention it.
* tests/misc/id-setgid: New file.
* tests/Makefile.am (TESTS): Add it.
(root_tests): It's a root-only test, so add it here, too.
Originally reported by Brynnen Owen as http://bugs.gnu.org/7320.
Raised again by Marc Mengel in http://bugzilla.redhat.com/816708.
Index: NEWS
===================================================================
--- NEWS.orig 2012-03-26 14:06:43.000000000 +0200
+++ NEWS 2012-05-07 14:20:23.431517270 +0200
@@ -1,5 +1,15 @@
GNU coreutils NEWS -*- outline -*-
+** Bug fixes
+
+ id and groups, when invoked with no user name argument, would print
+ the default group ID listed in the password database, and sometimes
+ that ID would be neither real nor effective. For example, when run
+ set-GID, or in a session for which the default group has just been
+ changed, the new group ID would be listed, even though it is not
+ yet effective.
+
+
* Noteworthy changes in release 8.16 (2012-03-26) [stable]
** New features
Index: THANKS.in
===================================================================
--- THANKS.in.orig 2012-03-24 19:22:13.000000000 +0100
+++ THANKS.in 2012-05-07 14:19:38.953620833 +0200
@@ -98,6 +98,7 @@ Brian Silverman bsil
Brian Youmans 3diff@gnu.org
Britton Leo Kerin fsblk@aurora.uaf.edu
Bruce Robertson brucer@theodolite.dyndns.org
+Brynnen Owen owen@illinois.edu
Carl Johnson carlj@cjlinux.home.org
Carl Lowenstein cdl@mpl.UCSD.EDU
Carl Roth roth@urs.us
@@ -355,6 +356,7 @@ Manfred Hollstein manf
Марк Коренберг socketpair@gmail.com
Marc Boucher marc@mbsi.ca
Marc Haber mh+debian-bugs@zugschlus.de
+Marc Mengel mengel@fnal.gov
Marc Lehman schmorp@schmorp.de
Marc Olzheim marcolz@stack.nl
Marco Franzen Marco.Franzen@Thyron.com
Index: src/group-list.c
===================================================================
--- src/group-list.c.orig 2012-02-03 14:16:13.000000000 +0100
+++ src/group-list.c 2012-05-07 14:19:38.953620833 +0200
@@ -38,11 +38,14 @@ print_group_list (const char *username,
bool use_names)
{
bool ok = true;
- struct passwd *pwd;
+ struct passwd *pwd = NULL;
- pwd = getpwuid (ruid);
- if (pwd == NULL)
- ok = false;
+ if (username)
+ {
+ pwd = getpwuid (ruid);
+ if (pwd == NULL)
+ ok = false;
+ }
if (!print_group (rgid, use_names))
ok = false;
@@ -58,8 +61,7 @@ print_group_list (const char *username,
gid_t *groups;
int i;
- int n_groups = xgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
- &groups);
+ int n_groups = xgetgroups (username, (pwd ? pwd->pw_gid : egid), &groups);
if (n_groups < 0)
{
if (username)
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am.orig 2012-05-07 14:19:38.807624454 +0200
+++ tests/Makefile.am 2012-05-07 14:19:38.953620833 +0200
@@ -36,6 +36,7 @@ root_tests = \
ls/nameless-uid \
misc/chcon \
misc/chroot-credentials \
+ misc/id-setgid \
misc/selinux \
misc/truncate-owned-by-other \
mkdir/writable-under-readonly \
@@ -197,6 +198,7 @@ TESTS = \
misc/head-pos \
misc/id-context \
misc/id-groups \
+ misc/id-setgid \
misc/md5sum \
misc/md5sum-bsd \
misc/md5sum-newline \
Index: tests/misc/id-setgid
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tests/misc/id-setgid 2012-05-07 14:19:38.953620833 +0200
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Verify that id -G prints the right group when run set-GID.
+
+# Copyright (C) 2012 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+print_ver_ id
+require_root_
+
+g=$(id -u $NON_ROOT_USERNAME) || framework_failure_
+
+# Construct a different group number.
+gp1=$(expr $g + 1)
+
+echo $gp1 > exp || framework_failure_
+
+setuidgid -g $gp1 $NON_ROOT_USERNAME env PATH="$PATH" id -G > out || fail=1
+compare exp out || fail=1
+# With coreutils-8.16 and earlier, id -G would print both: $gp1 $g
+
+Exit $fail

178
coreutils-race_in_cp.patch Normal file
View File

@ -0,0 +1,178 @@
commit ee9e43460f366406edff96b5abfb3ff33587e062
Author: Jim Meyering <meyering@redhat.com>
Date: Fri May 4 16:42:31 2012 +0200
cp: handle a race condition more sensibly
* src/copy.c (copy_reg): In a narrow race (stat sees dest, yet
open-without-O_CREAT fails with ENOENT), retry the open with O_CREAT.
* tests/cp/nfs-removal-race: New file.
* tests/Makefile.am (TESTS): Add it.
* NEWS (Bug fixes): Mention it.
Reported by Philipp Thomas and Neil F. Brown in
http://bugs.gnu.org/11100
Index: NEWS
===================================================================
--- NEWS.orig 2012-05-07 14:20:52.079810454 +0200
+++ NEWS 2012-05-07 14:21:35.566738140 +0200
@@ -9,6 +9,14 @@ GNU coreutils NEWS
changed, the new group ID would be listed, even though it is not
yet effective.
+ 'cp S D' is no longer subject to a race: if an existing D were removed
+ between the initial stat and subsequent open-without-O_CREAT, cp would
+ fail with a confusing diagnostic saying that the destination, D, was not
+ found. Now, in this unusual case, it retries the open (but with O_CREAT),
+ and hence usually succeeds. With NFS attribute caching, the condition
+ was particularly easy to trigger, since there, the removal of D could
+ precede the initial stat. [This bug was present in "the beginning".]
+
* Noteworthy changes in release 8.16 (2012-03-26) [stable]
Index: THANKS.in
===================================================================
--- THANKS.in.orig 2012-05-07 14:20:52.079810454 +0200
+++ THANKS.in 2012-05-07 14:20:52.087810257 +0200
@@ -439,7 +439,7 @@ Minh Tran-Le tran
Morten Welinder terra@diku.dk
Nao Nishijima nao.nishijima.xt@hitachi.com
Neal H Walfield neal@cs.uml.edu
-Neil Brown neilb@cse.unsw.edu.au
+Neil F. Brown neilb@suse.de
Nelson H. F. Beebe beebe@math.utah.edu
Nick Estes debian@nickstoys.com
Nick Graham nick.d.graham@gmail.com
@@ -489,6 +489,7 @@ Phil Richards phil
Philippe De Muyter phdm@macqel.be
Philippe Schnoebelen Philippe.Schnoebelen@imag.fr
Phillip Jones mouse@datastacks.com
+Philipp Thomas pth@suse.de
Piergiorgio Sartor sartor@sony.de
Pieter Bowman bowman@math.utah.edu
Piotr Gackiewicz gacek@intertele.pl
Index: src/copy.c
===================================================================
--- src/copy.c.orig 2012-03-24 21:26:51.000000000 +0100
+++ src/copy.c 2012-05-07 14:20:52.087810257 +0200
@@ -889,6 +889,8 @@ copy_reg (char const *src_name, char con
if (*new_dst)
{
+ open_with_O_CREAT:;
+
int open_flags = O_WRONLY | O_CREAT | O_BINARY;
dest_desc = open (dst_name, open_flags | O_EXCL,
dst_mode & ~omitted_permissions);
@@ -939,6 +941,23 @@ copy_reg (char const *src_name, char con
if (dest_desc < 0)
{
+ /* If we've just failed due to ENOENT for an ostensibly preexisting
+ destination (*new_dst was 0), that's a bit of a contradiction/race:
+ the prior stat/lstat said the file existed (*new_dst was 0), yet
+ the subsequent open-existing-file failed with ENOENT. With NFS,
+ the race window is wider still, since its meta-data caching tends
+ to make the stat succeed for a just-removed remote file, while the
+ more-definitive initial open call will fail with ENOENT. When this
+ situation arises, we attempt to open again, but this time with
+ O_CREAT. Do this only when not in move-mode, since when handling
+ a cross-device move, we must never open an existing destination. */
+ if (dest_errno == ENOENT && ! *new_dst && ! x->move_mode)
+ {
+ *new_dst = 1;
+ goto open_with_O_CREAT;
+ }
+
+ /* Otherwise, it's an error. */
error (0, dest_errno, _("cannot create regular file %s"),
quote (dst_name));
return_val = false;
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am.orig 2012-05-07 14:20:52.080810429 +0200
+++ tests/Makefile.am 2012-05-07 14:20:52.087810257 +0200
@@ -347,6 +347,7 @@ TESTS = \
cp/link-no-deref \
cp/link-preserve \
cp/link-symlink \
+ cp/nfs-removal-race \
cp/no-deref-link1 \
cp/no-deref-link2 \
cp/no-deref-link3 \
Index: tests/cp/nfs-removal-race
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tests/cp/nfs-removal-race 2012-05-07 14:20:52.087810257 +0200
@@ -0,0 +1,70 @@
+#!/bin/sh
+# Running cp S D on an NFS client while another client has just removed D
+# would lead (w/coreutils-8.16 and earlier) to cp's initial stat call
+# seeing (via stale NFS cache) that D exists, so that cp would then call
+# open without the O_CREAT flag. Yet, the open must actually consult
+# the server, which confesses that D has been deleted, thus causing the
+# open call to fail with ENOENT.
+#
+# This test simulates that situation by intercepting stat for a nonexistent
+# destination, D, and making the stat fill in the result struct for another
+# file and return 0.
+#
+# This test is skipped on systems that lack LD_PRELOAD support; that's fine.
+# Similarly, on a system that lacks <dlfcn.h> or __xstat, skipping it is fine.
+
+# Copyright (C) 2012 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+print_ver_ cp
+
+# Replace each stat call with a call to this wrapper.
+cat > k.c <<'EOF' || framework_failure_
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <dlfcn.h>
+
+#define __xstat __xstat_orig
+
+#include <sys/stat.h>
+#include <stddef.h>
+
+#undef __xstat
+
+int
+__xstat (int ver, const char *path, struct stat *st)
+{
+ static int (*real_stat)(int ver, const char *path, struct stat *st) = NULL;
+ if (!real_stat)
+ real_stat = dlsym (RTLD_NEXT, "__xstat");
+ /* When asked to stat nonexistent "d",
+ return results suggesting it exists. */
+ return real_stat (ver, *path == 'd' && path[1] == 0 ? "d2" : path, st);
+}
+EOF
+
+# Then compile/link it:
+$CC -shared -fPIC -O2 k.c -o k.so \
+ || framework_failure_ 'failed to compile with -shared -fPIC'
+
+touch d2 || framework_failure_
+echo xyz > src || framework_failure_
+
+# Finally, run the test:
+LD_PRELOAD=./k.so cp src d || fail=1
+
+compare src d || fail=1
+Exit $fail

View File

@ -1,3 +1,25 @@
-------------------------------------------------------------------
Mon May 7 14:22:29 CEST 2012 - pth@suse.de
- Two new upstream patches:
* id and groups, when invoked with no user name argument, would
print the default group ID listed in the password database, and
sometimes that ID would be neither real nor effective. For
example, when run set-GID, or in a session for which the default
group has just been changed, the new group ID would be listed,
even though it is not yet effective.
* 'cp S D' is no longer subject to a race: if an existing D were
removed between the initial stat and subsequent
open-without-O_CREAT, cp would fail with a confusing diagnostic
saying that the destination, D, was not found. Now, in this
unusual case, it retries the open (but with O_CREAT), and hence
usually succeeds. With NFS attribute caching, the condition was
particularly easy to trigger, since there, the removal of D could
precede the initial stat. [This bug was present in "the
beginning".] (bnc#760926).
-------------------------------------------------------------------
Fri Apr 27 12:38:23 CEST 2012 - pth@suse.de

View File

@ -75,6 +75,10 @@ Patch33: coreutils-8.9-singlethreaded-sort.patch
Patch34: coreutils-acl-nofollow.patch
Patch36: coreutils-basename_documentation.patch
Patch37: coreutils-bnc#697897-setsid.patch
#Upstream patch will be included with 8.17
Patch38: coreutils-id_show_real_groups.patch
#Upstream patch, needs to be removed for 8.17
Patch39: coreutils-race_in_cp.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
# this will create a cycle, broken up randomly - coreutils is just too core to have other
# prerequires
@ -118,6 +122,8 @@ uname unexpand uniq unlink uptime users vdir wc who whoami yes
%patch34
%patch36
%patch37
%patch38
%patch39
xz -dc %{S:4} >po/de.po