summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2010-04-14 22:02:19 +0000
committerdelphij <delphij@FreeBSD.org>2010-04-14 22:02:19 +0000
commit58be1647f81d964462a1ca747976a7a85714fc0b (patch)
tree90f64aecec4946da4408301a264d15000ddf0f0d
parentd7c34a15b8684c6d9333e40ee8de208dfd3ae3e3 (diff)
downloadFreeBSD-src-58be1647f81d964462a1ca747976a7a85714fc0b.zip
FreeBSD-src-58be1647f81d964462a1ca747976a7a85714fc0b.tar.gz
When an underlying ioctl(2) handler returns an error, our ioctl(2)
interface considers that it hits a fatal error, and will not copyout the request structure back for _IOW and _IOWR ioctls, keeping them untouched. The previous implementation of the SIOCGIFDESCR ioctl intends to feed the buffer length back to userland. However, if we return an error, the feedback would be defeated and ifconfig(8) would trap into an infinite loop. This commit changes SIOCGIFDESCR to set buffer field to NULL to indicate the previous ENAMETOOLONG case. Reported by: bschmidt MFC after: 2 weeks
-rw-r--r--sbin/ifconfig/ifconfig.c23
-rw-r--r--share/man/man4/netintro.49
-rw-r--r--sys/net/if.c7
3 files changed, 21 insertions, 18 deletions
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 7af3306..aa96175 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -922,19 +922,20 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
ifr.ifr_buffer.buffer = descr;
ifr.ifr_buffer.length = descrlen;
if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) {
- if (strlen(descr) > 0)
- printf("\tdescription: %s\n", descr);
- break;
- } else if (errno == ENAMETOOLONG)
- descrlen = ifr.ifr_buffer.length;
- else
- break;
- } else {
+ if (ifr.ifr_buffer.buffer == descr) {
+ if (strlen(descr) > 0)
+ printf("\tdescription: %s\n",
+ descr);
+ } else if (ifr.ifr_buffer.length > descrlen) {
+ descrlen = ifr.ifr_buffer.length;
+ continue;
+ }
+ }
+ } else
warn("unable to allocate memory for interface"
"description");
- break;
- }
- };
+ break;
+ }
if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
if (ifr.ifr_curcap != 0) {
diff --git a/share/man/man4/netintro.4 b/share/man/man4/netintro.4
index 348a13e..3e98940 100644
--- a/share/man/man4/netintro.4
+++ b/share/man/man4/netintro.4
@@ -32,7 +32,7 @@
.\" @(#)netintro.4 8.2 (Berkeley) 11/30/93
.\" $FreeBSD$
.\"
-.Dd January 26, 2010
+.Dd April 14, 2010
.Dt NETINTRO 4
.Os
.Sh NAME
@@ -292,8 +292,11 @@ field of
struct passed in as parameter, and the length would include
the terminating nul character.
If there is not enough space to hold the interface length,
-no copy would be done and an
-error would be returned.
+no copy would be done and the
+.Va buffer
+field of
+.Va ifru_buffer
+would be set to NULL.
The kernel will store the buffer length in the
.Va length
field upon return, regardless whether the buffer itself is
diff --git a/sys/net/if.c b/sys/net/if.c
index e4a2005..98c8afa 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -2049,14 +2049,13 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
case SIOCGIFDESCR:
error = 0;
sx_slock(&ifdescr_sx);
- if (ifp->if_description == NULL) {
- ifr->ifr_buffer.length = 0;
+ if (ifp->if_description == NULL)
error = ENOMSG;
- } else {
+ else {
/* space for terminating nul */
descrlen = strlen(ifp->if_description) + 1;
if (ifr->ifr_buffer.length < descrlen)
- error = ENAMETOOLONG;
+ ifr->ifr_buffer.buffer = NULL;
else
error = copyout(ifp->if_description,
ifr->ifr_buffer.buffer, descrlen);
OpenPOWER on IntegriCloud