bb_getgroups.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /*
  2. * Utility routines.
  3. *
  4. * Copyright (C) 2017 Denys Vlasenko
  5. *
  6. * Licensed under GPLv2, see file LICENSE in this source tree.
  7. */
  8. //kbuild:lib-y += bb_getgroups.o
  9. #include "libbb.h"
  10. gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array)
  11. {
  12. int n = ngroups ? *ngroups : 0;
  13. /* getgroups may be a bit expensive, try to use it only once */
  14. if (n < 32)
  15. n = 32;
  16. for (;;) {
  17. // FIXME: ash tries so hard to not die on OOM (when we are called from test),
  18. // and we spoil it with just one xrealloc here
  19. group_array = xrealloc(group_array, (n+1) * sizeof(group_array[0]));
  20. n = getgroups(n, group_array);
  21. /*
  22. * If buffer is too small, kernel does not return new_n > n.
  23. * It returns -1 and EINVAL:
  24. */
  25. if (n >= 0) {
  26. /* Terminator for bb_getgroups(NULL, NULL) usage */
  27. group_array[n] = (gid_t) -1;
  28. break;
  29. }
  30. if (errno == EINVAL) { /* too small? */
  31. /* This is the way to ask kernel how big the array is */
  32. n = getgroups(0, group_array);
  33. continue;
  34. }
  35. /* Some other error (should never happen on Linux) */
  36. bb_simple_perror_msg_and_die("getgroups");
  37. }
  38. if (ngroups)
  39. *ngroups = n;
  40. return group_array;
  41. }
  42. uid_t FAST_FUNC get_cached_euid(uid_t *euid)
  43. {
  44. if (*euid == (uid_t)-1)
  45. *euid = geteuid();
  46. return *euid;
  47. }
  48. gid_t FAST_FUNC get_cached_egid(gid_t *egid)
  49. {
  50. if (*egid == (gid_t)-1)
  51. *egid = getegid();
  52. return *egid;
  53. }
  54. /* Return non-zero if GID is in our supplementary group list. */
  55. int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid)
  56. {
  57. int i;
  58. int ngroups;
  59. gid_t *group_array;
  60. if (groupinfo->ngroups == 0)
  61. groupinfo->supplementary_array = bb_getgroups(&groupinfo->ngroups, NULL);
  62. ngroups = groupinfo->ngroups;
  63. group_array = groupinfo->supplementary_array;
  64. /* Search through the list looking for GID. */
  65. for (i = 0; i < ngroups; i++)
  66. if (gid == group_array[i])
  67. return 1;
  68. return 0;
  69. }