bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: bug#10021: [PATCH id] Add error-checking on GNU


From: Paul Eggert
Subject: Re: bug#10021: [PATCH id] Add error-checking on GNU
Date: Wed, 16 Nov 2011 00:44:16 -0800
User-agent: Mozilla/5.0 (X11; Linux i686; rv:7.0.1) Gecko/20110929 Thunderbird/7.0.1

Here are proposed patches for the other coreutils applications
that invoke getuid et al.

port to GNU hosts, where getuid and friends can fail
* src/groups.c (main):
* src/install.c (need_copy):
* src/su.c (log_su):
* src/test.c (unary_operator):
* src/whoami.c (main):
Don't assume that getuid and friends always succeed.
This fixes the same problem that we recently fixed with 'id'.
diff --git a/src/groups.c b/src/groups.c
index abb7bc7..279b831 100644
--- a/src/groups.c
+++ b/src/groups.c
@@ -97,9 +97,23 @@ main (int argc, char **argv)
   if (optind == argc)
     {
       /* No arguments.  Divulge the details of the current process. */
+      uid_t NO_UID = -1;
+      gid_t NO_GID = -1;
+
+      errno = 0;
       ruid = getuid ();
+      if (ruid == NO_UID && errno)
+        error (EXIT_FAILURE, errno, _("cannot get real UID"));
+
+      errno = 0;
       egid = getegid ();
+      if (egid == NO_GID && errno)
+        error (EXIT_FAILURE, errno, _("cannot get effective GID"));
+
+      errno = 0;
       rgid = getgid ();
+      if (rgid == NO_GID && errno)
+        error (EXIT_FAILURE, errno, _("cannot get real GID"));

       if (!print_group_list (NULL, ruid, rgid, egid, true))
         ok = false;
diff --git a/src/install.c b/src/install.c
index dbff9c9..94534f8 100644
--- a/src/install.c
+++ b/src/install.c
@@ -192,9 +192,27 @@ need_copy (const char *src_name, const char *dest_name,
     return true;

   if (src_sb.st_size != dest_sb.st_size
-      || (dest_sb.st_mode & CHMOD_MODE_BITS) != mode
-      || dest_sb.st_uid != (owner_id == (uid_t) -1 ? getuid () : owner_id)
-      || dest_sb.st_gid != (group_id == (gid_t) -1 ? getgid () : group_id))
+      || (dest_sb.st_mode & CHMOD_MODE_BITS) != mode)
+    return true;
+
+  if (owner_id == (uid_t) -1)
+    {
+      errno = 0;
+      uid_t ruid = getuid ();
+      if ((ruid == (uid_t) -1 && errno) || dest_sb.st_uid != ruid)
+        return true;
+    }
+  else if (dest_sb.st_uid != owner_id)
+    return true;
+
+  if (group_id == (uid_t) -1)
+    {
+      errno = 0;
+      gid_t rgid = getgid ();
+      if ((rgid == (uid_t) -1 && errno) || dest_sb.st_gid != rgid)
+        return true;
+    }
+  else if (dest_sb.st_gid != group_id)
     return true;

   /* compare SELinux context if preserving */
diff --git a/src/su.c b/src/su.c
index 081ecb2..b1ba2a7 100644
--- a/src/su.c
+++ b/src/su.c
@@ -173,7 +173,10 @@ log_su (struct passwd const *pw, bool successful)
     {
       /* getlogin can fail -- usually due to lack of utmp entry.
          Resort to getpwuid.  */
-      struct passwd *pwd = getpwuid (getuid ());
+      errno = 0;
+      uid_t ruid = getuid ();
+      uid_t NO_UID = -1;
+      struct passwd *pwd = (ruid == NO_UID && errno ? NULL : getpwuid (ruid));
       old_user = (pwd ? pwd->pw_name : "");
     }
   tty = ttyname (STDERR_FILENO);
diff --git a/src/test.c b/src/test.c
index 362df65..1b06ca8 100644
--- a/src/test.c
+++ b/src/test.c
@@ -414,13 +414,21 @@ unary_operator (void)

     case 'O':                  /* File is owned by you? */
       unary_advance ();
-      return (stat (argv[pos - 1], &stat_buf) == 0
-              && (geteuid () == stat_buf.st_uid));
+      if (stat (argv[pos - 1], &stat_buf) != 0)
+        return false;
+      errno = 0;
+      uid_t euid = geteuid ();
+      uid_t NO_UID = -1;
+      return ! (euid == NO_UID && errno) && euid == stat_buf.st_uid;

     case 'G':                  /* File is owned by your group? */
       unary_advance ();
-      return (stat (argv[pos - 1], &stat_buf) == 0
-              && (getegid () == stat_buf.st_gid));
+      if (stat (argv[pos - 1], &stat_buf) != 0)
+        return false;
+      errno = 0;
+      gid_t egid = getegid ();
+      gid_t NO_GID = -1;
+      return ! (egid == NO_GID && errno) && egid == stat_buf.st_gid;

     case 'f':                  /* File is a file? */
       unary_advance ();
diff --git a/src/whoami.c b/src/whoami.c
index e563dcf..1b0c3cd 100644
--- a/src/whoami.c
+++ b/src/whoami.c
@@ -61,6 +61,7 @@ main (int argc, char **argv)
 {
   struct passwd *pw;
   uid_t uid;
+  uid_t NO_UID = -1;

   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
@@ -81,8 +82,9 @@ main (int argc, char **argv)
       usage (EXIT_FAILURE);
     }

+  errno = 0;
   uid = geteuid ();
-  pw = getpwuid (uid);
+  pw = (uid == NO_UID && errno ? NULL : getpwuid (uid));
   if (pw)
     {
       puts (pw->pw_name);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]