socket: limit memory allocation when reading from socket

the write limit of libnfs has been 1M since a long time.
Restrict rtmax and wrmax to 1M and error out otherwise.

Limit the PDU size when reading from socket to rule out
malicious servers forcing us to allocate a lot of memory.

Signed-off-by: Peter Lieven <pl@kamp.de>
libnfs-4.0.0-vitalif
Peter Lieven 2015-06-19 13:15:56 +02:00
parent dc70b92dc6
commit 82aec93f12
4 changed files with 25 additions and 2 deletions

View File

@ -74,6 +74,7 @@ struct rpc_queue {
#define HASHES 1024
#define NFS_RA_TIMEOUT 5
#define NFS_MAX_XFER_SIZE (1024 * 1024)
struct rpc_context {
uint32_t magic;

View File

@ -62,8 +62,8 @@ struct rpc_context *rpc_init_context(void)
rpc->magic = RPC_CONTEXT_MAGIC;
/* Allow 1M of data (for writes) and some */
rpc->encodebuflen = 1024 * 1024 + 4096;
/* Allow NFS_MAX_XFER_SIZE of data (for writes) and some */
rpc->encodebuflen = NFS_MAX_XFER_SIZE + 4096;
rpc->encodebuf = malloc(rpc->encodebuflen);
if (rpc->encodebuf == NULL) {
free(rpc);

View File

@ -870,6 +870,22 @@ static void nfs_mount_10_cb(struct rpc_context *rpc, int status, void *command_d
nfs->readmax = res->FSINFO3res_u.resok.rtmax;
nfs->writemax = res->FSINFO3res_u.resok.wtmax;
if (nfs->readmax > NFS_MAX_XFER_SIZE) {
rpc_set_error(rpc, "server max rsize of %lu is greater than libnfs supported %d bytes",
nfs->readmax, NFS_MAX_XFER_SIZE);
data->cb(-EINVAL, nfs, command_data, data->private_data);
free_nfs_cb_data(data);
return;
}
if (nfs->writemax > NFS_MAX_XFER_SIZE) {
rpc_set_error(rpc, "server max wsize of %lu is greater than libnfs supported %d bytes",
nfs->writemax, NFS_MAX_XFER_SIZE);
data->cb(-EINVAL, nfs, command_data, data->private_data);
free_nfs_cb_data(data);
return;
}
memset(&args, 0, sizeof(GETATTR3args));
args.object = nfs->rootfh;

View File

@ -269,6 +269,12 @@ static int rpc_read_from_socket(struct rpc_context *rpc)
}
pdu_size = rpc_get_pdu_size(rpc->inbuf);
if (pdu_size > NFS_MAX_XFER_SIZE + 4096) {
rpc_set_error(rpc, "Incoming PDU exceeds limit of %d bytes.", NFS_MAX_XFER_SIZE + 4096);
return -1;
}
if (rpc->insize < pdu_size) {
rpc->inbuf = realloc(rpc->inbuf, pdu_size);
if (rpc->inbuf == NULL) {