Closed Bug 1589990 Opened 6 years ago Closed 6 years ago

STUN: stun_getifaddrs() can return uninitialised bits which are subsequently used

Categories

(Core :: WebRTC, defect, P2)

defect

Tracking

()

RESOLVED FIXED
mozilla74
Tracking Status
firefox74 --- fixed

People

(Reporter: jseward, Assigned: jseward)

Details

Attachments

(4 files)

media/mtransport/third_party/nICEr/src/stun/addrs.c:

stun_getifaddrs() is used on all non-WIN32 targets. It extracts from the
kernel an array describing network connections, or addresses, or something
like that (doesn't really matter what). These are written into its
out-parameter nr_local_addr addrs[] and the number of entries is written to
int *count.

There is a path through the main loop in stun_getifaddrs() which can cause a
nr_local_addr record to be returned with its .interface.type field being
uninitialized, but which nevertheless is later used. It also looks to me as
if the .interface.estimated_speed field is not initialised.

The path is simple: first this ioctl fails (returns nonzero):
e = ioctl(s, SIOCETHTOOL, &ifr); and then
e = ioctl(s, SIOCGIWRATE, &wrq); also fails.

The uninitialised .interface.type is subsequently used in
nr_local_addr_fmt_info_string():

    int addr_type = addr->interface.type;
    const char *vpn = (addr_type & NR_INTERFACE_TYPE_VPN) ? "VPN on " : "";

    const char *type = (addr_type & NR_INTERFACE_TYPE_WIRED) ? "wired" :
                       (addr_type & NR_INTERFACE_TYPE_WIFI) ? "wifi" :
                       (addr_type & NR_INTERFACE_TYPE_MOBILE) ? "mobile" :
                       "unknown";
Flags: needinfo?(docfaraday)
Attached file badness2.c

Standalone test program extracted from addrs.c, that shows the problem.

I suspect it is for a loopback mount, that both ioctls fail. I confirmed that
they both can fail by adding debug printing.

An obvious fix is to zero out the record we might be about to write to, at
the top of the main loop:

  while (if_addr && *count < maxaddrs) {
    memset(&addrs[*count], 0, sizeof(addrs[*count]));   <-----------

I don't know if 'zero' is a safe fill value for those otherwise-uninitialised
fields, but at least doing this would make it fail repeatably (if it would
have failed anyway), rather than non-deterministically.

A quick scan of stun_get_win32_addrs suggests it doesn't suffer from
the same problem.

Removing needinfo. Not sure why I added it. Sorry for the noise.

Flags: needinfo?(docfaraday)

Would a fix along these lines be appropriate?

Assignee: nobody → jseward
Attachment #9102919 - Flags: feedback?(docfaraday)
Comment on attachment 9102919 [details] [diff] [review] patch for contemplation Review of attachment 9102919 [details] [diff] [review]: ----------------------------------------------------------------- ::: media/mtransport/third_party/nICEr/src/stun/addrs.c @@ +202,5 @@ > hex_hashed_ifname)) > ABORT(r); > > for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) { > + // FIXME should we do this as a defensive measure? My inclination would be to do a single memset over the entire addrs array at the beginning of the function. @@ +271,5 @@ > > if_addr = if_addrs_head; > > while (if_addr && *count < maxaddrs) { > + // Ensure output records are always fully defined. See bug 1589990. Same comment here.
Attachment #9102919 - Flags: feedback?(docfaraday) → feedback+

As it's an ongoing task and I assume that might be landed in this cycle, so mark it as P2.

Priority: -- → P2

In media/mtransport/third_party/nICEr/src/stun/addrs.c:

stun_getifaddrs() is used on all non-WIN32 targets. It extracts from the
kernel an array describing network interfaces (I think). These are written
into its out-parameter nr_local_addr addrs[] and the number of entries is
written to int *count.

There is a path through the main loop in stun_getifaddrs() which can cause a
nr_local_addr record to be returned with its .interface.type field being
uninitialized, but which nevertheless is later used. It also looks as if the
.interface.estimated_speed field is not initialised.

This commit zero-initialises the entire output array before writing anything
into it, to avoid such problems, on all targets.

Pushed by jseward@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/6f33d915fcf5 STUN: stun_getifaddrs() can return uninitialised bits which are subsequently used. r=bwc.
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla74
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: