From: Paul Eggert Date: Thu, 24 Oct 2013 07:19:56 +0000 (-0700) Subject: gzip: fix permissions issue on Solaris-like systems X-Git-Tag: v1.7~50 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=f4ea7ba0bd70b1fc9986aca3d76bf46b4fb8ec52;p=debian%2Fgzip gzip: fix permissions issue on Solaris-like systems I.e., on systems that let users give files away. * gzip.c (do_chown): New function. (copy_stat): Use it, to change the group, then the permissions, then the owner. Idea suggested by Vladimir Marek in --- diff --git a/gzip.c b/gzip.c index 93cc738..f40cd21 100644 --- a/gzip.c +++ b/gzip.c @@ -1696,6 +1696,21 @@ local int check_ofname() return OK; } +/* Change the owner and group of a file. FD is a file descriptor for + the file and NAME its name. Change it to user UID and to group GID. + If UID or GID is -1, though, do not change the corresponding user + or group. */ +static void +do_chown (int fd, char const *name, uid_t uid, gid_t gid) +{ +#ifndef NO_CHOWN +# if HAVE_FCHOWN + ignore_value (fchown (fd, uid, gid)); +# else + ignore_value (chown (name, uid, gid)); +# endif +#endif +} /* ======================================================================== * Copy modes, times, ownership from input file to output file. @@ -1734,16 +1749,14 @@ local void copy_stat(ifstat) } #endif -#ifndef NO_CHOWN - /* Copy ownership */ -# if HAVE_FCHOWN - ignore_value (fchown (ofd, ifstat->st_uid, ifstat->st_gid)); -# elif HAVE_CHOWN - ignore_value (chown (ofname, ifstat->st_uid, ifstat->st_gid)); -# endif -#endif + /* Change the group first, then the permissions, then the owner. + That way, the permissions will be correct on systems that allow + users to give away files, without introducing a security hole. + Security depends on permissions not containing the setuid or + setgid bits. */ + + do_chown (ofd, ofname, -1, ifstat->st_gid); - /* Copy the protection modes */ #if HAVE_FCHMOD r = fchmod (ofd, mode); #else @@ -1757,6 +1770,8 @@ local void copy_stat(ifstat) perror(ofname); } } + + do_chown (ofd, ofname, ifstat->st_uid, -1); } #if ! NO_DIR