From timon@memphis.mephi.ru  Thu Jan 31 03:26:40 2002
Return-Path: <timon@memphis.mephi.ru>
Received: from memphis.mephi.ru (memphis.mephi.ru [194.67.67.234])
	by hub.freebsd.org (Postfix) with ESMTP id 04BAB37B402
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 31 Jan 2002 03:26:29 -0800 (PST)
Received: (from timon@localhost)
	by memphis.mephi.ru (8.11.6/8.11.3) id g0VBQNp55541;
	Thu, 31 Jan 2002 14:26:23 +0300 (MSK)
	(envelope-from timon)
Message-Id: <200201311126.g0VBQNp55541@memphis.mephi.ru>
Date: Thu, 31 Jan 2002 14:26:23 +0300 (MSK)
From: "Artem 'Zazoobr' Ignatjev" <timon@memphis.mephi.ru>
Reply-To: "Artem 'Zazoobr' Ignatjev" <timon@memphis.mephi.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: wrong execv() call in amd for ${mount} and ${unmount} if mount type:=program in amd.map 
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         34483
>Category:       bin
>Synopsis:       wrong execv() call in amd for ${mount} and ${unmount} if mount type:=program in amd.map
>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:   Thu Jan 31 03:30:02 PST 2002
>Closed-Date:    Sat Feb 2 07:55:39 PST 2002
>Last-Modified:  Sat Feb 02 07:58:34 PST 2002
>Originator:     Artem 'Zazoobr' Ignatjev
>Release:        FreeBSD 4.4-RELEASE i386
>Organization:
Moscow Engineering-Physical Institute (MEPhI)
>Environment:
System: FreeBSD memphis.mephi.ru 4.4-RELEASE FreeBSD 4.4-RELEASE #3: Sun Nov 18 00:46:03 MSK 2001 root@:/usr/src/sys/compile/LOCAL i386

>Description:
	amd(4) is a daemon which automatically mounts filesystems whenever a file or directory 
within that filesystem is accessed.
	The 'program' filesystem type (type:=program) allows a program to be run whenever a
mount or unmount of filesystem is requested.
	However, the following code from contrib/amd/amd/amfs_program.c (from /usr/src/ hierarchy)
makes that somewhat tricky:

$Id: amfs_program.c,v 1.5 1999/09/30 21:01:30 ezk Exp $

