[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Port to Solaris 10's rules for whether programs can chown files
From: |
Paul Eggert |
Subject: |
Port to Solaris 10's rules for whether programs can chown files |
Date: |
Mon, 30 May 2005 23:28:54 -0700 |
User-agent: |
Gnus/5.1006 (Gnus v5.10.6) Emacs/21.4 (gnu/linux) |
Inspired by the recent change to support Solaris 10's privilege
functions with respect to unlinking directories, I noticed another use
of geteuid. In this case it was used to decide whether programs
should be able to chown files. I installed this patch to handle the
case where a non-root process has that privilege, or a root process
lacks it. This shouldn't change behavior of coreutils except on
Solaris-10-like systems. (And I like to think that this change cleans
up the code a little, even on GNU systems.)
2005-05-30 Paul Eggert <address@hidden>
Port to Solaris 10's rules for whether programs can chown files.
* m4/jm-macros.m4 (gl_CHECK_ALL_HEADERS): Check for priv.h.
* src/copy.c [HAVE_PRIV_H]: Include <priv.h>.
(DO_CHOWN): Remove. Replaced by chown_failure_ok. All callers
changed.
(copy_internal): If chown failed, don't worry about what happened
to the mode bits; they can't have changed.
(chown_privileges, chown_failure_ok): New functions.
* src/copy.h: Add copyright notice.
(struct cp_options): Remove myeuid member. Add chown_privileges
member.
(chown_privileges, chown_failure_ok): New function decls.
* src/cp.c (re_protect): Remove unnecessary call to geteuid.
Use chown_failure_ok rather than our own code.
* src/cp.c (cp_options_init): Use chown_privileges rather than geteuid.
* src/install.c (cp_option_init): Likewise.
* src/mv.c (cp_option_init): Likewise.
Index: m4/jm-macros.m4
===================================================================
RCS file: /fetish/cu/m4/jm-macros.m4,v
retrieving revision 1.216
diff -p -u -r1.216 jm-macros.m4
--- m4/jm-macros.m4 18 May 2005 19:31:00 -0000 1.216
+++ m4/jm-macros.m4 31 May 2005 06:08:15 -0000
@@ -1,4 +1,4 @@
-#serial 87 -*- autoconf -*-
+#serial 88 -*- autoconf -*-
dnl Misc type-related macros for coreutils.
@@ -189,6 +189,7 @@ AC_DEFUN([gl_CHECK_ALL_HEADERS],
mnttab.h \
netdb.h \
paths.h \
+ priv.h \
stdlib.h \
stdint.h \
string.h \
Index: src/copy.c
===================================================================
RCS file: /fetish/cu/src/copy.c,v
retrieving revision 1.182
diff -p -u -r1.182 copy.c
--- src/copy.c 14 May 2005 07:58:36 -0000 1.182
+++ src/copy.c 31 May 2005 06:08:16 -0000
@@ -25,6 +25,9 @@
#if HAVE_HURD_H
# include <hurd.h>
#endif
+#if HAVE_PRIV_H
+# include <priv.h>
+#endif
#include "system.h"
#include "backupfile.h"
@@ -47,13 +50,6 @@
#include "xreadlink.h"
#include "yesno.h"
-#define DO_CHOWN(Chown, File, New_uid, New_gid)
\
- (Chown (File, New_uid, New_gid) \
- /* If non-root uses -p, it's ok if we can't preserve ownership. \
- But root probably wants to know, e.g. if NFS disallows it, \
- or if the target system doesn't support file ownership. */ \
- && ((errno != EPERM && errno != EINVAL) || x->myeuid == 0))
-
#define SAME_OWNER(A, B) ((A).st_uid == (B).st_uid)
#define SAME_GROUP(A, B) ((A).st_gid == (B).st_gid)
#define SAME_OWNER_AND_GROUP(A, B) (SAME_OWNER (A, B) && SAME_GROUP (A, B))
@@ -848,7 +844,7 @@ copy_internal (const char *src_path, con
bool backup_succeeded = false;
bool delayed_ok;
bool copied_as_regular = false;
- bool ran_chown = false;
+ bool chown_succeeded = false;
bool preserve_metadata;
if (x->move_mode && rename_succeeded)
@@ -1530,7 +1526,8 @@ copy_internal (const char *src_path, con
/* Preserve the owner and group of the just-`copied'
symbolic link, if possible. */
# if HAVE_LCHOWN
- if (DO_CHOWN (lchown, dst_path, src_sb.st_uid, src_sb.st_gid))
+ if (lchown (dst_path, src_sb.st_uid, src_sb.st_gid) != 0
+ && ! chown_failure_ok (x))
{
error (0, errno, _("failed to preserve ownership for %s"),
dst_path);
@@ -1590,8 +1587,9 @@ copy_internal (const char *src_path, con
if (x->preserve_ownership
&& (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb)))
{
- ran_chown = true;
- if (DO_CHOWN (chown, dst_path, src_sb.st_uid, src_sb.st_gid))
+ if (chown (dst_path, src_sb.st_uid, src_sb.st_gid) == 0)
+ chown_succeeded = true;
+ else if (! chown_failure_ok (x))
{
error (0, errno, _("failed to preserve ownership for %s"),
quote (dst_path));
@@ -1619,9 +1617,9 @@ copy_internal (const char *src_path, con
/* Permissions of newly-created regular files were set upon `open' in
copy_reg. But don't return early if there were any special bits and
- we had to run chown, because the chown must have reset those bits. */
+ chown succeeded, because the chown must have reset those bits. */
if ((new_dst && copied_as_regular)
- && !(ran_chown && (src_mode & ~S_IRWXUGO)))
+ && !(chown_succeeded && (src_mode & ~S_IRWXUGO)))
return delayed_ok;
if ((x->preserve_mode || new_dst)
@@ -1701,3 +1699,37 @@ copy (const char *src_path, const char *
return copy_internal (src_path, dst_path, nonexistent_dst, 0, NULL,
options, true, copy_into_self, rename_succeeded);
}
+
+/* Return true if this process has appropriate privileges to chown a
+ file whose owner is not the effective user ID. */
+
+bool
+chown_privileges (void)
+{
+#ifdef PRIV_FILE_CHOWN
+ bool result;
+ priv_set_t *pset = priv_allocset ();
+ if (!pset)
+ xalloc_die ();
+ result = (getppriv (PRIV_EFFECTIVE, pset) == 0
+ && priv_ismember (pset, PRIV_FILE_CHOWN));
+ priv_freeset (pset);
+ return result;
+#else
+ return (geteuid () == 0);
+#endif
+}
+
+/* Return true if it's OK for chown to fail, where errno is
+ the error number that chown failed with and X is the copying
+ option set. */
+
+bool
+chown_failure_ok (struct cp_options const *x)
+{
+ /* If non-root uses -p, it's ok if we can't preserve ownership.
+ But root probably wants to know, e.g. if NFS disallows it,
+ or if the target system doesn't support file ownership. */
+
+ return ((errno == EPERM || errno == EINVAL) && !x->chown_privileges);
+}
Index: src/copy.h
===================================================================
RCS file: /fetish/cu/src/copy.h,v
retrieving revision 1.31
diff -p -u -r1.31 copy.h
--- src/copy.h 26 Nov 2004 07:39:14 -0000 1.31
+++ src/copy.h 31 May 2005 06:08:16 -0000
@@ -1,3 +1,22 @@
+/* core functions for copying files and directories
+ Copyright (C) 89, 90, 91, 1995-2005 Free Software Foundation.
+
+ 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 2, 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, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Extracted from cp.c and librarified by Jim Meyering. */
+
#ifndef COPY_H
# define COPY_H
@@ -94,8 +113,9 @@ struct cp_options
If that fails, then resort to copying. */
bool move_mode;
- /* This process's effective user ID. */
- uid_t myeuid;
+ /* Whether this process has appropriate privileges to chown a file
+ whose owner is not the effective user ID. */
+ bool chown_privileges;
/* If true, when copying recursively, skip any subdirectories that are
on different file systems from the one we started on. */
@@ -195,14 +215,14 @@ int rpl_rename (const char *, const char
# define rename rpl_rename
# endif
-bool
-copy (const char *src_path, const char *dst_path,
- bool nonexistent_dst, const struct cp_options *options,
- bool *copy_into_self, bool *rename_succeeded);
-
-void
-dest_info_init (struct cp_options *);
-void
-src_info_init (struct cp_options *);
+bool copy (const char *src_path, const char *dst_path,
+ bool nonexistent_dst, const struct cp_options *options,
+ bool *copy_into_self, bool *rename_succeeded);
+
+void dest_info_init (struct cp_options *);
+void src_info_init (struct cp_options *);
+
+bool chown_privileges (void);
+bool chown_failure_ok (struct cp_options const *);
#endif
Index: src/cp.c
===================================================================
RCS file: /fetish/cu/src/cp.c,v
retrieving revision 1.209
diff -p -u -r1.209 cp.c
--- src/cp.c 30 May 2005 07:32:16 -0000 1.209
+++ src/cp.c 31 May 2005 06:08:16 -0000
@@ -281,7 +281,6 @@ re_protect (const char *const_dst_path,
struct dir_attr *p;
char *dst_path; /* A copy of CONST_DST_PATH we can change. */
char *src_path; /* The source name in `dst_path'. */
- uid_t myeuid = geteuid ();
ASSIGN_STRDUPA (dst_path, const_dst_path);
src_path = dst_path + src_offset;
@@ -322,11 +321,8 @@ re_protect (const char *const_dst_path,
if (x->preserve_ownership)
{
- /* If non-root uses -p, it's ok if we can't preserve ownership.
- But root probably wants to know, e.g. if NFS disallows it,
- or if the target system doesn't support file ownership. */
- if (chown (dst_path, src_sb.st_uid, src_sb.st_gid)
- && ((errno != EPERM && errno != EINVAL) || myeuid == 0))
+ if (chown (dst_path, src_sb.st_uid, src_sb.st_gid) != 0
+ && ! chown_failure_ok (x))
{
error (0, errno, _("failed to preserve ownership for %s"),
quote (dst_path));
@@ -683,7 +679,7 @@ cp_option_init (struct cp_options *x)
x->unlink_dest_after_failed_open = false;
x->hard_link = false;
x->interactive = I_UNSPECIFIED;
- x->myeuid = geteuid ();
+ x->chown_privileges = chown_privileges ();
x->move_mode = false;
x->one_file_system = false;
Index: src/install.c
===================================================================
RCS file: /fetish/cu/src/install.c,v
retrieving revision 1.177
diff -p -u -r1.177 install.c
--- src/install.c 30 May 2005 07:33:16 -0000 1.177
+++ src/install.c 31 May 2005 06:08:16 -0000
@@ -134,7 +134,7 @@ cp_option_init (struct cp_options *x)
x->hard_link = false;
x->interactive = I_UNSPECIFIED;
x->move_mode = false;
- x->myeuid = geteuid ();
+ x->chown_privileges = chown_privileges ();
x->one_file_system = false;
x->preserve_ownership = false;
x->preserve_links = false;
Index: src/mv.c
===================================================================
RCS file: /fetish/cu/src/mv.c,v
retrieving revision 1.165
diff -p -u -r1.165 mv.c
--- src/mv.c 14 May 2005 07:58:37 -0000 1.165
+++ src/mv.c 31 May 2005 06:08:16 -0000
@@ -121,7 +121,7 @@ cp_option_init (struct cp_options *x)
x->hard_link = false;
x->interactive = I_UNSPECIFIED;
x->move_mode = true;
- x->myeuid = geteuid ();
+ x->chown_privileges = chown_privileges ();
x->one_file_system = false;
x->preserve_ownership = true;
x->preserve_links = true;
- Port to Solaris 10's rules for whether programs can chown files,
Paul Eggert <=