strip setuid/setgid bits on backup (was Re: small security-related rsync extension)
Martin Pool
mbp at samba.org
Mon Jul 8 01:01:37 EST 2002
Any thoughts on whether this should go in? I can see arguments either
way. It seems like we ought to think about whether it would be better
to do it as part of a generalized --chmod or --chmod-backup facility.
--
Martin
On 21 Jun 2002, Dan Stromberg <strombrg at nis.acs.uci.edu> wrote:
> Included below is a shar archive containing two patches that together:
>
> 1) make backup files get their setuid and setgid bits stripped by
> default
>
> 2) add a "-s" option that allows backup files to continue to have
> these privileges
>
> This means that if you update a collection of binaries with rsync, and
> one or more of them has a local-root security problem, the backup
> file(s) created when you fix the problem in your source archive won't
> remain exploitable.
>
> The patch is relative to 2.5.4.
>
> The backup-dir support is attempted but untested. We're using the
> default backup behavior (with ~) in production. I'd be pleased if
> someone who uses backup-dir were to try it out and let me know how it
> goes.
>
> I'd also be pleased if this were to find its way into the main
> distribution in some form.
>
> Thank you.
>
> #!/bin/sh
> # This is a shell archive (shar 3.32)
> # made 06/21/2002 20:17 UTC by dcslib at tokyo.acs.uci.edu
> # Source directory /dcslibsrc/network/rsync/exportable-patches
> #
> # existing files WILL be overwritten
> #
> # This shar contains:
> # length mode name
> # ------ ---------- ------------------------------------------
> # 1798 -rw-r--r-- backup-priv-backups
> # 1339 -rw-r--r-- options-priv-backups
> #
> if touch 2>&1 | fgrep 'amc' > /dev/null
> then TOUCH=touch
> else TOUCH=true
> fi
> # ============= backup-priv-backups ==============
> echo "x - extracting backup-priv-backups (Text)"
> sed 's/^X//' << 'SHAR_EOF' > backup-priv-backups &&
> X*** backup.c.t Sun May 6 23:59:37 2001
> X--- backup.c Fri Jun 21 13:15:51 2002
> X***************
> X*** 29,34 ****
> X--- 29,56 ----
> X extern int preserve_devices;
> X extern int preserve_links;
> X extern int preserve_hard_links;
> X+ extern int priv_backups;
> X+
> X+ #ifdef HAVE_CHMOD
> X+ static int strip_perm(char *fname)
> X+ {
> X+ struct stat buf;
> X+ if (link_stat(fname,&buf) != 0) {
> X+ rprintf(FERROR,"stat failed\n");
> X+ return 0;
> X+ }
> X+
> X+ if (S_ISREG(buf.st_mode) && (buf.st_mode & (S_ISUID | S_ISGID))) {
> X+ mode_t new_mode;
> X+ new_mode = buf.st_mode & 01777;
> X+ if (do_chmod(fname,new_mode) != 0) {
> X+ rprintf(FERROR,"chmod failed\n");
> X+ return 0;
> X+ }
> X+ }
> X+ return 1;
> X+ }
> X+ #endif
> X
> X /* simple backup creates a backup with a suffix in the same directory */
> X static int make_simple_backup(char *fname)
> X***************
> X*** 46,54 ****
> X rsyserr(FERROR, errno, "rename %s to backup %s", fname, fnamebak);
> X return 0;
> X }
> X! } else if (verbose > 1) {
> X! rprintf(FINFO,"backed up %s to %s\n",fname,fnamebak);
> X }
> X return 1;
> X }
> X
> X--- 68,86 ----
> X rsyserr(FERROR, errno, "rename %s to backup %s", fname, fnamebak);
> X return 0;
> X }
> X! } else {
> X! if (verbose > 1) {
> X! rprintf(FINFO,"backed up %s to %s\n",fname,fnamebak);
> X! }
> X! #ifdef HAVE_CHMOD
> X! if (!priv_backups && strip_perm(fnamebak) == 0) {
> X! return 0;
> X! } else if (verbose > 1) {
> X! rprintf(FINFO,"Stripped setuid and/or setgid from %s\n",fnamebak);
> X! }
> X! #endif
> X }
> X+
> X return 1;
> X }
> X
> X***************
> X*** 271,276 ****
> X--- 303,314 ----
> X fname, keep_name, strerror(errno));
> X };
> X set_perms (keep_name, file, NULL, 0);
> X+ /* may mean an extra stat */
> X+ #ifdef HAVE_CHMOD
> X+ if (!priv_backups && strip_perm(keep_name) == 0) {
> X+ return 0;
> X+ }
> X+ #endif
> X free_file (file);
> X free (file);
> X
> SHAR_EOF
> $TOUCH -am 06211315102 backup-priv-backups &&
> chmod 0644 backup-priv-backups ||
> echo "restore of backup-priv-backups failed"
> set `wc -c backup-priv-backups`;Wc_c=$1
> if test "$Wc_c" != "1798"; then
> echo original size 1798, current size $Wc_c
> fi
> # ============= options-priv-backups ==============
> echo "x - extracting options-priv-backups (Text)"
> sed 's/^X//' << 'SHAR_EOF' > options-priv-backups &&
> X--- options.c.t Fri Jun 21 08:56:31 2002
> X+++ options.c Fri Jun 21 09:41:41 2002
> X@@ -21,6 +21,9 @@
> X #include "rsync.h"
> X #include "popt.h"
> X
> X+#ifdef HAVE_CHMOD
> X+int priv_backups = 0;
> X+#endif
> X int make_backups = 0;
> X int whole_file = -1;
> X int copy_links = 0;
> X@@ -188,6 +191,7 @@
> X rprintf(F," -b, --backup make backups (default %s suffix)\n",BACKUP_SUFFIX);
> X rprintf(F," --backup-dir make backups into this directory\n");
> X rprintf(F," --suffix=SUFFIX override backup suffix\n");
> X+ rprintf(F," --priv-backups preserve set[ug]id on backups\n");
> X rprintf(F," -u, --update update only (don't overwrite newer files)\n");
> X rprintf(F," -l, --links copy symlinks as symlinks\n");
> X rprintf(F," -L, --copy-links copy the referent of symlinks\n");
> X@@ -291,6 +295,9 @@
> X {"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM},
> X {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks},
> X {"help", 'h', POPT_ARG_NONE, 0, 'h'},
> X+#ifdef HAVE_CHMOD
> X+ {"priv-backups", 's', POPT_ARG_NONE, &priv_backups},
> X+#endif
> X {"backup", 'b', POPT_ARG_NONE, &make_backups},
> X {"dry-run", 'n', POPT_ARG_NONE, &dry_run},
> X {"sparse", 'S', POPT_ARG_NONE, &sparse_files},
> SHAR_EOF
> $TOUCH -am 06210941102 options-priv-backups &&
> chmod 0644 options-priv-backups ||
> echo "restore of options-priv-backups failed"
> set `wc -c options-priv-backups`;Wc_c=$1
> if test "$Wc_c" != "1339"; then
> echo original size 1339, current size $Wc_c
> fi
> exit 0
>
More information about the rsync
mailing list