This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/12080] New: setsockopt with a group_req argument fails when 32-bit binaries talk to 64-bit kernels
- From: "enh at google dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 1 Oct 2010 21:41:29 -0000
- Subject: [Bug libc/12080] New: setsockopt with a group_req argument fails when 32-bit binaries talk to 64-bit kernels
- Reply-to: sourceware-bugzilla at sourceware dot org
setsockopt MCAST_JOIN_GROUP calls (et cetera) fail with EINVAL when my 32-bit
binary talks to a 64-bit kernel. this is because struct group_req isn't packed.
/tmp$ cat mc.cpp
#include <errno.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
int main() {
struct sockaddr_in addr;
memset (&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr ("239.192.0.1");
int recv_sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (-1 == recv_sock) { perror("socket failed"); return 1; }
struct sockaddr_in recv_addr;
memcpy (&recv_addr, &addr, sizeof(addr));
recv_addr.sin_port = 7500;
socklen_t l = sizeof(recv_addr);
if (0 != bind (recv_sock, (struct sockaddr*)&recv_addr, l)) {
perror("bind failed"); return 1; }
struct group_req gr;
memset (&gr, 0, sizeof(gr));
printf("sizeof(group_req)=%i\n", sizeof(group_req));
printf("offsetof(group_req, gr_interface)=%i\n", offsetof(group_req,
gr_interface));
printf("offsetof(group_req, gr_group)=%i\n", offsetof(group_req, gr_group));
sockaddr_storage ss;
printf("sizeof(ss.ss_family)=%i\n", sizeof(ss.ss_family));
((struct sockaddr*)&gr.gr_group)->sa_family = addr.sin_family;
((struct sockaddr_in*)&gr.gr_group)->sin_addr.s_addr = addr.sin_addr.s_addr;
if (0 != setsockopt (recv_sock, SOL_IP, MCAST_JOIN_GROUP, (const
char*)&gr, sizeof(gr))) { perror("setsockopt failed"); return 1; }
return 0;
}
/tmp$ g++ -m64 mc.cpp -o mc && ./mc
sizeof(group_req)=136
offsetof(group_req, gr_interface)=0
offsetof(group_req, gr_group)=8
sizeof(ss.ss_family)=2
/tmp$ g++ -m32 mc.cpp -o mc && ./mc
sizeof(group_req)=132
offsetof(group_req, gr_interface)=0
offsetof(group_req, gr_group)=4
sizeof(ss.ss_family)=2
setsockopt failed: Invalid argument
/tmp$
i've worked around this by changing my code to recognize EINVAL and try again
with its own fake struct instead
struct group_req64 {
uint32_t gr_interface;
uint32_t my_padding;
sockaddr_storage gr_group;
};
that works, but i wonder if glibc should be doing this for me? i know it does
stuff with statfs/statfs64 and suchlike.
--
Summary: setsockopt with a group_req argument fails when 32-bit
binaries talk to 64-bit kernels
Product: glibc
Version: 2.11
Status: NEW
Severity: normal
Priority: P2
Component: libc
AssignedTo: drepper dot fsp at gmail dot com
ReportedBy: enh at google dot com
CC: glibc-bugs at sources dot redhat dot com
http://sourceware.org/bugzilla/show_bug.cgi?id=12080
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.