Skip to content

wrong DCE (__bad_copy_from exists) due to optimization failure under -m32 -fsanitize=alignment fprofile-instr-generate #2120

@kees

Description

@kees

This was originally reported here:
https://lore.kernel.org/all/202508060351.OMeX2wGa-lkp@intel.com/

It appears to be a very fragile state that requires -m32 -fsanitize=alignment fprofile-instr-generate on x86. Given that we have multiple bad states we're seeing with CONFIG_UBSAN_ALIGNMENT, I think we should just explicitly remove that config for x86, but I wanted to capture my attempt to reduce the test case. It's very weird: it requires needless parens to trigger. :|

clang -O2 -std=gnu11 \
    --target=x86_64-linux-gnu -m32 \
    -fprofile-instr-generate \
    -fsanitize=alignment \
    -c -o /dev/null  poc.c

Will emit: error: call to '__bad_copy_from' declared with 'error' attribute: copy source size is too small

(I can't seem to upload files ??, so here's the paste...)

typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned long size_t;
enum {
 false = 0,
 true = 1
};
typedef _Bool bool;

struct sctp_sock {
 __u16 subscribe;
};

struct sctp_event_subscribe {
 __u8 sctp_data_io_event;
 __u8 sctp_association_event;
 __u8 sctp_address_event;
 __u8 sctp_send_failure_event;
 __u8 sctp_peer_error_event;
 __u8 sctp_shutdown_event;
 __u8 sctp_partial_delivery_event;
 __u8 sctp_adaptation_layer_event;
 __u8 sctp_authentication_event;
 __u8 sctp_sender_dry_event;
 __u8 sctp_stream_reset_event;
 __u8 sctp_assoc_reset_event;
 __u8 sctp_stream_change_event;
 __u8 sctp_send_failure_event_event;
};

extern void __attribute__((__error__("copy source size is too small")))
__bad_copy_from(void);

static inline bool
check_copy_size(const void *addr, size_t len)
{
 int sz = __builtin_object_size(addr, 0);
 if (sz >= 0 && sz < len) {
  if (!__builtin_constant_p(len))
   ; /* "len" is NOT builtin constant here, which should be always */
  else
   __bad_copy_from(); /* this can never happen: "len" is not constant */
  return false;
 }
 return true;
}

static inline unsigned long
copy_to_user(void *to, const void *from, unsigned long len)
{
 if (!check_copy_size(from, len))
  return len;
 return 0;
}

extern bool sctp_ulpevent_type_enabled(__u16 subscribe);

extern void weirdo(void *to);

static int sctp_getsockopt_events(struct sctp_sock *s, int len, char *optval)
{
 struct sctp_event_subscribe subscribe;
 __u8 *sn_type = (__u8 *)&subscribe;
 int i;

 if (len == 0)
  return -22;

 if (len > sizeof(struct sctp_event_subscribe))
  len = sizeof(struct sctp_event_subscribe);

 for (i = 0; i < len; i++)
  sn_type[i] = sctp_ulpevent_type_enabled(s->subscribe);

 if (copy_to_user(optval, &subscribe, len))
  return -14;

 return 0;
}

int sctp_getsockopt(struct sctp_sock *sk, char *optval)
{
	int len = 0;

	true ?
		(weirdo(&len))
	     :
		(len = 14);

	return sctp_getsockopt_events(sk, len, optval);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    [ARCH] x86This bug impacts ARCH=i386

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions