NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/49247: getsockname(2) requires sockaddr structure to cleared



>Number:         49247
>Category:       kern
>Synopsis:       getsockname(2) requires sockaddr structure to cleared
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Sep 30 08:35:00 +0000 2014
>Originator:     Takahiro Kambe
>Release:        NetBSD 7.0_BETA
>Organization:
Takahiro Kambe
>Environment:
	
	
System: NetBSD edge.back-street.net 7.0_BETA NetBSD 7.0_BETA (VMWARE-F6) #2: Sat Sep 13 08:53:11 JST 2014 taca%edge.back-street.net@localhost:/data/amd64/obj/sys/arch/amd64/compile/VMWARE-F6 amd64
Architecture: x86_64
Machine: amd64
>Description:
	getsockname(2) requires sockaddr structure to zero cleared when
	passing UNIX domain socket.  On NetBSD 6.1_STABLE, no such
	assumeption was needed.

	And it break lmtp support of dovecot2.

>How-To-Repeat:
	Here is a simple sample program.  Executing without argument,
	storange output on NetBSD 7.0_BETA.

% ./a.out
18: /var/tmp/socktest0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
18: /var/tmp/socktest1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

	With some argument or execute on NetBSD 6.1_STABLE,

% ./a.out foo
18: /var/tmp/socktest0
18: /var/tmp/socktest1

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <err.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define UPATH	"/var/tmp/socktest"
#define N	2

int
make_sock(char *path)
{
	int fd;
	struct sockaddr_un un;

	fd = socket(PF_LOCAL, SOCK_STREAM, 0);
	if (fd < 0)
		err(EXIT_FAILURE, "socket");

	un.sun_family = AF_UNIX;
	strcpy(un.sun_path, path);
	un.sun_len = SUN_LEN(&un);

	(void)unlink(path);
	if (bind(fd, (struct sockaddr *)&un, sizeof un))
		err(EXIT_FAILURE, "bind");
	return fd;
}

int
main(int argc, char *argv[])
{
	int i, n, clear, fd[N];
	struct sockaddr_un *run;
	struct sockaddr_storage ss;
	socklen_t len;
	char buf[BUFSIZ];

	clear = (argc > 1)? 1: 0;

	n = N;
	for (i = 0; i < n; i++) {
		sprintf(buf, "%s%d", UPATH, i);
		fd[i] = make_sock(buf);
	}

	for (i = 0; i < n; i++) {
		if (clear)
			memset(&ss, 0, sizeof ss);
		else
			memset(&ss, 'a', sizeof ss);
		run = (struct sockaddr_un *)&ss;
		len = sizeof *run;

		if (getsockname(fd[i], (struct sockaddr *)run, &len))
			err(EXIT_FAILURE, "getsockname");

		printf("%d: %s\n", len - 2, run->sun_path);
	}
	return EXIT_SUCCESS;
}

>Fix:
	Unknown.  Workaround is make user program to clear sockaddr
	structure before calling getsockname(2).

	And I don't check in the case of getpeername(2).

>Unformatted:
 	
 	


Home | Main Index | Thread Index | Old Index