diff mbox series

[ulogd2,15/26] input: UNIXSOCK: prevent unaligned pointer access.

Message ID 20211030164432.1140896-16-jeremy@azazel.net
State Changes Requested
Delegated to: Pablo Neira
Headers show
Series Compiler Warning Fixes | expand

Commit Message

Jeremy Sowden Oct. 30, 2021, 4:44 p.m. UTC
`struct ulogd_unixsock_packet_t` is packed, so taking the address of its
`struct iphdr payload` member may yield an unaligned pointer value.
Copy it to a local variable instead.

Remove a couple of stray semicolons.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 input/packet/ulogd_inppkt_UNIXSOCK.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

Comments

Jan Engelhardt Oct. 30, 2021, 5:42 p.m. UTC | #1
On Saturday 2021-10-30 18:44, Jeremy Sowden wrote:

>`struct ulogd_unixsock_packet_t` is packed, so taking the address of its
>`struct iphdr payload` member may yield an unaligned pointer value.

That may not be a problem. Dereferencing through a pointer to
a packed struct generates very pessimistic code even when there is no
padding internally:

» cat >>x.cpp <<-EOF
struct ethhdr { unsigned long long a, b; } __attribute__((packed));
unsigned long f(const struct ethhdr *p) { return p->b; }
EOF
» sparc64-linux-gcc -c x.cpp -O2
» objdump -d x.o
_Z1fPK6ethhdr:
        save %sp, -144, %sp
        stx %i0, [%fp+2039]
        ldx [%fp+2039], %i0
        ldub [%i0+15], %i2
        ldub [%i0+14], %i1
        sllx %i1, 8, %i1
        or %i1, %i2, %i2
        ldub [%i0+13], %i3
...
Jeremy Sowden Nov. 6, 2021, 2:13 p.m. UTC | #2
On 2021-10-30, at 19:42:25 +0200, Jan Engelhardt wrote:
> On Saturday 2021-10-30 18:44, Jeremy Sowden wrote:
> >`struct ulogd_unixsock_packet_t` is packed, so taking the address of its
> >`struct iphdr payload` member may yield an unaligned pointer value.
>
> That may not be a problem. Dereferencing through a pointer to
> a packed struct generates very pessimistic code even when there is no
> padding internally:

Having taken another look at this, I've adopted different approach to
pacify the compiler: the pointer is only actually dereferenced to read
one member (`ip->version`), so I shall replace the local pointer
variable with an `ip_version` variable instead.

J.
diff mbox series

Patch

diff --git a/input/packet/ulogd_inppkt_UNIXSOCK.c b/input/packet/ulogd_inppkt_UNIXSOCK.c
index af2fbeca1f4c..f7611189363c 100644
--- a/input/packet/ulogd_inppkt_UNIXSOCK.c
+++ b/input/packet/ulogd_inppkt_UNIXSOCK.c
@@ -371,7 +371,7 @@  struct ulogd_unixsock_option_t  {
 static int handle_packet(struct ulogd_pluginstance *upi, struct ulogd_unixsock_packet_t *pkt, uint16_t total_len)
 {
 	char *data = NULL;
-	struct iphdr *ip;
+	struct iphdr ip = pkt->payload;
 	struct ulogd_key *ret = upi->output.keys;
 	uint8_t oob_family;
 	uint16_t payload_len;
@@ -387,22 +387,22 @@  static int handle_packet(struct ulogd_pluginstance *upi, struct ulogd_unixsock_p
 
 	payload_len = ntohs(pkt->payload_length);
 
-	ip = &pkt->payload;
-	if (ip->version == 4)
+	if (ip.version == 4)
 		oob_family = AF_INET;
-	else if (ip->version == 6)
+	else if (ip.version == 6)
 		oob_family = AF_INET6;
-	else oob_family = 0;
+	else
+		oob_family = 0;
 
 	okey_set_u8(&ret[UNIXSOCK_KEY_OOB_FAMILY], oob_family);
-	okey_set_ptr(&ret[UNIXSOCK_KEY_RAW_PCKT], ip);
+	okey_set_ptr(&ret[UNIXSOCK_KEY_RAW_PCKT], &ip);
 	okey_set_u32(&ret[UNIXSOCK_KEY_RAW_PCKTLEN], payload_len);
 
 	/* options */
 	if (total_len > payload_len + sizeof(uint16_t)) {
 		/* option starts at the next aligned address after the payload */
 		new_offset = USOCK_ALIGN(payload_len);
-		options_start = (void*)ip + new_offset;
+		options_start = (char *) &ip + new_offset;
 		data = options_start;
 		total_len -= (options_start - (char*)pkt);
 
@@ -460,7 +460,7 @@  static int handle_packet(struct ulogd_pluginstance *upi, struct ulogd_unixsock_p
 						"ulogd2: unknown option %d\n",
 						option_number);
 				break;
-			};
+			}
 		}
 	}
 
@@ -674,7 +674,7 @@  static int unixsock_instance_read_cb(int fd, unsigned int what, void *param)
 		}
 
 		/* handle_packet has shifted data in buffer */
-	};
+	}
 
 	return 0;
 }