Is it possible that my user-space application using the UNIX sockets API would receive an UDP packet that would have the IP TTL value equal to zero, or is it the case that it always has to be one or greater?
Packets will be delivered with TTL >= 1.
The Internet Protocol RFC 760 says "Time to Live: 8 bits [...] If this field contains the value zero, then the datagram should be destroyed." If the router decrements the TTL and finds zero, it should send ICMP TTL expired message to the originator; if there's still any life in the packet it forwards it.
A quick test across two hosts a few routers apart confirms it:
Doesn't arrive with sending TTL 3
$ ping -c 1 -t 3 192.168.0.28 From 192.168.253.0 icmp_seq=1 Time to live exceeded
Does arrive with sending TTL 4
$ ping -c 1 -t 4 192.168.0.28 64 bytes from 192.168.0.28: icmp_req=1 ttl=62 time=51.0 ms
On the receiving end arrives with TTL 1
17:53:19.346312 IP (tos 0x0, ttl 1, id 12703, offset 0, flags [DF], proto ICMP (1), length 84) 172.30.20.88 > 192.168.0.28: ICMP echo request, id 4949, seq 1, length 64