(line 116) static int
amfs_program_exec(char *info)
{
  char **xivec;
  int error;

  /*
   * Split copy of command info string
   */
  info = strdup(info);
  if (info == 0)
    return ENOBUFS;
  xivec = strsplit(info, ' ', '\'');
  /*
   * Put stdout to stderr
   */
/* ... skip ... */
(line 156) if (xivec[0] == 0 || xivec[1] == 0) {
    errno = EINVAL;
    plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
  } else {
    (void) execv(xivec[0], xivec + 1);
  }

Notice the line in `else' clause: it calls program xivec[0],  giving it 
arguments (INCLUDING argv[0] which supposed to be program name) since xivec[1], of course, 
this don't works, and called program `looses' its first argument. 

Also, no docs from contrib/amd/doc, written in tex/texi are neither formatted nor installed 
in /usr/share ierarchy ( I was unsuccessful trying to find formatted docs, at least)

>How-To-Repeat:
To check that, try adding this line to your amd.map:

test	type:=program;mount:="/usr/bin/logger request to mount ${path}";unmount:="/usr/bin/logger trying to unmount ${path}"

then reload map using killall (as root) 
killall -1 amd

 and then try to chdir to the 'test' directory in toplevel directory for amd (/mnt in my case)
cd /mnt/test

This will cause amd(8) to try mount the "test" directory by calling the ${mount} program, which
is supposed to be `/usr/bin/logger request to mount /mnt/test', where "/mnt/test" is the value of
${path} variable, but will fail, since execv(2) will look as follows:
execv("/usr/bin/logger", {"request", "to", "mount", "/mnt/test"})
and program is expected to be run by
execv("/usr/bin/logger", {"/usr/bin/logger", "request", "to", "mount", "/mnt/test"})
>Fix:

--- contrib/amd/amd/amfs_program.c.orig	
+++ contrib/amd/amd/amfs_program.c	
@@ -155,11 +155,11 @@
 
   if (xivec[0] == 0 || xivec[1] == 0) {
     errno = EINVAL;
     plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
   } else {
-    (void) execv(xivec[0], xivec + 1);
+    (void) execv(xivec[0], xivec);
   }
 
   /*
    * Save error number
    */
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: roam 
State-Changed-When: Thu Jan 31 03:35:28 PST 2002 
State-Changed-Why:  
amd is contributed software, as witnessed by the sources' location 
in the contrib/ section of the FreeBSD source tree.  As per the FreeBSD 
policy regarding contributed software, and as per the specific instructions 
in the src/contrib/amd/FREEBSD-upgrade file, local changes should be kept 
down to a minumum, and all proposed changes should be sent to the amd 
maintainers at <amd-dev@majordomo.cs.columbia.edu> for inclusion 
in a future release.  Thus, the changes would be cleanly imported into FreeBSD 
at the import of the next release, and there would be no conflicts 
in future imports. 

Could you verify if the change you are proposing (which looks fine to me 
personally, and therefore should also look fine to the amd maintainers) 
would not be accepted by the amd developers, so it can be cleanly imported 
into FreeBSD?  If it is, and if it is accepted exactly as in your patch, 
it would even be possible to commit it to FreeBSD before the next import, 
as it will be cleanly "swallowed" at import time. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=34483 

From: Peter Pentchev <roam@ringlet.net>
To: Artem 'Zazoobr' Ignatjev <timon@memphis.mephi.ru>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/34483: wrong execv() call in amd for ${mount} and ${unmount} if mount type:=program in amd.map
Date: Thu, 31 Jan 2002 13:48:18 +0200

 And just as a minor followup to my comments in the open->feedback
 state change, I have checked the amd sources and the same bug is
 present in the most recent version, am-utils-6.0.7.
 
 G'luck,
 Peter
 
 -- 
 No language can express every thought unambiguously, least of all this one.

From: "Artem 'Zazoobr' Ignatjev" <timon@memphis.mephi.ru>
To: freebsd-gnats-submit@freebsd.org
Cc:  
Subject: Re: bin/34483: wrong execv() call in amd for ${mount} and ${unmount} if mount type:=program in amd.map
Date: Sat, 2 Feb 2002 13:38:28 +0300 (MSK)

 Hi.
 Here is reply from author, Erez Zadok (from amd-dev <amd-dev@cs.columbia.edu> mailing list):
 
 > From ezk@shekel.mcl.cs.columbia.edu Sat Feb  2 07:11:08 2002
 > Date: Fri, 1 Feb 2002 23:11:02 -0500 (EST)
 > From: Erez Zadok <ezk@cs.columbia.edu>
 > To: "Artem 'Zazoobr' Ignatjev" <timon@memphis.mephi.ru>
 > Cc: amd-dev@cs.columbia.edu
 > Subject: Re: wrong execv() call for ${mount} and ${unmount} if mount type:=program in amd.map 
 > I don't think that's a bug.  The mount:= variable in amd requires special
 > syntax that's a little different than an argv[] list.  If the command to
 > mount something is, say, "mount /this /here", then you have to specify the
 > map entry as
 >
 > 	type:=program;mount:="/etc/mount mount /this /here"
 >
 > IOW, you also list the program name's full path (here etc/mount) in the list
 > of args to the program type's mount:= variable.
 >
 > That has been the syntax for amd's program type since the beginning.  It's a
 > source of unfortunate confusion to programmers who are used to think that
 > it's just an argv[] list.  It's not.
 > Erez.
 
 But I still think, that in case of hardlinks, this patch will work, and all man have to do 
 is to write the correct path in map; in other cases there could be no possibility to mount
 filesystem "by hands", without writing shell script/tiny program, which will call exec...() on
 one path, giving argv[0] with other prog's name.
 
 			Wishes & regards, Artem.

From: Peter Pentchev <roam@ringlet.net>
To: Artem 'Zazoobr' Ignatjev <timon@memphis.mephi.ru>
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/34483: wrong execv() call in amd for ${mount} and ${unmount} if mount type:=program in amd.map
Date: Sat, 2 Feb 2002 17:00:18 +0200

 On Sat, Feb 02, 2002 at 02:40:02AM -0800, Artem 'Zazoobr' Ignatjev wrote:
 >  Hi.
 >  Here is reply from author, Erez Zadok (from amd-dev <amd-dev@cs.columbia.edu> mailing list):
 >  
 [snip]
 >  > 	type:=program;mount:="/etc/mount mount /this /here"
 [snip]
 >  > It's a
 >  > source of unfortunate confusion to programmers who are used to think that
 >  > it's just an argv[] list.  It's not.
 >  
 >  But I still think, that in case of hardlinks, this patch will work, and all man have to do 
 >  is to write the correct path in map; in other cases there could be no possibility to mount
 >  filesystem "by hands", without writing shell script/tiny program, which will call exec...() on
 >  one path, giving argv[0] with other prog's name.
 
 Actually, I now believe Erez to be correct - I no longer think this is a bug.
 What he is trying to say is that you should provide argv[0] along with
 the other arguments, *after* the path to the program.  This allows you
 to execute a program, giving it an argv[0] different from the filename
 of the executable file - exactly the same way that inetd.conf's syntax
 allows you to do the same.  This is done to minimize the need for
 hardlinks, as you say; even without a hardlink, you are able to invoke,
 say, /sbin/mount as either 'mount' or 'mount_ffs' or 'mount_msdosfs' or
 whatever else you like.
 
 Just take a look at inetd.conf: it will illustrate this perfectly:
 
 ftp	stream	tcp	nowait	root	/usr/libexec/ftpd	ftpd -l
 
 This is equivalent to amd's syntax of:
 
 type:=program;mount:="/usr/libexec/ftpd ftpd -l"
 
 IOW, invoke the program executable file /usr/libexec/ftpd, and pass
 it an argv[] list of argv[0]="ftpd", argv[1]="-l", argv[2]=NULL.
 
 If you do not wish to invoke programs with names other than their
 executable files' names, you just have to provide the program name
 twice, as in:
 
 type:=program;mount:="mount mount blah"
 
 ..though this is both unusable and insecure (think PATH).  In an ideal
 case, you would provide a full path to the executable and just a name
 for the program, as in:
 
 type:=program;mount:="/sbin/mount mount blah"
 
 Can you provide an example of an executable/program name, which can NOT
 be handled by this scheme?  If not, I think this PR should be closed..
 Still, thanks for your effort to improve FreeBSD by filing a report on
 what you believed was a genuine problem!
 
 G'luck,
 Peter
 
 -- 
 Peter Pentchev		roam@ringlet.net	roam@FreeBSD.org
 Hey, out there - is it *you* reading me, or is it someone else?

From: "Artem 'Zazoobr' Ignatjev" <timon@memphis.mephi.ru>
To: roam@ringlet.net, timon@memphis.mephi.ru
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/34483: wrong execv() call in amd for ${mount} and ${unmount} if mount type:=program in amd.map
Date: Sat, 2 Feb 2002 18:36:55 +0300 (MSK)

 > From roam@straylight.ringlet.net Sat Feb  2 18:21:17 2002
 > Date: Sat, 2 Feb 2002 17:00:18 +0200
 > From: Peter Pentchev <roam@ringlet.net>
 > To: "Artem 'Zazoobr' Ignatjev" <timon@memphis.mephi.ru>
 > Cc: bug-followup@FreeBSD.org
 > Subject: Re: bin/34483: wrong execv() call in amd for ${mount} and ${unmount} if mount type:=program in amd.map
 >
 > Actually, I now believe Erez to be correct - I no longer think this is a bug.
 > What he is trying to say is that you should provide argv[0] along with
 > the other arguments, *after* the path to the program.  This allows you
 > to execute a program, giving it an argv[0] different from the filename
 > of the executable file - exactly the same way that inetd.conf's syntax
 > allows you to do the same.  This is done to minimize the need for
 > hardlinks, as you say; even without a hardlink, you are able to invoke,
 > say, /sbin/mount as either 'mount' or 'mount_ffs' or 'mount_msdosfs' or
 > whatever else you like.
 Yeah, I found description of this in _info am-utils_... So this pr should be closed, or
 something
 
State-Changed-From-To: feedback->closed 
State-Changed-By: roam 
State-Changed-When: Sat Feb 2 07:55:39 PST 2002 
State-Changed-Why:  
The originator agrees that the amd syntax allows both the executable 
image name and the argv[0] array to be specified unambiguously. 
Still, thank you for reporting what you considered a genuine problem! 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=34483 
>Unformatted:
