Non c'è bisogno di definire una variabile "puntatore a puntatore", basta fare una cosa del genere

codice:
inserisci_dati(&p0);
lasciando p0 dichiarato così com'è. Chiaramente andranno modificati i prototipi delle funzioni

codice:
void inserisci_dati(struct elemento **);
void inserisci_ordinatamente(struct elemento **, struct elemento *);
void stampa_lista(struct elemento *);
così come nelle intestazioni delle funzioni stesse. Nota che per la funzione di stampa non c'è bisogno di passare un puntatore a puntatore, in quanto non lo devi modificare.

Chiaramente se ridefinisci il parametro p0 come "struct elemento **p0" nelle funzioni, dovrai andare a sostituire (*p0) ad ogni occorrenza di p0. Tra l'altro ti anticipo già che al secondo inserimento da un segmentation fault, quindi ricontrolla come fai gli aggiornamenti e se hai problemi posta :)

Giusto per fare un esempio, con le modifiche che ti ho consigliato se provi ad inserire un solo elemento (perché al secondo crasha, come ti dicevo) per poi interrompere l'immissione, ottieni correttamente la stampa di quel valore.