home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / gnu / utils / bug / 2214 < prev    next >
Encoding:
Text File  |  1992-12-12  |  8.5 KB  |  335 lines

  1. Newsgroups: gnu.utils.bug
  2. Path: sparky!uunet!cis.ohio-state.edu!mercury.cs.mun.ca!michael
  3. From: michael@mercury.cs.mun.ca (Mike Rendell)
  4. Subject: fileutils-3.4: chgrp problems on old bsd systems, +fix
  5. Message-ID: <9212111827.AA19890@mercury.cs.mun.ca>
  6. Sender: gnulists@ai.mit.edu
  7. Organization: GNUs Not Usenet
  8. Distribution: gnu
  9. Date: Fri, 11 Dec 1992 11:09:55 GMT
  10. Approved: bug-gnu-utils@prep.ai.mit.edu
  11. Lines: 322
  12.  
  13. Machine: vax
  14. OS: (old) 4.3bsd from Mt. Xinu, Ultrix 2.2, others
  15.  
  16. The GNU chgrp doesn't work on older versions of bsd because only root can
  17. use chown(2) (there is a comment to this effect about sequents in the README
  18. file).  I've added (ifdef'd) code to the GNU chgrp to deal with such systems
  19. when it is installed setuid root.  The code checks that the user is in the
  20. named group, makes sure the user owns all files before changing the group,
  21. and checks directory permissions before recursing into them.  The diffs for
  22. configure(.in) add a test to see if the system has such a broken chown(2)
  23. (the test is done in a readable/executable subdirectory, conftest.dir, so it
  24. will work even if root is running configure).  The diffs also add a
  25. GETGROUPS_T test to the configure scripts since the modified chgrp uses
  26. getgroups().  Note that the Makefile doesn't install chgrp as setuid
  27. root - this needs to be done by hand.
  28.  
  29.  
  30. *** src/chgrp.c.orig    Fri Jul 17 17:18:38 1992
  31. --- src/chgrp.c    Fri Dec 11 14:41:06 1992
  32. ***************
  33. *** 24,32 ****
  34.   #include <getopt.h>
  35.   #include "system.h"
  36.   
  37. ! #ifndef _POSIX_VERSION
  38.   struct group *getgrnam ();
  39. ! #endif
  40.   
  41.   #ifdef _POSIX_SOURCE
  42.   #define endgrent()
  43. --- 24,48 ----
  44.   #include <getopt.h>
  45.   #include "system.h"
  46.   
  47. ! #ifdef _POSIX_VERSION
  48. ! #include <limits.h>
  49. ! #if !defined(NGROUPS_MAX) || NGROUPS_MAX < 1
  50. ! #define NGROUPS_MAX sysconf (_SC_NGROUPS_MAX)
  51. ! #endif /* !NGROUPS_MAX */
  52. ! #else /* not _POSIX_VERSION */
  53.   struct group *getgrnam ();
  54. ! uid_t getuid ();
  55. ! gid_t getgid ();
  56. ! #include <sys/param.h>
  57. ! #if !defined(NGROUPS_MAX) && defined(NGROUPS)
  58. ! #define NGROUPS_MAX NGROUPS
  59. ! #endif /* not NGROUPS_MAX and NGROUPS */
  60. ! #endif /* not _POSIX_VERSION */
  61. ! #ifndef GETGROUPS_T
  62. ! # define GETGROUPS_T gid_t
  63. ! #endif /* !GETGROUPS_T */
  64.   
  65.   #ifdef _POSIX_SOURCE
  66.   #define endgrent()
  67. ***************
  68. *** 63,68 ****
  69. --- 79,90 ----
  70.   /* The name of the group to which ownership of the files is being given. */
  71.   char *groupname;
  72.   
  73. + #ifdef HAVE_BROKEN_CHOWN
  74. + /* Uid/gid of the user running the program. */
  75. + uid_t    my_uid;
  76. + gid_t    my_gid;
  77. + #endif /* HAVE_BROKEN_CHOWN */
  78.   struct option long_options[] =
  79.   {
  80.     {"recursive", 0, 0, 'R'},
  81. ***************
  82. *** 113,118 ****
  83. --- 135,166 ----
  84.   
  85.     parse_group (argv[optind++], &group);
  86.   
  87. + #ifdef HAVE_BROKEN_CHOWN
  88. +   my_uid = getuid ();
  89. +   my_gid = getgid ();
  90. +   /* Check that (non-root) user is in group GROUP */
  91. +   if (my_uid)
  92. +     {
  93. + # ifdef NGROUPS_MAX
  94. +       GETGROUPS_T *groups;
  95. +       int i, n;
  96. +       groups = (GETGROUPS_T *) xmalloc (NGROUPS_MAX * sizeof(GETGROUPS_T));
  97. +       if ((n = getgroups (NGROUPS_MAX, groups)) < 0)
  98. +     error (1, errno, "cannot get supplemental group list");
  99. +       for (i = 0; i < n; i++)
  100. +     if (groups[i] == group)
  101. +       break;
  102. +       if (i == n)
  103. +     error (1, 0, "you are not in group %s", groupname);
  104. +       free (groups);
  105. + # else /* not NGROUPS_MAX */
  106. +       if (my_gid != group)
  107. +     error (1, 0, "you are not in group %s", groupname);
  108. + # endif /* not NGROUPS_MAX */
  109. +     }
  110. + #endif /* HAVE_BROKEN_CHOWN */
  111.     for (; optind < argc; ++optind)
  112.       errors |= change_file_group (argv[optind], group);
  113.   
  114. ***************
  115. *** 165,178 ****
  116.   
  117.     if (group != file_stats.st_gid)
  118.       {
  119. !       if (verbose)
  120. !     describe_change (file, 1);
  121. !       if (chown (file, file_stats.st_uid, group))
  122.       {
  123.         if (force_silent == 0)
  124. !         error (0, errno, "%s", file);
  125.         errors = 1;
  126.       }
  127.       }
  128.     else if (verbose && changes_only == 0)
  129.       describe_change (file, 0);
  130. --- 213,237 ----
  131.   
  132.     if (group != file_stats.st_gid)
  133.       {
  134. ! #ifdef HAVE_BROKEN_CHOWN
  135. !       if (my_uid && file_stats.st_uid != my_uid)
  136.       {
  137.         if (force_silent == 0)
  138. !         error (0, 0, "you are not the owner of %s", file);
  139.         errors = 1;
  140.       }
  141. +       else
  142. + #endif /* HAVE_BROKEN_CHOWN */
  143. +     {
  144. +       if (verbose)
  145. +         describe_change (file, 1);
  146. +       if (chown (file, file_stats.st_uid, group))
  147. +         {
  148. +           if (force_silent == 0)
  149. +         error (0, errno, "%s", file);
  150. +           errors = 1;
  151. +         }
  152. +     }
  153.       }
  154.     else if (verbose && changes_only == 0)
  155.       describe_change (file, 0);
  156. ***************
  157. *** 199,204 ****
  158. --- 258,274 ----
  159.     unsigned filelength;        /* Length of each pathname to process. */
  160.     unsigned pathlength;        /* Bytes allocated for `path'. */
  161.     int errors = 0;
  162. + #ifdef HAVE_BROKEN_CHOWN
  163. +   /* If only X_OK were used, chgrp's errors could be used to list the
  164. +      contents of unreadable directories.  So use R_OK as well... */
  165. +   if (my_uid && access (dir, R_OK|X_OK))
  166. +     {
  167. +       if (force_silent == 0)
  168. +     error (0, errno, "%s", dir);
  169. +       return 1;
  170. +     }
  171. + #endif /* HAVE_BROKEN_CHOWN */
  172.   
  173.     errno = 0;
  174.     name_space = savedir (dir, statp->st_size);
  175.  
  176.  
  177. *** configure.orig    Thu Oct 29 18:14:52 1992
  178. --- configure    Fri Dec 11 13:52:57 1992
  179. ***************
  180. *** 525,530 ****
  181. --- 525,582 ----
  182.   fi
  183.   rm -f conftest*
  184.   
  185. + echo checking getgroups group id type
  186. + echo "#include <sys/types.h>
  187. + #define NGID 256
  188. + main()
  189. + {
  190. +   gid_t gidset[NGID];
  191. +   int i, n;
  192. +   union { gid_t gval; long lval; }  val;
  193. +   val.lval = -1;
  194. +   for (i = 0; i < NGID; i++)
  195. +     gidset[i] = val.gval;
  196. +   n = getgroups(sizeof(gidset) / (sizeof(int) > sizeof(gid_t)
  197. +                               ? sizeof(int) : sizeof(gid_t)) - 1, gidset);
  198. +   if (n > 0 && gidset[n] != val.gval)
  199. +     exit(0);
  200. +   exit(1);
  201. + }" > conftest.c
  202. + eval $compile
  203. + if test -s conftest && ./conftest 2>/dev/null ; then
  204. +     DEFS="$DEFS -DGETGROUPS_T=int"
  205. + fi
  206. + rm -f conftest*
  207. + echo checking for broken chown
  208. + echo "main()
  209. + {
  210. +   int fd;
  211. +   char *file = "\"conftest.data\"";
  212. +   unlink (file);
  213. +   if ((fd = creat (file, 0644)) < 0)
  214. +     exit (1);
  215. +   close (fd);
  216. +   if (!getuid ())
  217. +     {
  218. +       if (chown (file, 1, getgid ()) < 0)
  219. +     exit (1);
  220. +       setuid (1);
  221. +     }
  222. +   if (chown (file, getuid (), getgid ()) < 0)
  223. +     exit (0);
  224. +   exit (1);
  225. + }" > conftest.c
  226. + eval $compile
  227. + [ -d conftest.dir ] || mkdir conftest.dir
  228. + chmod 755 conftest.dir
  229. + if test -s conftest && (cd ./conftest.dir; ../conftest) 2>/dev/null ; then
  230. +     DEFS="$DEFS -DHAVE_BROKEN_CHOWN"
  231. + fi
  232. + rm -rf conftest*
  233.   echo checking integer size
  234.   cat <<EOF > conftest.c
  235.   main() { exit(!(sizeof(long) > sizeof(int))); }
  236. ***************
  237. *** 715,720 ****
  238. --- 767,775 ----
  239.       LIBS="$SAVELIBS" ALLOCA=alloca.o
  240.     fi
  241.   fi
  242. + echo checking for BSD
  243. + ( test -f /vmunix || test -f /sdmach || test -f /../../mach ) && DEFS="$DEFS -DBSD42=1"
  244.   
  245.   echo checking for st_blocks in struct stat
  246.   echo "#include <sys/types.h>
  247.  
  248.  
  249. *** configure.in.orig    Thu Oct 29 16:27:10 1992
  250. --- configure.in    Fri Dec 11 13:56:32 1992
  251. ***************
  252. *** 90,95 ****
  253. --- 90,144 ----
  254.   fi
  255.   
  256.   AC_UID_T
  257. + echo checking getgroups group id type
  258. + echo "#include <sys/types.h>
  259. + #define NGID 256
  260. + main()
  261. + {
  262. +   gid_t gidset[NGID];
  263. +   int i, n;
  264. +   union { gid_t gval; long lval; }  val;
  265. +   val.lval = -1;
  266. +   for (i = 0; i < NGID; i++)
  267. +     gidset[i] = val.gval;
  268. +   n = getgroups (sizeof(gidset) / (sizeof(int) > sizeof(gid_t)
  269. +                               ? sizeof(int) : sizeof(gid_t)) - 1, gidset);
  270. +   if (n > 0 && gidset[n] != val.gval)
  271. +     exit (0);
  272. +   exit (1);
  273. + }" > conftest.c
  274. + eval $compile
  275. + if test -s conftest && ./conftest 2>/dev/null ; then
  276. +     DEFS="$DEFS -DGETGROUPS_T=int"
  277. + fi
  278. + rm -f conftest*
  279. + echo checking for broken chown
  280. + echo "main()
  281. + {
  282. +   int fd;
  283. +   char *file = "\"conftest.data\"";
  284. +   unlink (file);
  285. +   if ((fd = creat (file, 0644)) < 0)
  286. +     exit (1);
  287. +   close (fd);
  288. +   if (!getuid ())
  289. +     {
  290. +       if (chown (file, 1, getgid ()) < 0)
  291. +     exit (1);
  292. +       setuid (1);
  293. +     }
  294. +   if (chown (file, getuid (), getgid ()) < 0)
  295. +       exit (0);
  296. +   exit (1);
  297. + }" > conftest.c
  298. + [ -d conftest.dir ] || mkdir conftest.dir
  299. + chmod 755 conftest.dir
  300. + if test -s conftest && (cd ./conftest.dir; ../conftest) 2>/dev/null ; then
  301. +     DEFS="$DEFS -DHAVE_BROKEN_CHOWN"
  302. + fi
  303. + rm -rf conftest*
  304.   AC_INT_16_BITS
  305.   AC_STDC_HEADERS
  306.   AC_UNISTD_H
  307. ***************
  308. *** 117,122 ****
  309. --- 166,173 ----
  310.   
  311.   AC_VPRINTF
  312.   AC_ALLOCA
  313. + echo checking for BSD
  314. + ( test -f /vmunix || test -f /sdmach || test -f /../../mach ) && AC_DEFINE(BSD4_2)
  315.   AC_ST_BLOCKS
  316.   AC_UTIME_NULL
  317.   AC_XENIX_DIR
  318.  
  319. --
  320. Michael Rendell - Dept. of Comp. Sci., Memorial University of Newfoundland
  321.  
  322.