Yes, you need to synchronize framebuffer updates to happen so that the framebuffer area is not updated by your code while that area of framebuffer is being drawn on screen.
Port 03DAh has bit 3 signalling the vertical sync. Whenever that bit is low, assume that the visible area of the screen is being drawn. When that bit is high, the vertical sync period is ongoing and framebuffer data can be updated safely.
So have your code wait for 03DAh bit 3 to become low, and then wait for that bit to go high, and then update the framebuffer.
In C-like pseudocode which is not optimized for simplicity:
while( (inportb(0x03DA) & 0x08) == 0x08);
while( (inportb(0x03DA) & 0x08) == 0x00);
However not many virtual machine environments properly emulate VGA vertical sync at this level, as their intended purpose is not to run games or graphical software which directly use VGA ports.
You might have better luck with emulators intended for this, such as DOSBox, PCEm, or the like.