Maybe looking at the second question already provides insights of to the first:
So at the end of the loss calculation, there typically is a sum or mean to reduce to the value. If you work out the chain rule for this summation, this is mathematically equivalent to having each of the individual losses backpropagated through.
Turning back to the first question: In addition to differentiating all losses, when you mask things y = mask * x, the chain rule makes the mask to be applied to the gradient, too: dloss/dx = mask * dloss/dy. So there is the mask.
This is also why, when the loss or loss gradient becomes undefined (NaN), you need to use torch.where(mask, x, torch.zeros((), device=x.device, dtype=x.dtype) for masking, else you have mask * NaN = NaN`
Best regards
Thomas