Subject: bin/4288: mv should use lstat to test source file
To: None <gnats-bugs@gnats.netbsd.org>
From: John F. Woods <jfw@jfwhome.funhouse.com>
List: netbsd-bugs
Date: 10/18/1997 12:35:28
>Number:         4288
>Category:       bin
>Synopsis:       mv should use lstat to test source file
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Oct 18 09:50:02 1997
>Last-Modified:
>Originator:     John F. Woods
>Organization:
Misanthropes-R-Us
>Release:        Sat Oct 11 1997
>Environment:
	
System: NetBSD jfwhome.funhouse.com 1.2G NetBSD 1.2G (JFW) #23: Sat Oct 11 20:51:17 EDT 1997 jfw@jfwhome.funhouse.com:/usr/src/sys/arch/i386/compile/JFW i386


>Description:
	I tried moving a symlink (whose permission bits were 644) across file
systems.  mv failed with "permission denied", ultimately because it thought it
wanted to stat() the file pointed to rather than lstat()ing the link itself,
even though it was going to move the link.

>How-To-Repeat:
	From mail to current-users:
(from a directory on another disk separate from /u)
$ ln -s /u/jfw/Mail/inbox/7777 @
$ ls -l @
lrwxr-xr-x  1 jfw  wheel  22 Oct 18 11:57 @ -> /u/jfw/Mail/inbox/7777
$ mv @ ~

OK.

$ rm ~/@
$ ln -s /u/jfw/Mail/inbox/7777 @ 
$ chmod -h 666 @
$ mv @ ~
mv: @: Permission denied

Since when does mv require execute permission to move a file???
(note: this is a cross-device "mv", so it's really a cp followed by
rm, as was recently beaten to death by, uh, someone.  :-)  I don't
think I see where this is happening, either; a really cursory glance
through the code indicates that readlink checks the read permission,
not execute.  (Unless namei() won't even touch a no-execute symlink?)

Ah.  mv does a stat() to find out what the from file is, and that is
failing.  It should probably do an lstat() since if it is moving a
symbolic link (which will work because cp is told not to follow them),
it is irrelevant what the modes on the target file are.
	
>Fix:
*** mv.c.orig	Thu Oct  9 07:33:49 1997
--- mv.c	Sat Oct 18 12:29:53 1997
***************
*** 229,235 ****
  	 * (5)	The file hierarchy rooted in source_file shall be duplicated
  	 *	as a file hiearchy rooted in the destination path...
  	 */
! 	if (stat(from, &sb)) {
  		warn("%s", from);
  		return (1);
  	}
--- 229,235 ----
  	 * (5)	The file hierarchy rooted in source_file shall be duplicated
  	 *	as a file hiearchy rooted in the destination path...
  	 */
! 	if (lstat(from, &sb)) {
  		warn("%s", from);
  		return (1);
  	}
>Audit-Trail:
>Unformatted: