Subject: bin/9385: Bug in /usr/bin/Mail conflicts with Hesiod passwd source
To: None <gnats-bugs@gnats.netbsd.org>
From: Geoff Adams <gadams@avernus.com>
List: netbsd-bugs
Date: 02/10/2000 00:24:49
>Number:         9385
>Category:       bin
>Synopsis:       mail defines a function send() that conflicts with system's send()
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Feb 10 00:24:00 2000
>Last-Modified:
>Originator:     Geoff Adams
>Organization:
	
>Release:        19990210
>Environment:
	
System: NetBSD heisenberg.avernus.com 1.4P NetBSD 1.4P (HEISENBERG) #0: Tue Dec 7 00:14:40 EST 1999 gadams@heisenberg.avernus.com:/build/netbsd/sys/arch/sparc/compile/HEISENBERG sparc


>Description:
	
The file usr.bin/mail/send.c defines a function send() (here is its prototype
in usr.bin/mail/extern.h):

  int      send __P((struct message *, FILE *, struct ignoretab *, char *));

that is used throughout the program.  This function overrides the normal
send(2) system call wrapper found in libc.  This has been fine, until the
introduction of nsswitch.  Now, it's possible to have network sources for
password entries.

If the passwd map in /etc/nsswitch.conf is set to "dns" (and probably
"nis" as well), then as soon as Mail does a lookup of any password entry,
which it does in functions in getname.c while starting up, the Hesiod
lookup routines try to call send(2), but instead end up calling Mail's
send().  The arguments clash horribly, and we end up with a core dump.
>How-To-Repeat:
	
1.  Replace any existing passwd line in /etc/nsswitch.conf with this one:

passwd:         dns [notfound=return] files

2.  It may be neccessary to have an /etc/hesiod.conf file.  If so, try
this one:

rhs=.netbsd.org
lhs=.ns
classes=HS

3.  Invoke Mail:

/usr/bin/Mail

4.  Observe the core dump.
>Fix:
	
The following trivial patch against today's source fixes the problem.


Index: cmd1.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/mail/cmd1.c,v
retrieving revision 1.12
diff -c -r1.12 cmd1.c
*** cmd1.c	1999/02/09 04:51:30	1.12
--- cmd1.c	2000/02/10 08:05:05
***************
*** 349,355 ****
  		dot = mp;
  		if (value("quiet") == NOSTR)
  			fprintf(obuf, "Message %d:\n", *ip);
! 		(void) send(mp, obuf, doign ? ignore : 0, NOSTR);
  	}
  close_pipe:
  	if (obuf != stdout) {
--- 349,355 ----
  		dot = mp;
  		if (value("quiet") == NOSTR)
  			fprintf(obuf, "Message %d:\n", *ip);
! 		(void) sendmessage(mp, obuf, doign ? ignore : 0, NOSTR);
  	}
  close_pipe:
  	if (obuf != stdout) {
Index: cmd2.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/mail/cmd2.c,v
retrieving revision 1.9
diff -c -r1.9 cmd2.c
*** cmd2.c	1998/12/19 16:31:41	1.9
--- cmd2.c	2000/02/10 08:05:08
***************
*** 203,209 ****
  	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  		mp = &message[*ip - 1];
  		touch(mp);
! 		if (send(mp, obuf, ignore, NOSTR) < 0) {
  			perror(file);
  			Fclose(obuf);
  			return(1);
--- 203,209 ----
  	for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  		mp = &message[*ip - 1];
  		touch(mp);
! 		if (sendmessage(mp, obuf, ignore, NOSTR) < 0) {
  			perror(file);
  			Fclose(obuf);
  			return(1);
Index: collect.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/mail/collect.c,v
retrieving revision 1.19
diff -c -r1.19 collect.c
*** collect.c	1999/02/17 20:48:48	1.19
--- collect.c	2000/02/10 08:05:11
***************
*** 641,647 ****
  
  		touch(mp);
  		printf(" %d", *msgvec);
! 		if (send(mp, fp, ig, tabst) < 0) {
  			perror(tempMail);
  			return(-1);
  		}
--- 641,647 ----
  
  		touch(mp);
  		printf(" %d", *msgvec);
! 		if (sendmessage(mp, fp, ig, tabst) < 0) {
  			perror(tempMail);
  			return(-1);
  		}
Index: extern.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/mail/extern.h,v
retrieving revision 1.10
diff -c -r1.10 extern.h
*** extern.h	1998/10/08 17:36:55	1.10
--- extern.h	2000/02/10 08:05:11
***************
*** 224,230 ****
  int	 schdir __P((void *));
  int	 screensize __P((void));
  int	 scroll __P((void *));
! int	 send __P((struct message *, FILE *, struct ignoretab *, char *));
  int	 sendmail __P((void *));
  int	 set __P((void *));
  int	 setfile __P((char *));
--- 224,230 ----
  int	 schdir __P((void *));
  int	 screensize __P((void));
  int	 scroll __P((void *));
! int	 sendmessage __P((struct message *, FILE *, struct ignoretab *, char *));
  int	 sendmail __P((void *));
  int	 set __P((void *));
  int	 setfile __P((char *));
Index: quit.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/mail/quit.c,v
retrieving revision 1.10
diff -c -r1.10 quit.c
*** quit.c	1997/12/07 21:27:10	1.10
--- quit.c	2000/02/10 08:05:13
***************
*** 275,281 ****
  	}
  	for (mp = &message[0]; mp < &message[msgCount]; mp++)
  		if (mp->m_flag & MBOX)
! 			if (send(mp, obuf, saveignore, NOSTR) < 0) {
  				perror(mbox);
  				Fclose(ibuf);
  				Fclose(obuf);
--- 275,281 ----
  	}
  	for (mp = &message[0]; mp < &message[msgCount]; mp++)
  		if (mp->m_flag & MBOX)
! 			if (sendmessage(mp, obuf, saveignore, NOSTR) < 0) {
  				perror(mbox);
  				Fclose(ibuf);
  				Fclose(obuf);
***************
*** 404,410 ****
  	for (mp = &message[0]; mp < &message[msgCount]; mp++)
  		if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
  			p++;
! 			if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) {
  				perror(mailname);
  				Fclose(obuf);
  				return(-1);
--- 404,410 ----
  	for (mp = &message[0]; mp < &message[msgCount]; mp++)
  		if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
  			p++;
! 			if (sendmessage(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) {
  				perror(mailname);
  				Fclose(obuf);
  				return(-1);
***************
*** 525,531 ****
  		if ((mp->m_flag & MDELETED) != 0)
  			continue;
  		c++;
! 		if (send(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) {
  			perror(mailname);
  			relsesigs();
  			reset(0);
--- 525,531 ----
  		if ((mp->m_flag & MDELETED) != 0)
  			continue;
  		c++;
! 		if (sendmessage(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) {
  			perror(mailname);
  			relsesigs();
  			reset(0);
Index: send.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/mail/send.c,v
retrieving revision 1.10
diff -c -r1.10 send.c
*** send.c	1998/12/19 16:34:38	1.10
--- send.c	2000/02/10 08:05:14
***************
*** 59,65 ****
   * prefix is a string to prepend to each output line.
   */
  int
! send(mp, obuf, doign, prefix)
  	struct message *mp;
  	FILE *obuf;
  	struct ignoretab *doign;
--- 59,65 ----
   * prefix is a string to prepend to each output line.
   */
  int
! sendmessage(mp, obuf, doign, prefix)
  	struct message *mp;
  	FILE *obuf;
  	struct ignoretab *doign;
>Audit-Trail:
>Unformatted: