Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Jun 2006 19:20:24 GMT
From:      Martin Kammerhofer <dada@pluto.tugraz.at>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/88365: resubmission of MTA mangled PR
Message-ID:  <200606071920.k57JKOEi056025@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/88365; it has been noted by GNATS.

From: Martin Kammerhofer <dada@pluto.tugraz.at>
To: dada@sbox.tugraz.at
Cc:  
Subject: Re: bin/88365: resubmission of MTA mangled PR
Date: Wed, 7 Jun 2006 19:02:12 +0200

 >Submitter-Id:  current-users
 >Originator:    Martin Kammerhofer
 >Organization:  Graz Uni
 >Confidential:  no
 >Synopsis:      [patch] /bin/rm has problems with symbolic link flags
 >Severity:      non-critical
 >Priority:      medium
 >Category:      bin
 >Class:         sw-bug
 >Release:       FreeBSD 6.1-STABLE i386
 >Environment:
 System: FreeBSD Martin.liebt.Susi 6.1-STABLE FreeBSD 6.1-STABLE #2: Fri Jun 2 14:53:34 CEST 2006 toor@Martin.liebt.Susi:/usr/obj/usr/src/sys/P2B-S i386
 >Description:
 
 The  FreeBSD  /bin/rm  silently overrides  the  UF_APPEND|UF_IMMUTABLE
 flags when  running as  super user. This  should be documented  in the
 rm(1) manual page.
 
 Since FreeBSD 5.X and later have gotten lchflags(2) support, semantics
 are slightly broken. While standards dictate that rm(1), unlink(2) and
 rename(2)  never follow  symbolic  links, the  FreeBSD /bin/rm  _does_
 sometimes follow symbolic links inside the implicit chflags(2) call.
 
 This leads to the following behaviour:
 (1)	/bin/rm operating as super user cannot remove a symbolic link
 	which has UF_APPEND|UF_IMMUTABLE != 0.
 (2)	/bin/rm when running as super user and failing to unlink a
 	UF_APPEND|UF_IMMUTABLE protected symbolic link will reset the
 	UF_APPEND and UF_IMMUTABLE flags on the symbolic links target
 	- an object that /bin/rm must not change!
 
 Imho (1) is a nuisance while I consider (2) broken behaviour.
 
 /usr/bin/find ... -delete behaves like /bin/rm.
 
 pkg_add has a similar issue when creating backup files.
 
 Finally  /bin/cp  -Rp  should  be  made aware  of  lchflags(2)  (Patch
 fragment below  is similar  to the slightly  more verbose patch  in PR
 bin/90823)
 
 >How-To-Repeat:
 
 su
 touch myfile
 ln -s myfile myslink
 chflags -h uchg myfile myslink
 ls -lo myfile myslink
 rm -f myslink			# fails and modifies myfile instead
 ls -lo myfile myslink
 cp -Rp myslink myslink2		# fails to copy uchg flag (ENOSYS!)
 ls -lo myslink*
 
 >Fix:
 
 Note: When creating the patch below  I was not aware of PR kern/29355.
 It turns out that my patch is  a small subset of the PR 29355 userland
 part.   29355 is  4 years  old now  and most  of its  functionality is
 already  in  the tree.   My  patch catches  up  on  the still  missing
 "s/chflags/lchflags/"-parts. It is against --current.
 
 Index: bin/cp/utils.c
 ===================================================================
 RCS file: /home/ncvs/src/bin/cp/utils.c,v
 retrieving revision 1.46
 diff -u -t -r1.46 utils.c
 --- bin/cp/utils.c	5 Sep 2005 04:36:08 -0000	1.46
 +++ bin/cp/utils.c	5 Jun 2006 10:55:29 -0000
 @@ -321,7 +321,7 @@
          if (!gotstat || fs->st_flags != ts.st_flags)
                  if (fdval ?
                      fchflags(fd, fs->st_flags) :
 -                    (islink ? (errno = ENOSYS) :
 +                    (islink ? lchflags(to.p_path, fs->st_flags) :
                      chflags(to.p_path, fs->st_flags))) {
                          warn("chflags: %s", to.p_path);
                          rval = 1;
 Index: bin/rm/rm.c
 ===================================================================
 RCS file: /home/ncvs/src/bin/rm/rm.c,v
 retrieving revision 1.54
 diff -u -t -r1.54 rm.c
 --- bin/rm/rm.c	15 Apr 2006 09:26:23 -0000	1.54
 +++ bin/rm/rm.c	5 Jun 2006 10:47:38 -0000
 @@ -231,7 +231,7 @@
                          else if (!uid &&
                                   (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                                   !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
 -                                 chflags(p->fts_accpath,
 +                                 lchflags(p->fts_accpath,
                                           p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
                                  goto err;
                          continue;
 @@ -250,7 +250,7 @@
                  if (!uid &&
                      (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                      !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
 -                        rval = chflags(p->fts_accpath,
 +                        rval = lchflags(p->fts_accpath,
                                         p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
                  if (rval == 0) {
                          /*
 @@ -350,7 +350,7 @@
                  if (!uid &&
                      (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                      !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
 -                        rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
 +                        rval = lchflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
                  if (rval == 0) {
                          if (S_ISWHT(sb.st_mode))
                                  rval = undelete(f);
 Index: usr.bin/find/function.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/find/function.c,v
 retrieving revision 1.55
 diff -u -t -r1.55 function.c
 --- usr.bin/find/function.c	3 Apr 2006 20:36:37 -0000	1.55
 +++ usr.bin/find/function.c	5 Jun 2006 11:05:26 -0000
 @@ -439,7 +439,7 @@
          if ((entry->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
              !(entry->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
              geteuid() == 0)
 -                chflags(entry->fts_accpath,
 +                lchflags(entry->fts_accpath,
                         entry->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
  
          /* rmdir directories, unlink everything else */
 Index: usr.sbin/pkg_install/add/extract.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/pkg_install/add/extract.c,v
 retrieving revision 1.44
 diff -u -t -r1.44 extract.c
 --- usr.sbin/pkg_install/add/extract.c	7 Jan 2006 22:10:57 -0000	1.44
 +++ usr.sbin/pkg_install/add/extract.c	5 Jun 2006 12:40:05 -0000
 @@ -63,8 +63,7 @@
          if (q->type == PLIST_FILE) {
              snprintf(try, FILENAME_MAX, "%s/%s", dir, q->name);
              if (make_preserve_name(bup, FILENAME_MAX, name, try) && fexists(bup)) {
 -                (void)chflags(try, 0);
 -                (void)unlink(try);
 +                (void)lchflags(try, 0);
                  if (rename(bup, try))
                      warnx("rollback: unable to rename %s back to %s", bup, try);
              }
 @@ -160,7 +159,7 @@
                  /* first try to rename it into place */
                  snprintf(try, FILENAME_MAX, "%s/%s", Directory, p->name);
                  if (fexists(try)) {
 -                    (void)chflags(try, 0);      /* XXX hack - if truly immutable, rename fails */
 +                    (void)lchflags(try, 0);     /* XXX hack - if truly immutable, rename fails */
                      if (preserve && PkgName) {
                          char pf[FILENAME_MAX];
  
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606071920.k57JKOEi056025>