Hi Jim,

The following patches for coreutils and gnulib add a new Solaris 10
privilege module as previously suggested [1].

-- David

[1] http://lists.gnu.org/archive/html/bug-gnulib/2009-03/msg00123.html
From e67022be8d312fec0fa7619c65b9070171041c4c Mon Sep 17 00:00:00 2001
From: David Bartley <dtbar...@csclub.uwaterloo.ca>
Date: Wed, 29 Apr 2009 03:48:15 -0400
Subject: [PATCH] Drop PRIV_SYS_LINKDIR during mv/rm startup

---
 src/mv.c |    9 +++++++++
 src/rm.c |    9 +++++++++
 2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/src/mv.c b/src/mv.c
index 0613236..22bbb94 100644
--- a/src/mv.c
+++ b/src/mv.c
@@ -33,6 +33,10 @@
 #include "remove.h"
 #include "root-dev-ino.h"
 
+#if HAVE_GETPPRIV
+# include <priv.h>
+#endif
+
 /* The official name of this program (e.g., no `g' prefix).  */
 #define PROGRAM_NAME "mv"
 
@@ -354,6 +358,11 @@ main (int argc, char **argv)
 
   cp_option_init (&x);
 
+  /* Try to disable the ability to unlink a directory.  */
+#ifdef PRIV_SYS_LINKDIR
+  sol10priv_remove (PRIV_SYS_LINKDIR);
+#endif
+
   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
      we'll actually use backup_suffix_string.  */
   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
diff --git a/src/rm.c b/src/rm.c
index 8fecfdd..b15678a 100644
--- a/src/rm.c
+++ b/src/rm.c
@@ -56,6 +56,10 @@
 #include "root-dev-ino.h"
 #include "yesno.h"
 
+#if HAVE_GETPPRIV
+# include <priv.h>
+#endif
+
 /* The official name of this program (e.g., no `g' prefix).  */
 #define PROGRAM_NAME "rm"
 
@@ -241,6 +245,11 @@ main (int argc, char **argv)
 
   rm_option_init (&x);
 
