summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/groups.c14
-rw-r--r--src/install.c24
-rw-r--r--src/su.c5
-rw-r--r--src/test.c16
-rw-r--r--src/whoami.c4
5 files changed, 54 insertions, 9 deletions
diff --git a/src/groups.c b/src/groups.c
index abb7bc7c7..279b83168 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 dbff9c94b..94534f81e 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 081ecb2eb..b1ba2a7b7 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 362df65d8..1b06ca86e 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 e563dcf20..1b0c3cdb6 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);