diff --git a/kernel/sys/sys_net.c b/kernel/sys/sys_net.c index 179bf28..b577308 100644 --- a/kernel/sys/sys_net.c +++ b/kernel/sys/sys_net.c @@ -596,6 +596,20 @@ SYSCALL_DEFINE(recvfrom) cap = alen; if (cap > 0 && copy_to_user(uaddr, &sa, (uint64)cap) < 0) return -EFAULT; + } else if (sock_domain(s) == AF_NETLINK) { + // Everything on a netlink socket here comes from the kernel: port id + // 0, no groups. GLib's network monitor checks exactly that before it + // believes a message, and with no address at all it hit an assertion + // and every GNOME program that watches the network aborted. + uint16 nl[6] = { AF_NETLINK, 0, 0, 0, 0, 0 }; + alen = (int)sizeof(nl); + int cap = alen; + if (ulenp && get_user(cap, ulenp) < 0) + return -EFAULT; + if (cap > alen) + cap = alen; + if (cap > 0 && copy_to_user(uaddr, nl, (uint64)cap) < 0) + return -EFAULT; } if (ulenp && copy_to_user(ulenp, &alen, sizeof(alen)) < 0) @@ -1185,6 +1199,15 @@ SYSCALL_DEFINE(recvmsg) alen = m.msg_namelen; if (alen && copy_to_user((addr_t)m.msg_name, &sa, alen) < 0) return -EFAULT; + } else if (sock_domain(s) == AF_NETLINK) { + // The kernel, as in recvfrom above. + uint16 nl[6] = { AF_NETLINK, 0, 0, 0, 0, 0 }; + alen = (uint32)sizeof(nl); + if (alen > m.msg_namelen) + alen = m.msg_namelen; + if (alen && copy_to_user((addr_t)m.msg_name, nl, alen) < 0) + return -EFAULT; + alen = (uint32)sizeof(nl); } if (copy_to_user(umsg + __builtin_offsetof(struct msghdr, msg_namelen), &alen, sizeof(alen)) < 0)