Article View: gnu.utils.bug
Article #1151fileutils-3.4: chgrp problems on old bsd systems, +fix
From: Mike Rendell
Date: Fri, 11 Dec 1992 11:09
Date: Fri, 11 Dec 1992 11:09
321 lines
9054 bytes
9054 bytes
Machine: vax
OS: (old) 4.3bsd from Mt. Xinu, Ultrix 2.2, others
The GNU chgrp doesn't work on older versions of bsd because only root can
use chown(2) (there is a comment to this effect about sequents in the README
file). I've added (ifdef'd) code to the GNU chgrp to deal with such systems
when it is installed setuid root. The code checks that the user is in the
named group, makes sure the user owns all files before changing the group,
and checks directory permissions before recursing into them. The diffs for
configure(.in) add a test to see if the system has such a broken chown(2)
(the test is done in a readable/executable subdirectory, conftest.dir, so it
will work even if root is running configure). The diffs also add a
GETGROUPS_T test to the configure scripts since the modified chgrp uses
getgroups(). Note that the Makefile doesn't install chgrp as setuid
root - this needs to be done by hand.
*** src/chgrp.c.orig Fri Jul 17 17:18:38 1992
--- src/chgrp.c Fri Dec 11 14:41:06 1992
***************
*** 24,32 ****
#include <getopt.h>
#include "system.h"
! #ifndef _POSIX_VERSION
struct group *getgrnam ();
! #endif
#ifdef _POSIX_SOURCE
#define endgrent()
--- 24,48 ----
#include <getopt.h>
#include "system.h"
! #ifdef _POSIX_VERSION
! #include <limits.h>
! #if !defined(NGROUPS_MAX) || NGROUPS_MAX < 1
! #define NGROUPS_MAX sysconf (_SC_NGROUPS_MAX)
! #endif /* !NGROUPS_MAX */
!
! #else /* not _POSIX_VERSION */
struct group *getgrnam ();
! uid_t getuid ();
! gid_t getgid ();
! #include <sys/param.h>
! #if !defined(NGROUPS_MAX) && defined(NGROUPS)
! #define NGROUPS_MAX NGROUPS
! #endif /* not NGROUPS_MAX and NGROUPS */
! #endif /* not _POSIX_VERSION */
!
! #ifndef GETGROUPS_T
! # define GETGROUPS_T gid_t
! #endif /* !GETGROUPS_T */
#ifdef _POSIX_SOURCE
#define endgrent()
***************
*** 63,68 ****
--- 79,90 ----
/* The name of the group to which ownership of the files is being given. */
char *groupname;
+ #ifdef HAVE_BROKEN_CHOWN
+ /* Uid/gid of the user running the program. */
+ uid_t my_uid;
+ gid_t my_gid;
+ #endif /* HAVE_BROKEN_CHOWN */
+
struct option long_options[] =
{
{"recursive", 0, 0, 'R'},
***************
*** 113,118 ****
--- 135,166 ----
parse_group (argv[optind++], &group);
+ #ifdef HAVE_BROKEN_CHOWN
+ my_uid = getuid ();
+ my_gid = getgid ();
+ /* Check that (non-root) user is in group GROUP */
+ if (my_uid)
+ {
+ # ifdef NGROUPS_MAX
+ GETGROUPS_T *groups;
+ int i, n;
+
+ groups = (GETGROUPS_T *) xmalloc (NGROUPS_MAX * sizeof(GETGROUPS_T));
+ if ((n = getgroups (NGROUPS_MAX, groups)) < 0)
+ error (1, errno, "cannot get supplemental group list");
+ for (i = 0; i < n; i++)
+ if (groups[i] == group)
+ break;
+ if (i == n)
+ error (1, 0, "you are not in group %s", groupname);
+ free (groups);
+ # else /* not NGROUPS_MAX */
+ if (my_gid != group)
+ error (1, 0, "you are not in group %s", groupname);
+ # endif /* not NGROUPS_MAX */
+ }
+ #endif /* HAVE_BROKEN_CHOWN */
+
for (; optind < argc; ++optind)
errors |= change_file_group (argv[optind], group);
***************
*** 165,178 ****
if (group != file_stats.st_gid)
{
! if (verbose)
! describe_change (file, 1);
! if (chown (file, file_stats.st_uid, group))
{
if (force_silent == 0)
! error (0, errno, "%s", file);
errors = 1;
}
}
else if (verbose && changes_only == 0)
describe_change (file, 0);
--- 213,237 ----
if (group != file_stats.st_gid)
{
! #ifdef HAVE_BROKEN_CHOWN
! if (my_uid && file_stats.st_uid != my_uid)
{
if (force_silent == 0)
! error (0, 0, "you are not the owner of %s", file);
errors = 1;
}
+ else
+ #endif /* HAVE_BROKEN_CHOWN */
+ {
+ if (verbose)
+ describe_change (file, 1);
+ if (chown (file, file_stats.st_uid, group))
+ {
+ if (force_silent == 0)
+ error (0, errno, "%s", file);
+ errors = 1;
+ }
+ }
}
else if (verbose && changes_only == 0)
describe_change (file, 0);
***************
*** 199,204 ****
--- 258,274 ----
unsigned filelength; /* Length of each pathname to process. */
unsigned pathlength; /* Bytes allocated for `path'. */
int errors = 0;
+
+ #ifdef HAVE_BROKEN_CHOWN
+ /* If only X_OK were used, chgrp's errors could be used to list the
+ contents of unreadable directories. So use R_OK as well... */
+ if (my_uid && access (dir, R_OK|X_OK))
+ {
+ if (force_silent == 0)
+ error (0, errno, "%s", dir);
+ return 1;
+ }
+ #endif /* HAVE_BROKEN_CHOWN */
errno = 0;
name_space = savedir (dir, statp->st_size);
*** configure.orig Thu Oct 29 18:14:52 1992
--- configure Fri Dec 11 13:52:57 1992
***************
*** 525,530 ****
--- 525,582 ----
fi
rm -f conftest*
+ echo checking getgroups group id type
+ echo "#include <sys/types.h>
+ #define NGID 256
+ main()
+ {
+ gid_t gidset[NGID];
+ int i, n;
+ union { gid_t gval; long lval; } val;
+
+ val.lval = -1;
+ for (i = 0; i < NGID; i++)
+ gidset[i] = val.gval;
+ n = getgroups(sizeof(gidset) / (sizeof(int) > sizeof(gid_t)
+ ? sizeof(int) : sizeof(gid_t)) - 1, gidset);
+ if (n > 0 && gidset[n] != val.gval)
+ exit(0);
+ exit(1);
+ }" > conftest.c
+ eval $compile
+ if test -s conftest && ./conftest 2>/dev/null ; then
+ DEFS="$DEFS -DGETGROUPS_T=int"
+ fi
+ rm -f conftest*
+
+ echo checking for broken chown
+ echo "main()
+ {
+ int fd;
+ char *file = "\"conftest.data\"";
+
+ unlink (file);
+ if ((fd = creat (file, 0644)) < 0)
+ exit (1);
+ close (fd);
+ if (!getuid ())
+ {
+ if (chown (file, 1, getgid ()) < 0)
+ exit (1);
+ setuid (1);
+ }
+ if (chown (file, getuid (), getgid ()) < 0)
+ exit (0);
+ exit (1);
+ }" > conftest.c
+ eval $compile
+ [ -d conftest.dir ] || mkdir conftest.dir
+ chmod 755 conftest.dir
+ if test -s conftest && (cd ./conftest.dir; ../conftest) 2>/dev/null ; then
+ DEFS="$DEFS -DHAVE_BROKEN_CHOWN"
+ fi
+ rm -rf conftest*
+
echo checking integer size
cat <<EOF > conftest.c
main() { exit(!(sizeof(long) > sizeof(int))); }
***************
*** 715,720 ****
--- 767,775 ----
LIBS="$SAVELIBS" ALLOCA=alloca.o
fi
fi
+
+ echo checking for BSD
+ ( test -f /vmunix || test -f /sdmach || test -f /../../mach ) && DEFS="$DEFS -DBSD42=1"
echo checking for st_blocks in struct stat
echo "#include <sys/types.h>
*** configure.in.orig Thu Oct 29 16:27:10 1992
--- configure.in Fri Dec 11 13:56:32 1992
***************
*** 90,95 ****
--- 90,144 ----
fi
AC_UID_T
+ echo checking getgroups group id type
+ echo "#include <sys/types.h>
+ #define NGID 256
+ main()
+ {
+ gid_t gidset[NGID];
+ int i, n;
+ union { gid_t gval; long lval; } val;
+
+ val.lval = -1;
+ for (i = 0; i < NGID; i++)
+ gidset[i] = val.gval;
+ n = getgroups (sizeof(gidset) / (sizeof(int) > sizeof(gid_t)
+ ? sizeof(int) : sizeof(gid_t)) - 1, gidset);
+ if (n > 0 && gidset[n] != val.gval)
+ exit (0);
+ exit (1);
+ }" > conftest.c
+ eval $compile
+ if test -s conftest && ./conftest 2>/dev/null ; then
+ DEFS="$DEFS -DGETGROUPS_T=int"
+ fi
+ rm -f conftest*
+ echo checking for broken chown
+ echo "main()
+ {
+ int fd;
+ char *file = "\"conftest.data\"";
+
+ unlink (file);
+ if ((fd = creat (file, 0644)) < 0)
+ exit (1);
+ close (fd);
+ if (!getuid ())
+ {
+ if (chown (file, 1, getgid ()) < 0)
+ exit (1);
+ setuid (1);
+ }
+ if (chown (file, getuid (), getgid ()) < 0)
+ exit (0);
+ exit (1);
+ }" > conftest.c
+ [ -d conftest.dir ] || mkdir conftest.dir
+ chmod 755 conftest.dir
+ if test -s conftest && (cd ./conftest.dir; ../conftest) 2>/dev/null ; then
+ DEFS="$DEFS -DHAVE_BROKEN_CHOWN"
+ fi
+ rm -rf conftest*
AC_INT_16_BITS
AC_STDC_HEADERS
AC_UNISTD_H
***************
*** 117,122 ****
--- 166,173 ----
AC_VPRINTF
AC_ALLOCA
+ echo checking for BSD
+ ( test -f /vmunix || test -f /sdmach || test -f /../../mach ) && AC_DEFINE(BSD4_2)
AC_ST_BLOCKS
AC_UTIME_NULL
AC_XENIX_DIR
--
Michael Rendell - Dept. of Comp. Sci., Memorial University of Newfoundland
Technical Details
Message-ID:
<9212111827.AA19890@mercury.cs.mun.ca>Path:
arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!mercury.cs.mun.ca!michaelShow Full Headers
Complete Article Headers
Newsgroups: gnu.utils.bug Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!mercury.cs.mun.ca!michael From: michael@mercury.cs.mun.ca (Mike Rendell) Subject: fileutils-3.4: chgrp problems on old bsd systems, +fix Message-ID: <9212111827.AA19890@mercury.cs.mun.ca> Sender: gnulists@ai.mit.edu Organization: GNUs Not Usenet Distribution: gnu Date: Fri, 11 Dec 1992 11:09:55 GMT Approved: bug-gnu-utils@prep.ai.mit.edu Lines: 322