[Toybox] [PATCH] id can work without /etc/{passwd,groups}

hhm heehooman at gmail.com
Thu Mar 19 19:08:53 PDT 2015


The toybox implementation of `id` shouldn't error out when no
/etc/passwd or /etc/group is present (other implementations, for
example busybox, didn't error when tested).

Currently, doing `id -u` (or `id -g` etc.) will error out, even though
no data from the above files is necessary; all the information can be
gotten from the syscalls. This is because pw->pw_uid and grp->gr_gid
are used while only the values of getuid() and getgid() are required.

Therefore, these commands will error out on stock android, where none
of these files are present in their standard locations.

This can easily be remedied by just using the values returned by the
syscalls, which are in fact already stored in variables in the present
implementation, for -u and -g, when -n is not used and no [user] is
provided on the command line (in which case those files need to be
queried anyway).


diff --git a/toys/posix/id.c b/toys/posix/id.c
index a5a94a5..950b02b 100644
--- a/toys/posix/id.c
+++ b/toys/posix/id.c
@@ -86,8 +86,8 @@ void do_id(char *username)
   int flags, i, ngroups;
   struct passwd *pw;
   struct group *grp;
-  uid_t uid = getuid(), euid = geteuid();
-  gid_t gid = getgid(), egid = getegid(), *groups;
+  uid_t uid = getuid(), euid = geteuid(), iuid;
+  gid_t gid = getgid(), egid = getegid(), *groups, igid;

   flags = toys.optflags;

@@ -100,66 +100,77 @@ void do_id(char *username)
   }

   i = flags & FLAG_r;
-  pw = xgetpwuid(i ? uid : euid);
-  if (TT.do_u) s_or_u(pw->pw_name, pw->pw_uid, 1);
-
-  grp = xgetgrgid(i ? gid : egid);
-  if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1);
+  iuid = i ? uid : euid;
+  igid = i ? gid : egid;
+
+  if ((!TT.do_n) && (TT.do_u || (flags & FLAG_g))) {
+    if (TT.do_u) {
+      s_or_u("", iuid, 1);
+    } else {
+      s_or_u("", igid, 1);
+    }
+  } else {
+    pw = xgetpwuid(iuid);
+    if (TT.do_u) s_or_u(pw->pw_name, pw->pw_uid, 1);
+
+    grp = xgetgrgid(igid);
+    if (flags & FLAG_g) s_or_u(grp->gr_name, grp->gr_gid, 1);
+
+    if (!TT.do_G && !TT.do_Z) {
+      showid("uid=", pw->pw_uid, pw->pw_name);
+      showid(" gid=", grp->gr_gid, grp->gr_name);
+
+      if (!i) {
+        if (uid != euid) {
+          pw = xgetpwuid(euid);
+          showid(" euid=", pw->pw_uid, pw->pw_name);
+        }
+        if (gid != egid) {
+          grp = xgetgrgid(egid);
+          showid(" egid=", grp->gr_gid, grp->gr_name);
+        }
+      }

-  if (!TT.do_G && !TT.do_Z) {
-    showid("uid=", pw->pw_uid, pw->pw_name);
-    showid(" gid=", grp->gr_gid, grp->gr_name);
+      showid(" groups=", grp->gr_gid, grp->gr_name);
+    }

-    if (!i) {
-      if (uid != euid) {
-        pw = xgetpwuid(euid);
-        showid(" euid=", pw->pw_uid, pw->pw_name);
+    if (!TT.do_Z) {
+      groups = (gid_t *)toybuf;
+      i = sizeof(toybuf)/sizeof(gid_t);
+      ngroups = username ? getgrouplist(username, gid, groups, &i)
+        : getgroups(i, groups);
+      if (ngroups<0) perror_exit(0);
+
+      int show_separator = !TT.do_G;
+      for (i = 0; i<ngroups; i++) {
+        if (show_separator) xputc(TT.do_G ? ' ' : ',');
+        show_separator = 1;
+        if (!(grp = getgrgid(groups[i]))) perror_msg(0);
+        else if (TT.do_G) s_or_u(grp->gr_name, grp->gr_gid, 0);
+        else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name);
+        else show_separator = 0; // Because we didn't show anything this time.
       }
-      if (gid != egid) {
-        grp = xgetgrgid(egid);
-        showid(" egid=", grp->gr_gid, grp->gr_name);
+      if (TT.do_G) {
+        xputc('\n');
+        exit(0);
       }
     }

-    showid(" groups=", grp->gr_gid, grp->gr_name);
-  }
+    if (CFG_TOYBOX_SELINUX) {
+      char *context = NULL;

-  if (!TT.do_Z) {
-    groups = (gid_t *)toybuf;
-    i = sizeof(toybuf)/sizeof(gid_t);
-    ngroups = username ? getgrouplist(username, gid, groups, &i)
-      : getgroups(i, groups);
-    if (ngroups<0) perror_exit(0);
-
-    int show_separator = !TT.do_G;
-    for (i = 0; i<ngroups; i++) {
-      if (show_separator) xputc(TT.do_G ? ' ' : ',');
-      show_separator = 1;
-      if (!(grp = getgrgid(groups[i]))) perror_msg(0);
-      else if (TT.do_G) s_or_u(grp->gr_name, grp->gr_gid, 0);
-      else if (grp->gr_gid != egid) showid("", grp->gr_gid, grp->gr_name);
-      else show_separator = 0; // Because we didn't show anything this time.
-    }
-    if (TT.do_G) {
-      xputc('\n');
-      exit(0);
+      if (is_selinux_enabled() < 1) {
+        if (TT.do_Z)
+          error_exit("SELinux disabled");
+      } else if (getcon(&context) == 0) {
+        if (!TT.do_Z) xputc(' ');
+        printf("context=%s", context);
+      }
+      if (CFG_TOYBOX_FREE) free(context);
     }
-  }
-
-  if (CFG_TOYBOX_SELINUX) {
-    char *context = NULL;

-    if (is_selinux_enabled() < 1) {
-      if (TT.do_Z)
-        error_exit("SELinux disabled");
-    } else if (getcon(&context) == 0) {
-      if (!TT.do_Z) xputc(' ');
-      printf("context=%s", context);
-    }
-    if (CFG_TOYBOX_FREE) free(context);
+    xputc('\n');
   }
-
-  xputc('\n');
 }

 void id_main(void)

 1426817333.0


More information about the Toybox mailing list