From 684831c59a4932ff05ebb22d6ee6f49d805742f82babc863a1b4bb1d744029ac Mon Sep 17 00:00:00 2001 From: Philipp Thomas Date: Mon, 7 May 2012 12:25:45 +0000 Subject: [PATCH] - 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 --- coreutils-id_show_real_groups.patch | 176 +++++++++++++++++++++++++++ coreutils-race_in_cp.patch | 178 ++++++++++++++++++++++++++++ coreutils.changes | 22 ++++ coreutils.spec | 6 + 4 files changed, 382 insertions(+) create mode 100644 coreutils-id_show_real_groups.patch create mode 100644 coreutils-race_in_cp.patch diff --git a/coreutils-id_show_real_groups.patch b/coreutils-id_show_real_groups.patch new file mode 100644 index 0000000..51e9598 --- /dev/null +++ b/coreutils-id_show_real_groups.patch @@ -0,0 +1,176 @@ +commit 032a549481444395558286b433296c97c09c721d +Author: Jim Meyering +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 . ++ ++. "${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 diff --git a/coreutils-race_in_cp.patch b/coreutils-race_in_cp.patch new file mode 100644 index 0000000..0e2824c --- /dev/null +++ b/coreutils-race_in_cp.patch @@ -0,0 +1,178 @@ +commit ee9e43460f366406edff96b5abfb3ff33587e062 +Author: Jim Meyering +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 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 . ++ ++. "${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 ++#include ++ ++#define __xstat __xstat_orig ++ ++#include ++#include ++ ++#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 diff --git a/coreutils.changes b/coreutils.changes index bbac744..5e7aa7d 100644 --- a/coreutils.changes +++ b/coreutils.changes @@ -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 diff --git a/coreutils.spec b/coreutils.spec index 8e9b1a2..d6befb4 100644 --- a/coreutils.spec +++ b/coreutils.spec @@ -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