Over-fetching is fetching too much data. There is data in the reponse you don't use.
Under-fetching is not having enough data with one call to an endpoint, leading you to call a second endpoint.
In both cases, they are performances issues : you either use more bandwidth than you should, or you are making more HTTP requests that you should.
GraphQL fixes this problem because it allows access to an arbitrary set of data exposed by the server. You specifically specify what you need and will get this data, and only this data, in one trip to the server.