diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2019-01-21 12:27:31 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-01-22 08:25:25 +0100 |
commit | 47c87c4098d19592982cd44d356e0f82f48e0639 (patch) | |
tree | a97f9c8517c19318939784cdd1a29af9cef32cce /fs | |
parent | 9d929c6f4b5ed7d9b7be7ef874c8523a52719c81 (diff) | |
download | barebox-47c87c4098d19592982cd44d356e0f82f48e0639.tar.gz barebox-47c87c4098d19592982cd44d356e0f82f48e0639.tar.xz |
fs/nfs: copy data from rpc replies to local storage
The nfs code uses data provided to the packet handler after net_poll()
returned. But the life time of this data already ended when net_poll()
returns. Most of the time it is possible to get away here but on i.MX28
the data is overwritten since commit 82ec28929cc9 ("net: fec_imx: Do not
use DMA coherent memory for Rx buffers").
So the data from the packet is copied to a malloced buffer that needs
free()ing when the data is not used any more.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs.c | 31 |
1 files changed, 26 insertions, 5 deletions
@@ -440,7 +440,6 @@ again: nfs_timer_start = get_time_ns(); nfs_state = STATE_START; - nfs_packet = NULL; while (nfs_state != STATE_DONE) { if (ctrlc()) { @@ -459,8 +458,10 @@ again: ret = rpc_check_reply(nfs_packet, rpc_prog, npriv->rpc_id, &nfserr); if (!ret) { - if (rpc_prog == PROG_NFS) + if (rpc_prog == PROG_NFS && nfserr) { + free(nfs_packet); ret = nfserr; + } break; } } @@ -489,6 +490,9 @@ static int rpc_lookup_req(struct nfs_priv *npriv, uint32_t prog, uint32_t ver) return ret; port = ntoh32(net_read_uint32(nfs_packet + sizeof(struct rpc_reply))); + + free(nfs_packet); + return port; } @@ -658,11 +662,14 @@ static int nfs_mount_req(struct nfs_priv *npriv) if (npriv->rootfh.size > NFS3_FHSIZE) { printf("%s: file handle too big: %lu\n", __func__, (unsigned long)npriv->rootfh.size); + free(nfs_packet); return -EIO; } memcpy(npriv->rootfh.data, p, npriv->rootfh.size); p += DIV_ROUND_UP(npriv->rootfh.size, 4); + free(nfs_packet); + return 0; } @@ -675,6 +682,7 @@ static void nfs_umount_req(struct nfs_priv *npriv) uint32_t *p; int len; int pathlen; + int ret; pathlen = strlen(npriv->path); @@ -685,7 +693,9 @@ static void nfs_umount_req(struct nfs_priv *npriv) len = p - &(data[0]); - rpc_req(npriv, PROG_MOUNT, MOUNT_UMOUNT, data, len); + ret = rpc_req(npriv, PROG_MOUNT, MOUNT_UMOUNT, data, len); + if (!ret) + free(nfs_packet); } /* @@ -753,6 +763,8 @@ static int nfs_lookup_req(struct nfs_priv *npriv, struct nfs_fh *fh, nfs_read_post_op_attr(p, inode); + free(nfs_packet); + return 0; } @@ -831,6 +843,7 @@ static void *nfs_readdirattr_req(struct nfs_priv *npriv, struct nfs_dir *dir) len = nfs_packet + nfs_len - (void *)p; if (!len) { printf("%s: huh, no payload left\n", __func__); + free(nfs_packet); return NULL; } @@ -838,6 +851,8 @@ static void *nfs_readdirattr_req(struct nfs_priv *npriv, struct nfs_dir *dir) memcpy(buf, p, len); + free(nfs_packet); + xdr_init(&dir->stream, buf, len); /* now xdr points to dirlist3 res.resok.reply */ @@ -912,11 +927,15 @@ static int nfs_read_req(struct file_priv *priv, uint64_t offset, */ p += 2; - if (readlen && !rlen && !eof) + if (readlen && !rlen && !eof) { + free(nfs_packet); return -EIO; + } kfifo_put(priv->fifo, (char *)p, rlen); + free(nfs_packet); + return 0; } @@ -925,7 +944,7 @@ static void nfs_handler(void *ctx, char *packet, unsigned len) char *pkt = net_eth_to_udp_payload(packet); nfs_state = STATE_DONE; - nfs_packet = pkt; + nfs_packet = xmemdup(pkt, len); nfs_len = len; } @@ -992,6 +1011,8 @@ static int nfs_readlink_req(struct nfs_priv *npriv, struct nfs_fh *fh, *target = xzalloc(len + 1); memcpy(*target, p, len); + free(nfs_packet); + return 0; } |