Package: ulogd Version: 1.24-3 Severity: normal Hi,
attached a more usable patch that fixes the 64bit kernel -> 32bit userspace problem as well as the unaligned access. Conversion from 64bit to 32bit is hardcoded to i386 and sparc and needs to be made dynamically. But I have no idea how to test for that. MfG Goswin -- System Information: Debian Release: squeeze/sid APT prefers unstable APT policy: (500, 'unstable'), (499, 'unstable') Architecture: amd64 (x86_64) Kernel: Linux 2.6.31.6-xen-2010.02.18 (SMP w/4 CPU cores) Locale: LANG=C, LC_CTYPE=de_DE (charmap=ISO-8859-1) Shell: /bin/sh linked to /bin/bash Versions of packages ulogd depends on: ii debconf [debconf-2.0] 1.5.28 Debian configuration management sy ii libc6 2.10.2-6 Embedded GNU C Library: Shared lib ii lsb-base 3.2-23 Linux Standard Base 3.2 init scrip ulogd recommends no packages. Versions of packages ulogd suggests: pn ulogd-mysql <none> (no description available) pn ulogd-pcap <none> (no description available) pn ulogd-pgsql <none> (no description available) pn ulogd-sqlite3 <none> (no description available) -- debconf information excluded
Description: Changes required to handle alignment, padding and bitness This patch changes the struct ulog_packet_msg_t type to fix problems with the alignment, padding and bitness. . On several architectures access to memory must be aligned. Unaligned access results in slower code, kernel traps or termination of the programm. In the kernel struct ulog_packet_msg_t the payload is not aligned to be used as struct iphdr. . On several architectures one can have a 64bit kernel with 32bit userspace. The kernel struct ulog_packet_msg_t has different offsets for its members due to different size of long and size_t and differences in padding. . The patch still hardcodes that i386 and sparc need to convert from 64bit kernel to 32bit userspace while all other arch only fix the alignment issues. This needs to be done dynamically depnding on the running kernel and for all 32bit archs that support 64bit kernel. Author: Goswin von Brederlow <goswin-...@web.de> Bug-Debian: http://bugs.debian.org/265985 Last-Update: 2010-04-06 Index: ulogd-1.24/ulogd.c =================================================================== --- ulogd-1.24.orig/ulogd.c 2010-04-06 05:24:26.000000000 +0200 +++ ulogd-1.24/ulogd.c 2010-04-06 05:24:35.000000000 +0200 @@ -421,7 +421,7 @@ /* call all registered interpreters and hand the results over to * propagate_results */ -static void handle_packet(ulog_packet_msg_t *pkt) +static void handle_packet(ulog_packet_msg_aligned_t *pkt) { ulog_iret_t *ret; ulog_iret_t *allret = NULL; @@ -659,7 +659,7 @@ struct passwd *pw; uid_t uid = 0; gid_t gid = 0; - ulog_packet_msg_t *upkt; + ulog_packet_msg_aligned_t *upkt; ulog_output_t *p; @@ -815,6 +815,7 @@ libulog_buf, len))) { DEBUGP("==> packet received\n"); handle_packet(upkt); + free(upkt); } } } Index: ulogd-1.24/extensions/ulogd_BASE.c =================================================================== --- ulogd-1.24.orig/extensions/ulogd_BASE.c 2010-04-06 05:24:25.000000000 +0200 +++ ulogd-1.24/extensions/ulogd_BASE.c 2010-04-06 05:24:30.000000000 +0200 @@ -32,6 +32,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/socket.h> #include <netinet/ip.h> #include <netinet/in.h> @@ -59,7 +60,7 @@ }; static ulog_iret_t *_interp_raw(ulog_interpreter_t *ip, - ulog_packet_msg_t *pkt) + ulog_packet_msg_aligned_t *pkt) { unsigned char *p; int i; @@ -83,7 +84,7 @@ } /* include pointer to raw ipv4 packet */ - ret[1].value.ptr = pkt->payload; + ret[1].value.ptr = pkt->data[0].raw; ret[1].flags |= ULOGD_RETF_VALID; ret[2].value.ui32 = pkt->data_len; ret[2].flags |= ULOGD_RETF_VALID; @@ -123,7 +124,7 @@ }; static ulog_iret_t *_interp_oob(struct ulog_interpreter *ip, - ulog_packet_msg_t *pkt) + ulog_packet_msg_aligned_t *pkt) { ulog_iret_t *ret = ip->result; @@ -200,11 +201,10 @@ }; static ulog_iret_t *_interp_iphdr(struct ulog_interpreter *ip, - ulog_packet_msg_t *pkt) + ulog_packet_msg_aligned_t *pkt) { ulog_iret_t *ret = ip->result; - struct iphdr *iph = (struct iphdr *) pkt->payload; - + struct iphdr *iph = &pkt->data[0].iph; ret[0].value.ui32 = ntohl(iph->saddr); ret[0].flags |= ULOGD_RETF_VALID; ret[1].value.ui32 = ntohl(iph->daddr); @@ -304,9 +304,9 @@ }; static ulog_iret_t *_interp_tcphdr(struct ulog_interpreter *ip, - ulog_packet_msg_t *pkt) + ulog_packet_msg_aligned_t *pkt) { - struct iphdr *iph = (struct iphdr *) pkt->payload; + struct iphdr *iph = &pkt->data[0].iph; void *protoh = (u_int32_t *)iph + iph->ihl; struct tcphdr *tcph = (struct tcphdr *) protoh; ulog_iret_t *ret = ip->result; @@ -378,9 +378,9 @@ }; static ulog_iret_t *_interp_udp(struct ulog_interpreter *ip, - ulog_packet_msg_t *pkt) + ulog_packet_msg_aligned_t *pkt) { - struct iphdr *iph = (struct iphdr *) pkt->payload; + struct iphdr *iph = &pkt->data[0].iph; void *protoh = (u_int32_t *)iph + iph->ihl; struct udphdr *udph = protoh; ulog_iret_t *ret = ip->result; @@ -436,9 +436,9 @@ }; static ulog_iret_t *_interp_icmp(struct ulog_interpreter *ip, - ulog_packet_msg_t *pkt) + ulog_packet_msg_aligned_t *pkt) { - struct iphdr *iph = (struct iphdr *) pkt->payload; + struct iphdr *iph = &pkt->data[0].iph; void *protoh = (u_int32_t *)iph + iph->ihl; struct icmphdr *icmph = protoh; ulog_iret_t *ret = ip->result; @@ -489,12 +489,12 @@ }; static ulog_iret_t *_interp_ahesp(struct ulog_interpreter *ip, - ulog_packet_msg_t *pkt) + ulog_packet_msg_aligned_t *pkt) { ulog_iret_t *ret = ip->result; #if 0 - struct iphdr *iph = (struct iphdr *) pkt->payload; + struct iphdr *iph = &pkt->data[0].iph; void *protoh = (u_int32_t *) (iph + iph->ihl); struct esphdr *esph = protoh; Index: ulogd-1.24/include/ulogd/ulogd.h =================================================================== --- ulogd-1.24.orig/include/ulogd/ulogd.h 2010-04-06 05:24:25.000000000 +0200 +++ ulogd-1.24/include/ulogd/ulogd.h 2010-04-06 05:24:30.000000000 +0200 @@ -93,7 +93,7 @@ unsigned int id; /* function to call for each packet */ ulog_iret_t* (*interp)(struct ulog_interpreter *ip, - ulog_packet_msg_t *pkt); + ulog_packet_msg_aligned_t *pkt); /* number of keys this interpreter has */ unsigned int key_num; /* keys of this particular interpreter */ Index: ulogd-1.24/libipulog/libipulog.c =================================================================== --- ulogd-1.24.orig/libipulog/libipulog.c 2010-04-06 05:24:25.000000000 +0200 +++ ulogd-1.24/libipulog/libipulog.c 2010-04-06 05:24:35.000000000 +0200 @@ -197,7 +197,7 @@ /* get a pointer to the actual start of the ipulog packet, use this to strip netlink header */ -ulog_packet_msg_t *ipulog_get_packet(struct ipulog_handle *h, +ulog_packet_msg_aligned_t *ipulog_get_packet(struct ipulog_handle *h, const unsigned char *buf, size_t len) { @@ -237,7 +237,52 @@ h->last_nlhdr = nlh; - return NLMSG_DATA(nlh); + /* Convert kernel data to userspace */ + /* FIXME: Check if running kernel is 64bit with 32bit userspace */ +#ifdef __i386__ + static int convert = 0; +#elif __sparc__ + static int convert = 0; +#else + int convert = 1; +#endif + if (convert) { /* 32 -> 32 and 64 -> 64 */ + ulog_packet_msg_t *kernel = NLMSG_DATA(nlh); + ulog_packet_msg_aligned_t *pkg = malloc(sizeof(ulog_packet_msg_aligned_t) + kernel->data_len); + if (pkg == NULL) return NULL; + + pkg->mark = kernel->mark; + pkg->timestamp_sec = kernel->timestamp_sec; + pkg->timestamp_usec = kernel->timestamp_usec; + pkg->hook = kernel->hook; + pkg->indev_name = kernel->indev_name; + pkg->outdev_name = kernel->outdev_name; + pkg->data_len = kernel->data_len; + pkg->prefix = kernel->prefix; + pkg->mac_len = kernel->mac_len; + pkg->mac = kernel->mac; + memcpy(pkg->data[0].raw, kernel->payload, kernel->data_len); + + return pkg; + } else { /* 64 -> 32 */ + ulog_packet_msg64_t *kernel = NLMSG_DATA(nlh); + ulog_packet_msg_aligned_t *pkg = malloc(sizeof(ulog_packet_msg_aligned_t) + kernel->data_len); + if (pkg == NULL) return NULL; + + pkg->mark = kernel->mark; + pkg->timestamp_sec = kernel->timestamp_sec; + pkg->timestamp_usec = kernel->timestamp_usec; + pkg->hook = kernel->hook; + pkg->indev_name = kernel->indev_name; + pkg->outdev_name = kernel->outdev_name; + pkg->data_len = kernel->data_len; + pkg->prefix = kernel->prefix; + pkg->mac_len = kernel->mac_len; + pkg->mac = kernel->mac; + memcpy(pkg->data[0].raw, kernel->payload, kernel->data_len); + + return pkg; + } } /* print a human readable description of the last error to stderr */ Index: ulogd-1.24/libipulog/include/libipulog/libipulog.h =================================================================== --- ulogd-1.24.orig/libipulog/include/libipulog/libipulog.h 2010-04-06 05:24:25.000000000 +0200 +++ ulogd-1.24/libipulog/include/libipulog/libipulog.h 2010-04-06 05:24:30.000000000 +0200 @@ -12,6 +12,7 @@ #include <asm/types.h> #include <linux/netlink.h> #include <net/if.h> +#include <netinet/ip.h> #include <linux/netfilter_ipv4/ipt_ULOG.h> /* FIXME: glibc sucks */ @@ -31,7 +32,42 @@ ssize_t ipulog_read(struct ipulog_handle *h, unsigned char *buf, size_t len, int timeout); -ulog_packet_msg_t *ipulog_get_packet(struct ipulog_handle *h, +/* Format of the ULOG packets passed through netlink from a 64bit kernel to + * 32bit userspace */ +typedef struct ulog_packet_msg64 { + unsigned long long mark; + long long timestamp_sec; + long long timestamp_usec; + unsigned int hook; + char indev_name[IFNAMSIZ]; + char outdev_name[IFNAMSIZ]; + char pad[4]; + unsigned long long data_len; + char prefix[ULOG_PREFIX_LEN]; + unsigned char mac_len; + unsigned char mac[ULOG_MAC_LEN]; + unsigned char payload[0]; +} ulog_packet_msg64_t; + +/* Format of the ULOG packets after conversion */ +typedef struct ulog_packet_msg_aligned { + unsigned long long mark; + long long timestamp_sec; + long long timestamp_usec; + unsigned int hook; + char *indev_name; + char *outdev_name; + size_t data_len; + char *prefix; + unsigned char mac_len; + unsigned char *mac; + union { + unsigned char raw[0]; + struct iphdr iph; + } data[0]; +} ulog_packet_msg_aligned_t; + +ulog_packet_msg_aligned_t *ipulog_get_packet(struct ipulog_handle *h, const unsigned char *buf, size_t len); Index: ulogd-1.24/extensions/ulogd_LOCAL.c =================================================================== --- ulogd-1.24.orig/extensions/ulogd_LOCAL.c 2010-04-06 05:24:25.000000000 +0200 +++ ulogd-1.24/extensions/ulogd_LOCAL.c 2010-04-06 05:24:30.000000000 +0200 @@ -41,7 +41,7 @@ static char hostname[255]; static ulog_iret_t *_interp_local(ulog_interpreter_t *ip, - ulog_packet_msg_t *pkt) + ulog_packet_msg_aligned_t *pkt) { struct timeval tv; ulog_iret_t *ret = ip->result; Index: ulogd-1.24/extensions/ulogd_PWSNIFF.c =================================================================== --- ulogd-1.24.orig/extensions/ulogd_PWSNIFF.c 2010-04-06 05:24:25.000000000 +0200 +++ ulogd-1.24/extensions/ulogd_PWSNIFF.c 2010-04-06 05:24:30.000000000 +0200 @@ -62,9 +62,9 @@ return NULL; } -static ulog_iret_t *_interp_pwsniff(ulog_interpreter_t *ip, ulog_packet_msg_t *pkt) +static ulog_iret_t *_interp_pwsniff(ulog_interpreter_t *ip, ulog_packet_msg_aligned_t *pkt) { - struct iphdr *iph = (struct iphdr *) pkt->payload; + struct iphdr *iph = &pkt->data[0].iph; void *protoh = (u_int32_t *)iph + iph->ihl; struct tcphdr *tcph = protoh; u_int32_t tcplen = ntohs(iph->tot_len) - iph->ihl * 4;