Bug 31704 - sin_zero field & bind problems
Summary: sin_zero field & bind problems
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 4.4-RELEASE
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2001-11-02 07:50 UTC by Valentin Nechayev
Modified: 2002-10-23 10:10 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Valentin Nechayev 2001-11-02 07:50:01 UTC
If bind() syscall is called for PF_INET socket with address another than
INADDR_ANY, and sin_zero field in addr parameter is not filled with
zero (this is common programming problem), bind() will fail.
Source of failure is ifa_ifwithaddr() in src/sys/net/if.c, which compares
structure contents for all their length (determined from sa_len field).
ifa_ifwithaddr() is called by in_pcbbind(), which performs all work
of comparing addresses and ports.

Stevens' examples performs zero-filling before use. But I never
saw an _explicit_ rule to perform such filling in any official manual.
(Later, I was pointed to chapter in FreeBSD Developers' Handbook, but I
don't know any programmer near me who read this document! - all study on
real code, or Stevens, or russian books.)
During last month, I saw 4 complaints to opaque and misunderstandable
behavior of FreeBSD kernel in this place - 2 from Usenet and 2 from
my workmates; in each case, complainer was totally confused: he fills
all described fields - sin_family, sin_port and sin_addr - and what hell? ;|
The needed fix is too simple, and I supposed it is better to apply it once,
than continue to confuse people. That's why I also consider this as
software bug, and tagged this report as sw-bug, not change-request.

There was a small discussion in freebsd-hackers began by me (at 13-14 Oct
2001). There were quite different opinions, but I support one said by John
Polstra and Vladimir Dozen that Posix and Single Unix Specification does not
require zero-filling neither in general not for this specific structure.
This also leads me to consider this problem as software bug, because porting
of applications conformed to SUS meets yet another hard-understood and
hard-diagnosed rake.

Another occurences found with Google:

Letter to freebsd-current from Mike Smith, 11/25/1997 20:31:19,

PR kern/9309 by ru@

NetBSD PR kern/2972

Fix: Fill sin_zero before testing of address structure instead interface address
list. This fix successfully tested by me. AFAIS it is applicable to all
FreeBSD versions.



/netch--uIFKBv248IPO44Ya5ilrH0pjtA2z7iGsjK3Wq2DaBWW8NjoW
Content-Type: text/plain; name="file.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="file.diff"

--- src/sys/netinet/in_pcb.c.0	Sat Sep 22 17:41:17 2001
+++ src/sys/netinet/in_pcb.c	Sat Sep 22 17:44:59 2001
@@ -198,6 +198,7 @@
 		sin = (struct sockaddr_in *)nam;
 		if (nam->sa_len != sizeof (*sin))
 			return (EINVAL);
+		bzero(&sin->sin_zero, sizeof(sin->sin_zero));
 #ifdef notdef
 		/*
 		 * We should check the family, but old programs
How-To-Repeat: 
#define FILLER 0xDE

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <stdio.h>
#include <string.h>

int main() {
  int s;
  struct sockaddr_in sia;
  s = socket( PF_INET, SOCK_STREAM, 0 );
  if( s == -1 )  err( 1, "socket()" );
  memset( &sia, FILLER, sizeof sia );
  sia.sin_family = AF_INET;
  sia.sin_port = htons( 4455 );
  sia.sin_addr.s_addr = htonl( 0x7f000001 );
  if( bind( s, ( struct sockaddr* ) &sia, sizeof sia ) < 0 )
    err( 1, "bind()" );
  puts( "all ok" );
  return 0;
}

With any FILLER value other than 0, bind() will fail with EADDRNOTAVAIL.
Also note than sin_len field is refilled in getsockaddr(), and garbage
in it in userland copy does not matter.
Comment 1 arr freebsd_committer freebsd_triage 2001-11-06 00:49:17 UTC
State Changed
From-To: open->closed

Revision 1.92 fixes the issue.  Thanks for re-bringing this up.
Comment 2 Maxim Konovalov freebsd_committer freebsd_triage 2002-10-23 10:01:10 UTC
Also fixed in rev. 1.59.2.25 src/sys/netinet/in_pcb.c in 4.7-STABLE.

-- 
Maxim Konovalov, maxim@FreeBSD.org