Skip to content

init_sockaddr() calls freeaddrinfo() on an uninitialized pointer when resolution fails #611

Description

@somethingwithproof

init_sockaddr() declares hostinfo without initializing it, then calls freeaddrinfo() on it from every getaddrinfo() failure path. POSIX leaves *res unspecified when getaddrinfo() returns an error, so on failure the function frees whatever the stack happened to hold.

ping.c:984 on develop:

int init_sockaddr(struct sockaddr_in *name, const char *hostname, unsigned short int port) {
	struct addrinfo hints, *hostinfo;      /* never initialized */
	int rv, retry_count;
	...
	rv = getaddrinfo(hostname, NULL, &hints, &hostinfo);

	if (rv == 0) {
		break;
	} else {
		switch (rv) {
			case EAI_AGAIN:
				...
				if (hostinfo != NULL) {     /* indeterminate */
					freeaddrinfo(hostinfo);
				}

Five paths do this: EAI_AGAIN twice (lines 1005 and 1014), EAI_FAIL (1023), EAI_MEMORY (1031), and default (1039).

The EAI_AGAIN retry at 1005 is the most reachable. It frees, then continues around the loop for up to three more attempts, so a device whose name is temporarily unresolvable can hit it repeatedly within one call.

init_sockaddr() is called from the ICMP, UDP and TCP ping paths (ping.c:438, 693, 856), once per device per poll cycle for any device configured by hostname. Reaching the bug needs a resolution failure, which is an ordinary condition when a nameserver is slow or a device name is stale.

Present on develop (line 984) and 1.2.x (line 890).

Fix

Initialize hostinfo to NULL at the declaration, and drop the freeaddrinfo() calls on paths where getaddrinfo() allocated nothing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions