diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2011-01-10 21:35:10 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2011-01-10 21:35:10 +0000 |
commit | 03248b7340e568f9556b9d6bbce82277acf79e4e (patch) | |
tree | a0ebc945c655ec2e171a66354671046c2184315f /sys/rpc | |
parent | ab709a4e92a5f80e9e1c6ae81c13f3f58b0fae6b (diff) | |
download | FreeBSD-src-03248b7340e568f9556b9d6bbce82277acf79e4e.zip FreeBSD-src-03248b7340e568f9556b9d6bbce82277acf79e4e.tar.gz |
Fix a bug in the client side krpc where it was, sometimes
erroneously, assumed that 4 bytes of data were in the first
mbuf of a list by replacing the bcopy() with m_copydata().
Also, replace the uses of m_pullup(), which can fail for
reasons other than not enough data, with m_copydata().
For the cases where it isn't known that there is enough
data in the mbuf list, check first via m_len and m_length().
This is believed to fix a problem reported by dpd at dpdtech.com
and george+freebsd at m5p.com.
Reviewed by: jhb
MFC after: 8 days
Diffstat (limited to 'sys/rpc')
-rw-r--r-- | sys/rpc/clnt_dg.c | 7 | ||||
-rw-r--r-- | sys/rpc/clnt_vc.c | 13 | ||||
-rw-r--r-- | sys/rpc/svc_vc.c | 7 |
3 files changed, 10 insertions, 17 deletions
diff --git a/sys/rpc/clnt_dg.c b/sys/rpc/clnt_dg.c index a01f598..d35a6a9 100644 --- a/sys/rpc/clnt_dg.c +++ b/sys/rpc/clnt_dg.c @@ -1089,15 +1089,14 @@ clnt_dg_soupcall(struct socket *so, void *arg, int waitflag) /* * The XID is in the first uint32_t of the reply. */ - if (m->m_len < sizeof(xid)) - m = m_pullup(m, sizeof(xid)); - if (!m) + if (m->m_len < sizeof(xid) && m_length(m, NULL) < sizeof(xid)) /* * Should never happen. */ continue; - xid = ntohl(*mtod(m, uint32_t *)); + m_copydata(m, 0, sizeof(xid), (char *)&xid); + xid = ntohl(xid); /* * Attempt to match this reply with a pending request. diff --git a/sys/rpc/clnt_vc.c b/sys/rpc/clnt_vc.c index 9699a8d..9882407 100644 --- a/sys/rpc/clnt_vc.c +++ b/sys/rpc/clnt_vc.c @@ -916,7 +916,7 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag) mtx_unlock(&ct->ct_lock); break; } - bcopy(mtod(m, uint32_t *), &header, sizeof(uint32_t)); + m_copydata(m, 0, sizeof(uint32_t), (char *)&header); header = ntohl(header); ct->ct_record = NULL; ct->ct_record_resid = header & 0x7fffffff; @@ -975,14 +975,11 @@ clnt_vc_soupcall(struct socket *so, void *arg, int waitflag) * The XID is in the first uint32_t of * the reply. */ - if (ct->ct_record->m_len < sizeof(xid)) - ct->ct_record = - m_pullup(ct->ct_record, - sizeof(xid)); - if (!ct->ct_record) + if (ct->ct_record->m_len < sizeof(xid) && + m_length(ct->ct_record, NULL) < sizeof(xid)) break; - bcopy(mtod(ct->ct_record, uint32_t *), - &xid, sizeof(uint32_t)); + m_copydata(ct->ct_record, 0, sizeof(xid), + (char *)&xid); xid = ntohl(xid); mtx_lock(&ct->ct_lock); diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index 85d335f..999cad1 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -559,11 +559,8 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg, } if (n < sizeof(uint32_t)) goto readmore; - if (cd->mpending->m_len < sizeof(uint32_t)) - cd->mpending = m_pullup(cd->mpending, - sizeof(uint32_t)); - memcpy(&header, mtod(cd->mpending, uint32_t *), - sizeof(header)); + m_copydata(cd->mpending, 0, sizeof(header), + (char *)&header); header = ntohl(header); cd->eor = (header & 0x80000000) != 0; cd->resid = header & 0x7fffffff; |