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;

Reply via email to