fix potential overflow in nfs_pread_mcb
[deb_libnfs.git] / lib / libnfs.c
index 424a73604581a7f747e1cde1e6871f317d224808..4f0650f41abbe9ccca78bfc7a01fece238b9e706 100644 (file)
@@ -1588,9 +1588,14 @@ static void nfs_pread_mcb(struct rpc_context *rpc, int status, void *command_dat
                        data->error = 1;
                } else  {
                        if (res->READ3res_u.resok.count > 0) {
-                               memcpy(&data->buffer[mdata->offset - data->start_offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count);
-                               if ((unsigned)data->max_offset < mdata->offset + res->READ3res_u.resok.count) {
-                                       data->max_offset = mdata->offset + res->READ3res_u.resok.count;
+                               if (res->READ3res_u.resok.count <= mdata->count) {
+                                       memcpy(&data->buffer[mdata->offset - data->start_offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count);
+                                       if ((unsigned)data->max_offset < mdata->offset + res->READ3res_u.resok.count) {
+                                               data->max_offset = mdata->offset + res->READ3res_u.resok.count;
+                                       }
+                               } else {
+                                       rpc_set_error(nfs->rpc, "NFS: Read overflow. Server has sent more data than requested!");
+                                       data->error = 1;
                                }
                        }
                }
@@ -2732,9 +2737,13 @@ static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_d
        rdpe_cb_data->getattrcount--;
 
        if (status == RPC_STATUS_ERROR) {
+               rpc_set_error(nfs->rpc, "LOOKUP during READDIRPLUS emulation "
+                             "failed with RPC_STATUS_ERROR");
                rdpe_cb_data->status = RPC_STATUS_ERROR;
        }
        if (status == RPC_STATUS_CANCEL) {
+               rpc_set_error(nfs->rpc, "LOOKUP during READDIRPLUS emulation "
+                             "failed with RPC_STATUS_CANCEL");
                rdpe_cb_data->status = RPC_STATUS_CANCEL;
        }
        if (status == RPC_STATUS_SUCCESS && res->status == NFS3_OK) {
@@ -2758,7 +2767,10 @@ static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_d
 
        if (rdpe_cb_data->getattrcount == 0) {
                if (rdpe_cb_data->status != RPC_STATUS_SUCCESS) {
-                       data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
+                       rpc_set_error(nfs->rpc, "READDIRPLUS emulation "
+                             "failed: %s", rpc_get_error(rpc));
+                       data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc),
+                               data->private_data);
                        nfs_free_nfsdir(nfsdir);
                } else {
                        data->cb(0, nfs, nfsdir, data->private_data);