+  /* Try to disable the ability to unlink a directory.  */
+#ifdef PRIV_SYS_LINKDIR
+  sol10priv_remove (PRIV_SYS_LINKDIR);
+#endif
+
   while ((c = getopt_long (argc, argv, "dfirvIR", long_opts, NULL)) != -1)
     {
       switch (c)
-- 
1.5.6.5

From 6820e25447dc8d7f1f3992e915eade95768a4e56 Mon Sep 17 00:00:00 2001
From: David Bartley <dtbar...@csclub.uwaterloo.ca>
Date: Wed, 29 Apr 2009 03:52:26 -0400
Subject: [PATCH] New module 'sol10priv'.

---
 ChangeLog         |    9 ++++
 lib/sol10priv.c   |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/sol10priv.h   |   26 ++++++++++++
 lib/unlinkdir.c   |   27 +++---------
 m4/sol10priv.m4   |   14 ++++++
 modules/sol10priv |   25 +++++++++++
 modules/unlinkdir |    3 +-
 7 files changed, 200 insertions(+), 21 deletions(-)
 create mode 100644 lib/sol10priv.c
 create mode 100644 lib/sol10priv.h
 create mode 100644 m4/sol10priv.m4
 create mode 100644 modules/sol10priv

diff --git a/ChangeLog b/ChangeLog
index 6389ebe..249f696 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-04-27  David Bartley  <dtbar...@csclub.uwaterloo.ca>
+        New module 'sol10priv'.
+        * lib/sol10priv.c: New file.
+        * lib/sol10priv.h: New file.
+        * m4/sol10priv.m4: New file.
+        * modules/sol10priv: New file.
+        * lib/unlinkdir.c: Make cannot_unlink_dir thread-safe.
+        * modules/unlinkdir: Add dependency on sol10priv module.
+
 2009-04-27  Bruno Haible  <br...@clisp.org>
 
 	New module 'libunistring'.
diff --git a/lib/sol10priv.c b/lib/sol10priv.c
new file mode 100644
index 0000000..e522ad2
--- /dev/null
+++ b/lib/sol10priv.c
@@ -0,0 +1,117 @@
+/* Query, remove, or restore a Solaris 10 privilege.
+
+   Copyright (C) 2009 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/>.
+
+   Written by David Bartley.  */
+
+#include <config.h>
+
+#if HAVE_GETPPRIV
+
+# include "sol10priv.h"
+# include <priv.h>
+
+static priv_set_t *eff_set;
+static priv_set_t *rem_set;
+static bool initialized;
+
+static int
+sol10priv_init (void)
+{
+  if (! initialized)
+    {
+      eff_pset = priv_allocset ();
+      if (!eff_pset)
+	{
+	  return -1;
+	}
+      rem_pset = priv_allocset ();
+      if (!rem_pset)
+	{
+	  priv_freeset (eff_pset);
+	  return -1;
+	}
+      if (getppriv (PRIV_EFFECTIVE, eff_set) != 0)
+	{
+	  priv_freeset (eff_pset);
+	  priv_freeset (rem_pset);
+	  return -1;
+	}
+      priv_emptyset (rem_set);
+      initialized = true;
+    }
+
+  return 0;
+}
+
+
+/* Check if priv is in the effective set.  */
+int
+sol10priv_ismember (const char *priv)
+{
+  if (! initialized && ! sol10priv_initialize ())
+    return -1;
+
+  return priv_ismember (eff_set, priv);
+}
+
+
+/* Try to remove priv from the effective set.  */
+int
+sol10priv_remove (const char *priv)
+{
+  if (! initialized && ! sol10priv_initialize ())
+    return -1;
+
+  if (priv_ismember (eff_set, priv) && ! priv_ismember (rem_set, priv))
+    {
+      if (priv_delset (eff_set, priv) != 0)
+	return -1;
+      if (setppriv (PRIV_EFFECTIVE, eff_set) != 0)
+	{
+	  priv_addset (eff_set, priv);
+	  return -1;
+	}
+      priv_addset (rem_set, priv);
+    }
+
+  return 0;
+}
+
+
+/* Try to restore priv if it was previously removed from the effective set.  */
+int
+sol10priv_restore (const char *priv)
+{
+  if (! initialized && ! sol10priv_initialize ())
+    return -1;
+
+  if (priv_ismember (rem_set, priv) && ! priv_ismember (eff_set, priv))
+    {
+      if (priv_addset (eff_set, priv) != 0)
+	return -1;
+      if (setppriv (PRIV_EFFECTIVE, eff_set) != 0)
+	{
+	  priv_addset (eff_set, priv);
+	  return -1;
+	}
+      priv_delset (rem_set, priv);
+    }
+
+  return 0;
+}
+
+#endif
diff --git a/lib/sol10priv.h b/lib/sol10priv.h
new file mode 100644
index 0000000..5e72fd6
--- /dev/null
+++ b/lib/sol10priv.h
@@ -0,0 +1,26 @@
+/* Query, remove, or restore a Solaris 10 privilege.
+
+   Copyright (C) 2009 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/>.
+
+   Written by David Bartley.  */
+
+#if HAVE_GETPPRIV
+
+int sol10priv_ismember (const char *priv);
+int sol10priv_remove (const char *priv);
+int sol10priv_restore (const char *priv);
+
+#endif
diff --git a/lib/unlinkdir.c b/lib/unlinkdir.c
index 9c3ff00..e32986b 100644
--- a/lib/unlinkdir.c
+++ b/lib/unlinkdir.c
@@ -1,4 +1,4 @@
-/* unlinkdir.c - determine (and maybe change) whether we can unlink directories
+/* unlinkdir.c - determine whether we can unlink directories
 
    Copyright (C) 2005-2006, 2009 Free Software Foundation, Inc.
 
@@ -15,11 +15,12 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-/* Written by Paul Eggert and Jim Meyering.  */
+/* Written by Paul Eggert, Jim Meyering, and David Bartley.  */
 
 #include <config.h>
 
 #include "unlinkdir.h"
+#include "sol10priv.h"
 
 #if HAVE_PRIV_H
 # include <priv.h>
@@ -29,12 +30,7 @@
 #if ! UNLINK_CANNOT_UNLINK_DIR
 
 /* Return true if we cannot unlink directories, false if we might be
-   able to unlink directories.  If possible, tell the kernel we don't
-   want to be able to unlink directories, so that we can return true.
-
-   Note: this function may modify the process privilege set, to remove
-   the PRIV_SYS_LINKDIR privilege, so is neither thread-safe, nor
-   appropriate for use in a library.  */
+   able to unlink directories.  */
 
 bool
 cannot_unlink_dir (void)
@@ -44,20 +40,11 @@ cannot_unlink_dir (void)
 
   if (! initialized)
     {
-# if defined PRIV_EFFECTIVE && defined PRIV_SYS_LINKDIR
+# if HAVE_GETPPRIV && defined PRIV_SYS_LINKDIR
       /* We might be able to unlink directories if we cannot
 	 determine our privileges, or if we have the
-	 PRIV_SYS_LINKDIR privilege and cannot delete it.  */
-      priv_set_t *pset = priv_allocset ();
-      if (pset)
-	{
-	  cannot =
-	    (getppriv (PRIV_EFFECTIVE, pset) == 0
-	     && (! priv_ismember (pset, PRIV_SYS_LINKDIR)
-		 || (priv_delset (pset, PRIV_SYS_LINKDIR) == 0
-		     && setppriv (PRIV_SET, PRIV_EFFECTIVE, pset) == 0)));
-	  priv_freeset (pset);
-	}
+	 PRIV_SYS_LINKDIR privilege.  */
+      cannot = (sol10priv_ismember (PRIV_SYS_LINKDIR) == 0);
 # else
       /* In traditional Unix, only root can unlink directories.  */
       cannot = (geteuid () != 0);
diff --git a/m4/sol10priv.m4 b/m4/sol10priv.m4
new file mode 100644
index 0000000..e58f402
--- /dev/null
+++ b/m4/sol10priv.m4
@@ -0,0 +1,14 @@
+# serial 6
+
+# Copyright (C) 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Written by David Bartley.
+
+AC_DEFUN([gl_SOL10PRIV],
+[
+  AC_CHECK_FUNCS([getppriv])
+])
diff --git a/modules/sol10priv b/modules/sol10priv
new file mode 100644
index 0000000..5c35318
--- /dev/null
+++ b/modules/sol10priv
@@ -0,0 +1,25 @@
+Description:
+Query, remove or, restore a Solaris 10 privilege
+
+Files:
+lib/sol10priv.h
+lib/sol10priv.c
+m4/sol10priv.m4
+
+Depends-on:
+stdbool
+
+configure.ac:
+gl_SOL10PRIV
+
+Makefile.am:
+lib_SOURCES += sol10priv-remove.c sol10priv-restore.c
+
+Include:
+"sol10priv.h"
+
+License:
+GPL
+
+Maintainer:
+David Bartley
diff --git a/modules/unlinkdir b/modules/unlinkdir
index e8c68a6..9a0a284 100644
--- a/modules/unlinkdir
+++ b/modules/unlinkdir
@@ -1,5 +1,5 @@
 Description:
-Determine (and maybe change) whether we can unlink directories.
+Determine whether we can unlink directories.
 
 Files:
 lib/unlinkdir.h
@@ -8,6 +8,7 @@ m4/unlinkdir.m4
 
 Depends-on:
 stdbool
+sol10priv
 
 configure.ac:
 gl_UNLINKDIR
-- 
1.5.6.5

Reply via email to