lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1283920965.2634.723.camel@edumazet-laptop>
Date:	Wed, 08 Sep 2010 06:42:45 +0200
From:	Eric Dumazet <eric.dumazet@...il.com>
To:	David Miller <davem@...emloft.net>
Cc:	brian.haley@...com, ole@....pl, netdev@...r.kernel.org
Subject: Re: [PATCH] inet: dont set inet_rcv_saddr in connect()

Le mardi 07 septembre 2010 à 20:34 -0700, David Miller a écrit :
> From: Brian Haley <brian.haley@...com>
> Date: Tue, 07 Sep 2010 22:34:59 -0400
> 
> > Is this really the right thing to do?  Linux has been doing this forever,
> > right?  Just like BSD has done it forever.
> 
> Indeed, I checked for this in Stevens volume 2 when I reviewed
> Eric's patch, the logic is identical.
> 
> > The way I've always "cleared" a local address is to set the address
> > family to AF_UNSPEC on the next connect() call, as mentioned on the
> > man page.  I just want to make sure we're not changing something
> > just to work around a broken application, sendto()/sendmsg() work
> > perfect in this case by not setting the local address.
> > 

Problem is AF_UNSPEC always clears the remote address (as stated in
manual), and sometimes local one (as not stated)

if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
	inet_reset_saddr(sk);

This is the workaround that was coded years ago in Linux to undo the
local addr setting ;)


Following program produces this output :

local addr=0x7f000001 sin_port=37877
after connect(AF_UNSPEC) local addr=0x0 sin_port=0
local addr=0x7f000001 sin_port=37877
after connect(AF_UNSPEC) local addr=0x7f000001 sin_port=0



#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
	int fd;
	struct sockaddr_in target, me;
	socklen_t len;

	if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
		perror("socket");
		return 1;
	}
	memset(&target, 0, sizeof(target));
	target.sin_family = AF_INET;
	target.sin_port = 123;
	target.sin_addr.s_addr = htonl(0x7f000001);
	if (connect(fd, (const struct sockaddr *)&target, sizeof(target)) == -1) {
		perror("connect");
		close(fd);
		return 2;
	}
	len = sizeof(me);
	if (getsockname(fd, (struct sockaddr *)&me, &len)== -1) {
		perror("getsockname");
		close(fd);
		return 3;
	}
	printf("local addr=0x%x sin_port=%u\n",
		ntohl(me.sin_addr.s_addr), ntohs(me.sin_port));
	memset(&target, 0, sizeof(target));
	target.sin_family = AF_UNSPEC;
	if (connect(fd, (const struct sockaddr *)&target, sizeof(target)) == -1) {
		perror("connect AF_UNSPEC");
		close(fd);
		return 4;
	}	
	len = sizeof(me);
	if (getsockname(fd, (struct sockaddr *)&me, &len)== -1) {
		perror("getsockname 2");
		close(fd);
		return 3;
	}
	printf("after connect(AF_UNSPEC) local addr=0x%x sin_port=%u\n",
		ntohl(me.sin_addr.s_addr), ntohs(me.sin_port));
	memset(&target, 0, sizeof(target));
	target.sin_family = AF_INET;
	target.sin_addr.s_addr = htonl(0x7f000001);
	if (bind(fd, (const struct sockaddr *)&target, sizeof(target)) == -1) {
		perror("bind");
		close(fd);
		return 2;
	}
	len = sizeof(me);
	if (getsockname(fd, (struct sockaddr *)&me, &len)== -1) {
		perror("getsockname");
		close(fd);
		return 3;
	}
	printf("local addr=0x%x sin_port=%u\n",
		ntohl(me.sin_addr.s_addr), ntohs(me.sin_port));

	memset(&target, 0, sizeof(target));
	target.sin_family = AF_UNSPEC;
	if (connect(fd, (const struct sockaddr *)&target, sizeof(target)) == -1) {
		perror("connect AF_UNSPEC");
		close(fd);
		return 4;
	}	

	len = sizeof(me);
	if (getsockname(fd, (struct sockaddr *)&me, &len)== -1) {
		perror("getsockname 2");
		close(fd);
		return 3;
	}
	printf("after connect(AF_UNSPEC) local addr=0x%x sin_port=%u\n",
		ntohl(me.sin_addr.s_addr), ntohs(me.sin_port));
	return 0;
}



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