From vaidab@phenix.rootshell.be  Tue Nov  1 18:20:04 2005
Return-Path: <vaidab@phenix.rootshell.be>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 1375916A41F
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  1 Nov 2005 18:20:04 +0000 (GMT)
	(envelope-from vaidab@phenix.rootshell.be)
Received: from phenix.rootshell.be (phenix.rootshell.be [217.22.55.50])
	by mx1.FreeBSD.org (Postfix) with ESMTP id AA44943D4C
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  1 Nov 2005 18:20:03 +0000 (GMT)
	(envelope-from vaidab@phenix.rootshell.be)
Received: by phenix.rootshell.be (Postfix, from userid 55646)
	id 9C6641798C; Tue,  1 Nov 2005 19:20:02 +0100 (CET)
Received: from localhost (localhost [127.0.0.1])
	by phenix.rootshell.be (Postfix) with ESMTP id 9783817989;
	Tue,  1 Nov 2005 19:20:02 +0100 (CET)
Message-Id: <Pine.LNX.4.62.0511011916560.13183@phenix.rootshell.be>
Date: Tue, 1 Nov 2005 19:20:01 +0100 (CET)
From: vaidab <vaidab@phenix.rootshell.be>
To: FreeBSD-gnats-submit@freebsd.org
Cc: vaida.bogdan@gmail.com
Subject: "/bin/rm -P" cannot remove files not writeable by user while
 "/bin/rm" can

>Number:         88365
>Category:       bin
>Synopsis:       [patch] rm(1): "/bin/rm -P" cannot remove files not writeable by user while "/bin/rm" can
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 01 18:30:19 GMT 2005
>Closed-Date:    Fri Mar 30 16:48:28 GMT 2007
>Last-Modified:  Fri Mar 30 16:48:28 GMT 2007
>Originator:     Vaida Bogdan
>Release:        FreeBSD 5.4-RELEASE-p8 i386
>Organization:
>Environment:
 System: FreeBSD angelique.ro 5.4-RELEASE-p8 FreeBSD 5.4-RELEASE-p8 #22: Thu Oct 20 09:37:06 UTC 2005 root@angelique.ro:/usr/obj/usr/src/sys/ANGELIQUE i386
>Description:

 "/bin/rm -P" cannot remove files not writeable by user while "/bin/rm" can
 
          The patch will chmod the file "u+w" and then remove it.
 
> How-To-Repeat:
          $ touch 1; chmod 0 1; ls -l 1
          ----------  1 vaidab  vaidab  0 Sep 26 22:59 1
          $ /bin/rm -P 1
          rm: 1: Permission denied
          $ /bin/rm 1
          override r--r--r--  vaidab/vaidab for 1? y
          $ ls -l 1
          $ ls: 1: No such file or directory
 
> Fix:
 
 --- /usr/src/bin/rm/rm.c.orig   Sun Sep 26 22:23:02 2004
 +++ /usr/src/bin/rm/rm.c        Mon Sep 27 10:00:50 2004
 @@ -384,6 +384,8 @@
          }
          if (!S_ISREG(sbp->st_mode))
                  return (1);
 +       if (lchmod(file, S_IWUSR) == -1)
 +               goto err;
          if ((fd = open(file, O_WRONLY, 0)) == -1)
                  goto err;
          if (fstatfs(fd, &fsb) == -1)
 @@ -441,7 +443,7 @@
                   * we will not be able to overwrite file contents and will
                   * barf later.
                   */
 -               if (!stdin_ok || S_ISLNK(sp->st_mode) || Pflag ||
 +               if (!stdin_ok || S_ISLNK(sp->st_mode) ||
                      (!access(name, W_OK) &&
                      !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
                      (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid)))
 
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: gnats-admin->freebsd-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Tue Nov 1 19:43:33 GMT 2005 
Responsible-Changed-Why:  
Rescue this PR from the 'pending' category. 

To submitter: whatever submission mechanism you are using to send PRs is 
not working out very well.  Please try an alternate. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=88365 

From: vaidab <vaidab@phenix.rootshell.be>
To: bug-followup@FreeBSD.org
Cc: vaida.bogdan@gmail.com
Subject: Re: bin/88365 : [patch] rm(1): "/bin/rm -P" cannot remove files not
 writeable by user while "/bin/rm" can
Date: Sun, 6 Nov 2005 10:14:07 +0100 (CET)

 I'm submitting the patch again. mx1.freebsd.org rejects me as I don't have 
 a hostname and my send-pr are sent via email
 
 > Fix:
 
 --- /usr/src/bin/rm/rm.c.orig	Thu Nov  3 21:19:47 2005
 +++ /usr/src/bin/rm/rm.c	Thu Nov  3 21:20:42 2005
 @@ -393,6 +393,8 @@
   	}
   	if (!S_ISREG(sbp->st_mode))
   		return (1);
 +	if (lchmod(file, S_IWUSR) == -1)
 +		goto err;
   	if ((fd = open(file, O_WRONLY, 0)) == -1)
   		goto err;
   	if (fstatfs(fd, &fsb) == -1)
 @@ -450,7 +452,7 @@
   		 * we will not be able to overwrite file contents and will
   		 * barf later.
   		 */
 -		if (!stdin_ok || S_ISLNK(sp->st_mode) || Pflag ||
 +		if (!stdin_ok || S_ISLNK(sp->st_mode) ||
   		    (!access(name, W_OK) &&
   		    !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
   		    (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid)))

Adding to audit trail from misfiled PR bin/98532:

[Note: submitter' mailer changed all the tabs to escape characters, and
and thus the patch is useless; submitter was asked for feedback]

Date: Mon, 05 Jun 2006 17:16:24 +0200
From: "Bakk.techn., Martin Kammerhofer" <dada@sbox.tugraz.at>

=09The FreeBSD /bin/rm silently overrides the UF_APPEND|UF_IMMUTABLE
=09flags when running as super user. This should be documented
=09in the rm(1) manual page.

=09Since FreeBSD 5.X and later have gotten lchflags(2) support, semantics
=09are slightly broken. While standards dictate that rm(1), unlink(2) and
=09rename(2) never follow symbolic links, the FreeBSD /bin/rm _does_
=09sometimes follow symbolic links inside the implicit chflags(2) call.

=09This leads to the following behaviour:
=09(1)=09/bin/rm operating as super user cannot remove a symbolic link
=09=09which has UF_APPEND|UF_IMMUTABLE !=3D 0.
=09(2)=09/bin/rm when running as super user and failing to unlink a
=09=09UF_APPEND|UF_IMMUTABLE protected symbolic link will reset the
=09=09UF_APPEND and UF_IMMUTABLE flags on the symbolic links target
=09=09- an object that /bin/rm must not change!

=09Imho (1) is a nuisance while I consider (2) broken behaviour.

=09/usr/bin/find ... -delete behaves like /bin/rm.

=09pkg_add has a similar issue when creating backup files.

=09Finally /bin/cp -Rp should be made aware of lchflags(2)
=09(Patch fragment below is similar to the slightly more verbose
=09patch in PR bin/90823)

=09su
=09touch myfile
=09ln -s myfile myslink
=09chflags -h uchg myfile myslink
=09ls -lo myfile myslink
=09rm -f myslink=09=09=09# fails and modifies myfile instead
=09ls -lo myfile myslink
=09cp -Rp myslink myslink2=09=09# fails to copy uchg flag (ENOSYS!)
=09ls -lo myslink*

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 29355=C2=B4s userland part.
29355 is 4 years old now and most of its functionality is already in the tre=
e.
My patch catches up on the still missing "s/chflags/lchflags/"-parts.

Index: bin/cp/utils.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
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=095 Sep 2005 04:36:08 -0000=091.46
+++ bin/cp/utils.c=095 Jun 2006 10:55:29 -0000
@@ -321,7 +321,7 @@
         if (!gotstat || fs->st_flags !=3D ts.st_flags)
                 if (fdval ?
                     fchflags(fd, fs->st_flags) :
-                    (islink ? (errno =3D ENOSYS) :
+                    (islink ? lchflags(to.p_path, fs->st_flags) :
                     chflags(to.p_path, fs->st_flags))) {
                         warn("chflags: %s", to.p_path);
                         rval =3D 1;
Index: bin/rm/rm.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
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=0915 Apr 2006 09:26:23 -0000=091.54
+++ bin/rm/rm.c=095 Jun 2006 10:47:38 -0000
@@ -231,7 +231,7 @@
                         else if (!uid &&
                                  (p->fts_statp->st_flags & (UF_APPEND|UF_IM=
MUTABLE)) &&
                                  !(p->fts_statp->st_flags & (SF_APPEND|SF_I=
MMUTABLE)) &&
-                                 chflags(p->fts_accpath,
+                                 lchflags(p->fts_accpath,
                                          p->fts_statp->st_flags &=3D ~(UF_A=
PPEND|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 =3D chflags(p->fts_accpath,
+                        rval =3D lchflags(p->fts_accpath,
                                        p->fts_statp->st_flags &=3D ~(UF_APP=
END|UF_IMMUTABLE));
                 if (rval =3D=3D 0) {
                         /*
@@ -350,7 +350,7 @@
                 if (!uid &&
                     (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                     !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
-                        rval =3D chflags(f, sb.st_flags & ~(UF_APPEND|UF_IM=
MUTABLE));
+                        rval =3D lchflags(f, sb.st_flags & ~(UF_APPEND|UF_I=
MMUTABLE));
                 if (rval =3D=3D 0) {
                         if (S_ISWHT(sb.st_mode))
                                 rval =3D undelete(f);
Index: usr.bin/find/function.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
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=093 Apr 2006 20:36:37 -0000=091.55
+++ usr.bin/find/function.c=095 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() =3D=3D 0)
-                chflags(entry->fts_accpath,
+                lchflags(entry->fts_accpath,
                        entry->fts_statp->st_flags &=3D ~(UF_APPEND|UF_IMMUT=
ABLE));
=20
         /* rmdir directories, unlink everything else */
Index: usr.sbin/pkg_install/add/extract.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
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=097 Jan 2006 22:10:57 -0000=091.44
+++ usr.sbin/pkg_install/add/extract.c=095 Jun 2006 12:40:05 -0000
@@ -63,8 +63,7 @@
         if (q->type =3D=3D 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 immu=
table, rename fails */
+                    (void)lchflags(try, 0);     /* XXX hack - if truly immu=
table, rename fails */
                     if (preserve && PkgName) {
                         char pf[FILENAME_MAX];
=20

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];
  
 
State-Changed-From-To: open->closed 
State-Changed-By: le 
State-Changed-When: Fri Mar 30 16:47:06 UTC 2007 
State-Changed-Why:  
Duplicate of bin/72124.  The submitter of the misfiled PR whose patch 
was attached to this one was asked to file the PR again to avoid 
confusion. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=88365 
>Unformatted:
