diff options
author | Brooks Davis <brooks@FreeBSD.org> | 2004-09-15 04:41:56 +0000 |
---|---|---|
committer | Brooks Davis <brooks@FreeBSD.org> | 2004-09-15 04:41:56 +0000 |
commit | c859ef977e347c7dd2a1086f0f1809838300eec0 (patch) | |
tree | b532f0fccfa8b8b1e679621ae637757365f14d89 /sys/net/if_clone.c | |
parent | e8807f22f9383f9a5f3a86fb6dbe77efb5beade6 (diff) | |
download | src-c859ef977e347c7dd2a1086f0f1809838300eec0.tar.gz src-c859ef977e347c7dd2a1086f0f1809838300eec0.zip |
Fix a LOR where copyout was called while holding a lock.
Reported by: rwatson
Notes
Notes:
svn path=/head/; revision=135256
Diffstat (limited to 'sys/net/if_clone.c')
-rw-r--r-- | sys/net/if_clone.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c index 04c54bdd069f..7a519ee452d5 100644 --- a/sys/net/if_clone.c +++ b/sys/net/if_clone.c @@ -235,9 +235,24 @@ if_clone_free(struct if_clone *ifc) int if_clone_list(struct if_clonereq *ifcr) { - char outbuf[IFNAMSIZ], *dst; + char *buf, *dst, *outbuf = NULL; struct if_clone *ifc; - int count, err = 0; + int buf_count, count, err = 0; + + IF_CLONERS_LOCK(); + /* + * Set our internal output buffer size. We could end up not + * reporting a cloner that is added between the unlock and lock + * below, but that's not a major problem. Not caping our + * allocation to the number of cloners actually in the system + * could be because that would let arbitrary users cause us to + * allocate abritrary amounts of kernel memory. + */ + buf_count = (if_cloners_count < ifcr->ifcr_count) ? + if_cloners_count : ifcr->ifcr_count; + IF_CLONERS_UNLOCK(); + + outbuf = malloc(IFNAMSIZ*buf_count, M_CLONE, M_WAITOK | M_ZERO); IF_CLONERS_LOCK(); @@ -252,19 +267,21 @@ if_clone_list(struct if_clonereq *ifcr) goto done; } - count = (if_cloners_count < ifcr->ifcr_count) ? - if_cloners_count : ifcr->ifcr_count; + count = (if_cloners_count < buf_count) ? + if_cloners_count : buf_count; - for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0; - ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) { - strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ); - err = copyout(outbuf, dst, IFNAMSIZ); - if (err) - break; + for (ifc = LIST_FIRST(&if_cloners), buf = outbuf; + ifc != NULL && count != 0; + ifc = LIST_NEXT(ifc, ifc_list), count--, buf += IFNAMSIZ) { + strlcpy(buf, ifc->ifc_name, IFNAMSIZ); } done: IF_CLONERS_UNLOCK(); + if (err == 0) + err = copyout(outbuf, dst, buf_count*IFNAMSIZ); + if (outbuf != NULL) + free(outbuf, M_CLONE); return (err); } |