Subject: bin/30188: cp copies permissions of setuid source to existing destination without -p
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <jld@panix.com>
List: netbsd-bugs
Date: 05/10/2005 22:36:00
>Number:         30188
>Category:       bin
>Synopsis:       cp copies permissions of setuid source to existing destination without -p
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue May 10 22:36:00 +0000 2005
>Originator:     Jed Davis
>Release:        NetBSD 2.0.2
>Organization:
Public Access Networks Corp.
>Environment:
System: NetBSD byzantium.nyc.access.net 2.0.2 NetBSD 2.0.2 (PANIX-STAFF) #0: Thu May  5 21:13:35 EDT 2005  root@juggler.panix.com:/devel/netbsd/2.0.2/src/sys/arch/i386/compile/PANIX-STAFF i386
Architecture: i386
Machine: i386
>Description:

See the how-to-repeat section for an example.  The code responsible is
in src/bin/cp/utils.c, lines 184-200 in r1.27; the purpose of that being
apparently to handle setuid bits safely.  However, it seems to me that,
if pflag==0, then there's no point to any of this and it should all
be skipped --- rather than skipping only the setfile() and proceeding
into the tests for the source's having been set[ug]id and the ensuing
fchmod().  Christos added, on tech-userlevel:

} cp without -p when executed by root is supposed to copy the
} permissions when the file is being created, but not when the file
} already exists. At least this is what solaris and linux do.


>How-To-Repeat:

  hostname# ls -l /dev/null                       
  crw-rw-rw-  1 root  wheel  2, 2 May  9 18:33 /dev/null
  hostname# cp /usr/libexec/ssh-keysign /dev/null
  hostname# ls -l /dev/null                      
  cr-sr-xr-x  1 root  wheel  2, 2 May  9 23:25 /dev/null

>Fix:

Changing line 184 to something like 

	if (pflag || (dne && my_uid == 0)) {
		if (setfile(fs, to_fd))

and then closing that on what will be line 202 (and fixing the
indentation &c) seems like it'd do what Christos speaks of, while also
preventing the setuid-/dev/null problem.