| Summary: | [if_mib] Failure to check for existence of interface in if_mib.c | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Base System | Reporter: | brandt <brandt> | ||||
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> | ||||
| Status: | Closed FIXED | ||||||
| Severity: | Affects Only Me | ||||||
| Priority: | Normal | ||||||
| Version: | 5.0-CURRENT | ||||||
| Hardware: | Any | ||||||
| OS: | Any | ||||||
| Attachments: |
|
||||||
Responsible Changed From-To: freebsd-bugs->fenner I fixed if_mib.c; leaving the PR open to remind me to look for others. State Changed From-To: open->suspended The orginal failure was fixed but the same bad code might lurk elsewhere. At least there shouldn't be any problems with ifaddr_byindex() because there's only one user of it now exists in the tree, and it's working right. Cheers, -- Ruslan Ermilov ru@FreeBSD.org FreeBSD committer Responsible Changed From-To: fenner->freebsd-bugs fenner has handed in his commit bit. State Changed From-To: suspended->closed ru@ claimed this had been fixed long ago. |
if_mib.c:sysctl_ifdata fails to check whether the accessed interface really exists. The problem is, that since the advent of loadable modules the interface index name space may be sparse. Before loadable modules one was sure that all interfaces between 1 and if_index really exists so the check if (name[0] <= 0 || name[0] > if_index) was ok. Now it is possible to unload interface drivers so that interfaces between 1 and if_index may disappear. ifaddr_byindex(IDX) will return NULL in this case which in turn leads to a kernel panic. There may be other places in the kernel that also build on the old assumption. How-To-Repeat: Put 2 network cards in your computer which need different drivers. Build these drivers as loadable modules and reboot. Now configure the two interfaces. Now unload the driver for the first interface and execute the test program below: # include "stdio.h" # include "err.h" # include "sys/types.h" # include "sys/sysctl.h" # include "sys/socket.h" # include "net/if.h" # include "net/if_mib.h" int main(int argc, char *argv[]) { int name[6]; size_t len; name[0] = CTL_NET; name[1] = PF_LINK; name[2] = NETLINK_GENERIC; name[3] = IFMIB_IFDATA; name[4] = 4; name[5] = IFDATA_LINKSPECIFIC; if (sysctl(name, 6, NULL, &len, NULL, 0) < 0) { err(1, "sysctl failed"); return (1); } return (0); } Watch the kernel panic.