diff --git a/share/libc/sys/socket.c b/share/libc/sys/socket.c
index ca4cf1c5b5590b5e399d550e9c14fc4d493d2ed7..e1cfd553a5ad4d178dc01466e84416192b5b8063 100644
--- a/share/libc/sys/socket.c
+++ b/share/libc/sys/socket.c
@@ -90,15 +90,14 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
     // non-error
     ((char*)buf)[Frama_C_interval(0, len-1)] = Frama_C_interval(0, 255);
     if (addrbuf) {
-      // simulate writing source address
-      socklen_t addrlen = *addrbuf_len > sizeof(struct sockaddr) ? *addrbuf_len : sizeof(struct sockaddr);
-      Frama_C_make_unknown((char*)addrbuf, addrlen);
+      Frama_C_make_unknown((char*)addrbuf, *addrbuf_len);
       /* From the "Linux Programmer's Manual:
          "Upon return, 'addrbuf_len' is updated to contain the actual size of
          the source address. The returned address is truncated if the buffer
          provided is too small; in this case, 'addrbuf_len' will return a value
-         greater than was supplied to the call. */
-      *addrbuf_len = addrlen;
+         greater than was supplied to the call."
+         Here we use _SS_MAXSIZE as the maximum address struct size. */
+      *addrbuf_len = Frama_C_unsigned_int_interval(0, _SS_MAXSIZE);
     }
     return Frama_C_long_interval(0, len);
   }
diff --git a/share/libc/sys/socket.h b/share/libc/sys/socket.h
index 93472efdd30dd2fe3a621c2cb9aa53d54bbcbfd6..5885125caafe53c8d88ffdb47095ed3a97f7d89a 100644
--- a/share/libc/sys/socket.h
+++ b/share/libc/sys/socket.h
@@ -42,8 +42,12 @@ typedef __UINT_LEAST32_T socklen_t;
 #include "../__fc_define_ssize_t.h"
 #include "../features.h"
 
+// Non-POSIX; value taken from Linux implementation
+#define _SS_MAXSIZE 128
+
 struct sockaddr_storage {
   sa_family_t   ss_family;
+  char __sa_data[_SS_MAXSIZE - sizeof(sa_family_t)]; /* non-POSIX */
 };
 
 #include "./uio.h"